From nobody Thu Apr 9 17:59:08 2026 Received: from mail-lj1-f177.google.com (mail-lj1-f177.google.com [209.85.208.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C4FA4423A8E for ; Tue, 3 Mar 2026 13:23:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772544214; cv=none; b=V1sOhEYI0AJPDIi3kIxUZb1dY8qnLQlxMIh1M5dgDa330JMLGn9fwqfL6DLMgBWgaHjaPurS9weooMsWgS9Hc/y1PoZOAJ9n8vUmcIDn2y8VRKeaVbkZWWwxRHmjmHYg25hU0fR5P0nKDiksgCWzac8vU7dpFr38jMA1wVDbm3g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772544214; c=relaxed/simple; bh=KqwRlC6a0mFJBPkblfsKOEZY7P0vlTLRhRY9ZzoVEss=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tZBL5xt3LHDNOAcn7T4SbwhwUVNOekAbhMeI62L11H8Eu+KjD/jBXky1SbpiPdCTs3IKjnRMLNg42P4nYdUpzbEBCihWZeyAmH829xKsEDO65A8TY4kdO+APyX4K0oqcuFwDZnQn5Z3xYi5+CAF+Z9X6hpQPKQCCLf73DXjsSsE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=ebZgW3Nr; arc=none smtp.client-ip=209.85.208.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="ebZgW3Nr" Received: by mail-lj1-f177.google.com with SMTP id 38308e7fff4ca-389e71756d8so104816461fa.2 for ; Tue, 03 Mar 2026 05:23:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1772544210; x=1773149010; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=4SAiIzSfTMRShdXJxCInhMGpqoMCKhmfdktkL1GCb0E=; b=ebZgW3Nrqb81MdqiZgEgQPDhRcCC42qgUPPd+lzVy0DpJfbQjs2pSh+O9MMJem0h/+ 8nxIyUw6cp+7tb0lNMGGXJXJjbpjer3TtuHU/+ahnqLkqG57iQa8NL+GKwwWFvPBrPYq n0S3c9Js+EqHXNB9CQ3g0GpA0SyU/J3B+810GnsfE6a9OiaMe2ZkcjAiQGrv2SCJ/Nqn vcpz1q+WPztpWZL01CeiJXSA45MvD3CUIjiQrPdWFjzD5/I9PpIFZkIPEDPojX9F19X8 0IlvyIzbCCSNt7l6OP5RSTv9sYbQP98nsDB6Yzmcrggdrsssr1JE1dQlexGipyAUHum5 jitA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772544210; x=1773149010; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=4SAiIzSfTMRShdXJxCInhMGpqoMCKhmfdktkL1GCb0E=; b=gyDR1Bqrt9qFBeVSgAJlYflUVo8kW0syoPIwykc8oxXR/sJuA4/3+6tfomY//Ysx2h ryt+6PQqDP2RubUHj7iObmwlp9UB5mc2aZMRjiM1UaPZFzq0h8eIutTZzxWl9QVkBXQ+ zrlziGW8BNTjb+bws+6d3f79hkrImcAVhTA1lecAjIqycIP4qQA3MAba6YeXaiGXjWDd ldawW6TPtP2v+VsTEzhzKw2gGR5ubhaADL/yiwi3qPw9ukdURZ2rayW80xNi7MoUZN3U Em2mmkhv5y8BKSbK4NLW+wtChFSoM3yYx2nwfYo2dRmNmf/8hf5Z7dYpqe3U16Kj+zSa CERg== X-Forwarded-Encrypted: i=1; AJvYcCW3G1YxCwB4/sVJDhPQai3m0ckcfuOo3nuvKzhsQNxLXHSdDRETfbL81MveXhr9F0vATkz1oetIQ05wPbk=@vger.kernel.org X-Gm-Message-State: AOJu0YxHmRA6fSqk0oVkjFrrsP3g3AtiYWhhbz9q9vmFY2j3UQM/ccvK /QYrnrklqqf5Zsrdf1iEkrSXlK9jYy9Asj6O8USyiCzS/X4qi1KmdRJ+MP0gxC7Gteo= X-Gm-Gg: ATEYQzxZ6EmPRn61maeBZdvEcdz40qUbPUl9ReQo1shOPxkJw60if+HnSrUE+2aSOCH 33dLa9+/XMaURS2O6z7F0HPXPzadUMGNvGRgNJl7ZnG6rZy7jFzsmUomZbPzoga3Wz++MjvmDmS vEiHc8TiftB2GewchqkWPPNT31Ye2+xpQ6M/KqhfwoLIl9Ne3JigzvmSwIPrjxtNy8W2fb1VGw0 GOahQnyBGHcVAOJU7Ggh4l45R1bgFRDcLsP6AyGwNTtE1H+jhL3NwFWiQ1u2rAdLmwlCVUnJtf1 3ec6L7KCFSQyrqvF+OgLvMF1JORRwtjczg/49YJEKN7IBAqL1F+tkmvX/ddsWP64zC1TG6pQ0z6 U08DTDG6LUfgDlhehEORUVVSySRGElkJnrC3/cnbte8Nv9oQJoZvAqy7mkn1FqMeHhd6i2xrq0H 6bvB3KxnmwqkdT/pmlbT44NiIajJggloAXhz+0tt3PfyPZHfxmQdpN0hP8Hu/4m+3cLajLC4+V X-Received: by 2002:a05:651c:1c7:b0:387:17e6:1dd9 with SMTP id 38308e7fff4ca-389ff34cc65mr108309141fa.23.1772544209839; Tue, 03 Mar 2026 05:23:29 -0800 (PST) Received: from uffe-tuxpro14.. (h-178-174-189-39.A498.priv.bahnhof.se. [178.174.189.39]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5a1235811e3sm587866e87.29.2026.03.03.05.23.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 03 Mar 2026 05:23:29 -0800 (PST) From: Ulf Hansson To: Saravana Kannan , "Rafael J . Wysocki" , Greg Kroah-Hartman , linux-pm@vger.kernel.org Cc: Kevin Hilman , Stephen Boyd , Marek Szyprowski , Bjorn Andersson , Abel Vesa , Peng Fan , Tomi Valkeinen , Maulik Shah , Konrad Dybcio , Thierry Reding , Jonathan Hunter , Geert Uytterhoeven , Dmitry Baryshkov , Ulf Hansson , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/9] pmdomain: core: Add initial fine grained sync_state support Date: Tue, 3 Mar 2026 14:22:50 +0100 Message-ID: <20260303132305.438657-5-ulf.hansson@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260303132305.438657-1-ulf.hansson@linaro.org> References: <20260303132305.438657-1-ulf.hansson@linaro.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" A onecell (#power-domain-cells =3D <1 or 2>; in DT) power domain provider typically provides multiple independent power domains, each with their own corresponding consumers. In these cases we have to wait for all consumers for all the provided power domains before the ->sync_state() callback gets called for the supplier. In a first step to improve this, let's implement support for fine grained sync_state support a per genpd basis by using the ->queue_sync_state() callback. To take step by step, let's initially limit the improvement to the internal genpd provider driver and to its corresponding genpd devices for onecell providers. Signed-off-by: Ulf Hansson --- drivers/pmdomain/core.c | 128 ++++++++++++++++++++++++++++++++++++++ include/linux/pm_domain.h | 1 + 2 files changed, 129 insertions(+) diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c index ad57846f02a3..53401db2a386 100644 --- a/drivers/pmdomain/core.c +++ b/drivers/pmdomain/core.c @@ -2699,6 +2699,123 @@ static struct generic_pm_domain *genpd_get_from_pro= vider( return genpd; } =20 +static bool genpd_should_wait_for_consumer(struct device_node *np) +{ + struct generic_pm_domain *genpd; + bool should_wait =3D false; + + mutex_lock(&gpd_list_lock); + list_for_each_entry(genpd, &gpd_list, gpd_list_node) { + if (genpd->provider =3D=3D of_fwnode_handle(np)) { + genpd_lock(genpd); + + /* Clear the previous state before reevaluating. */ + genpd->wait_for_consumer =3D false; + + /* + * Unless there is at least one genpd for the provider + * that is being kept powered-on, we don't have to care + * about waiting for consumers. + */ + if (genpd->stay_on) + should_wait =3D true; + + genpd_unlock(genpd); + } + } + mutex_unlock(&gpd_list_lock); + + return should_wait; +} + +static void genpd_parse_for_consumer(struct device_node *sup, + struct device_node *con) +{ + struct generic_pm_domain *genpd; + int i; + + for (i =3D 0; ; i++) { + struct of_phandle_args pd_args; + + if (of_parse_phandle_with_args(con, "power-domains", + "#power-domain-cells", + i, &pd_args)) + break; + + /* + * The phandle must correspond to the supplier's genpd provider + * to be relevant else let's move to the next index. + */ + if (sup !=3D pd_args.np) { + of_node_put(pd_args.np); + continue; + } + + mutex_lock(&gpd_list_lock); + genpd =3D genpd_get_from_provider(&pd_args); + if (!IS_ERR(genpd)) { + genpd_lock(genpd); + genpd->wait_for_consumer =3D true; + genpd_unlock(genpd); + } + mutex_unlock(&gpd_list_lock); + + of_node_put(pd_args.np); + } +} + +static void _genpd_queue_sync_state(struct device_node *np) +{ + struct generic_pm_domain *genpd; + + mutex_lock(&gpd_list_lock); + list_for_each_entry(genpd, &gpd_list, gpd_list_node) { + if (genpd->provider =3D=3D of_fwnode_handle(np)) { + genpd_lock(genpd); + if (genpd->stay_on && !genpd->wait_for_consumer) { + genpd->stay_on =3D false; + genpd_queue_power_off_work(genpd); + } + genpd_unlock(genpd); + } + } + mutex_unlock(&gpd_list_lock); +} + +static void genpd_queue_sync_state(struct device *dev) +{ + struct device_node *np =3D dev->of_node; + struct device_link *link; + + if (!genpd_should_wait_for_consumer(np)) + return; + + list_for_each_entry(link, &dev->links.consumers, s_node) { + struct device *consumer =3D link->consumer; + + pr_info("%s:%s con=3D%s\n", __func__, dev_name(dev), + dev_name(consumer)); + + if (!device_link_test(link, DL_FLAG_MANAGED)) + continue; + + if (link->status =3D=3D DL_STATE_ACTIVE) + continue; + + if (!consumer->of_node) + continue; + + /* + * A consumer device has not been probed yet. Let's parse its + * device node for the power-domains property, to find out the + * genpds it may belong to and then prevent sync state for them. + */ + genpd_parse_for_consumer(np, consumer->of_node); + } + + _genpd_queue_sync_state(np); +} + static void genpd_sync_state(struct device *dev) { return of_genpd_sync_state(dev->of_node); @@ -3531,6 +3648,16 @@ static int genpd_provider_probe(struct device *dev) return 0; } =20 +static void genpd_provider_queue_sync_state(struct device *dev) +{ + struct generic_pm_domain *genpd =3D container_of(dev, struct generic_pm_d= omain, dev); + + if (genpd->sync_state !=3D GENPD_SYNC_STATE_ONECELL) + return; + + genpd_queue_sync_state(dev); +} + static void genpd_provider_sync_state(struct device *dev) { struct generic_pm_domain *genpd =3D container_of(dev, struct generic_pm_d= omain, dev); @@ -3559,6 +3686,7 @@ static struct device_driver genpd_provider_drv =3D { .name =3D "genpd_provider", .bus =3D &genpd_provider_bus_type, .probe =3D genpd_provider_probe, + .queue_sync_state =3D genpd_provider_queue_sync_state, .sync_state =3D genpd_provider_sync_state, .suppress_bind_attrs =3D true, }; diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index b299dc0128d6..7aa49721cde5 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -215,6 +215,7 @@ struct generic_pm_domain { cpumask_var_t cpus; /* A cpumask of the attached CPUs */ bool synced_poweroff; /* A consumer needs a synced poweroff */ bool stay_on; /* Stay powered-on during boot. */ + bool wait_for_consumer; /* Consumers awaits to be probed. */ enum genpd_sync_state sync_state; /* How sync_state is managed. */ int (*power_off)(struct generic_pm_domain *domain); int (*power_on)(struct generic_pm_domain *domain); --=20 2.43.0