public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Viresh Kumar <viresh.kumar@linaro.org>,
	Thorsten Leemhuis <regressions@leemhuis.info>,
	Vladimir Lypak <vladimir.lypak@gmail.com>,
	Ulf Hansson <ulf.hansson@linaro.org>,
	Sasha Levin <sashal@kernel.org>,
	vireshk@kernel.org, nm@ti.com, sboyd@kernel.org,
	rafael@kernel.org, linux-pm@vger.kernel.org
Subject: [PATCH AUTOSEL 6.8 24/24] OPP: Fix required_opp_tables for multiple genpds using same table
Date: Wed,  5 Jun 2024 07:50:34 -0400	[thread overview]
Message-ID: <20240605115101.2962372-24-sashal@kernel.org> (raw)
In-Reply-To: <20240605115101.2962372-1-sashal@kernel.org>

From: Viresh Kumar <viresh.kumar@linaro.org>

[ Upstream commit 2a56c462fe5a2ee61d38e2d7b772bee56115a00c ]

The required_opp_tables parsing is not perfect, as the OPP core does the
parsing solely based on the DT node pointers.

The core sets the required_opp_tables entry to the first OPP table in
the "opp_tables" list, that matches with the node pointer.

If the target DT OPP table is used by multiple devices and they all
create separate instances of 'struct opp_table' from it, then it is
possible that the required_opp_tables entry may be set to the incorrect
sibling device.

Unfortunately, there is no clear way to initialize the right values
during the initial parsing and we need to do this at a later point of
time.

Cross check the OPP table again while the genpds are attached and fix
them if required.

Also add a new API for the genpd core to fetch the device pointer for
the genpd.

Cc: Thorsten Leemhuis <regressions@leemhuis.info>
Reported-by: Vladimir Lypak <vladimir.lypak@gmail.com>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218682
Co-developed-by: Vladimir Lypak <vladimir.lypak@gmail.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/opp/core.c        | 31 ++++++++++++++++++++++++++++++-
 drivers/pmdomain/core.c   | 10 ++++++++++
 include/linux/pm_domain.h |  6 ++++++
 3 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index c4e0432ae42a0..3f02deba4aef6 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -2393,7 +2393,8 @@ static void _opp_detach_genpd(struct opp_table *opp_table)
 static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev,
 			const char * const *names, struct device ***virt_devs)
 {
-	struct device *virt_dev;
+	struct device *virt_dev, *gdev;
+	struct opp_table *genpd_table;
 	int index = 0, ret = -EINVAL;
 	const char * const *name = names;
 
@@ -2426,6 +2427,34 @@ static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev,
 			goto err;
 		}
 
+		/*
+		 * The required_opp_tables parsing is not perfect, as the OPP
+		 * core does the parsing solely based on the DT node pointers.
+		 * The core sets the required_opp_tables entry to the first OPP
+		 * table in the "opp_tables" list, that matches with the node
+		 * pointer.
+		 *
+		 * If the target DT OPP table is used by multiple devices and
+		 * they all create separate instances of 'struct opp_table' from
+		 * it, then it is possible that the required_opp_tables entry
+		 * may be set to the incorrect sibling device.
+		 *
+		 * Cross check it again and fix if required.
+		 */
+		gdev = dev_to_genpd_dev(virt_dev);
+		if (IS_ERR(gdev))
+			return PTR_ERR(gdev);
+
+		genpd_table = _find_opp_table(gdev);
+		if (!IS_ERR(genpd_table)) {
+			if (genpd_table != opp_table->required_opp_tables[index]) {
+				dev_pm_opp_put_opp_table(opp_table->required_opp_tables[index]);
+				opp_table->required_opp_tables[index] = genpd_table;
+			} else {
+				dev_pm_opp_put_opp_table(genpd_table);
+			}
+		}
+
 		/*
 		 * Add the virtual genpd device as a user of the OPP table, so
 		 * we can call dev_pm_opp_set_opp() on it directly.
diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c
index 18e232b5ed53d..755e4d0c63224 100644
--- a/drivers/pmdomain/core.c
+++ b/drivers/pmdomain/core.c
@@ -184,6 +184,16 @@ static struct generic_pm_domain *dev_to_genpd(struct device *dev)
 	return pd_to_genpd(dev->pm_domain);
 }
 
+struct device *dev_to_genpd_dev(struct device *dev)
+{
+	struct generic_pm_domain *genpd = dev_to_genpd(dev);
+
+	if (IS_ERR(genpd))
+		return ERR_CAST(genpd);
+
+	return &genpd->dev;
+}
+
 static int genpd_stop_dev(const struct generic_pm_domain *genpd,
 			  struct device *dev)
 {
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index b97c5e9820f97..0e18088af392d 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -233,6 +233,7 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 int pm_genpd_init(struct generic_pm_domain *genpd,
 		  struct dev_power_governor *gov, bool is_off);
 int pm_genpd_remove(struct generic_pm_domain *genpd);
+struct device *dev_to_genpd_dev(struct device *dev);
 int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state);
 int dev_pm_genpd_add_notifier(struct device *dev, struct notifier_block *nb);
 int dev_pm_genpd_remove_notifier(struct device *dev);
@@ -280,6 +281,11 @@ static inline int pm_genpd_remove(struct generic_pm_domain *genpd)
 	return -EOPNOTSUPP;
 }
 
+static inline struct device *dev_to_genpd_dev(struct device *dev)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
 static inline int dev_pm_genpd_set_performance_state(struct device *dev,
 						     unsigned int state)
 {
-- 
2.43.0


      parent reply	other threads:[~2024-06-05 11:52 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-05 11:50 [PATCH AUTOSEL 6.8 01/24] usb: gadget: uvc: configfs: ensure guid to be valid before set Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 02/24] f2fs: remove clear SB_INLINECRYPT flag in default_options Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 03/24] usb: typec: ucsi_glink: rework quirks implementation Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 04/24] usb: misc: uss720: check for incompatible versions of the Belkin F5U002 Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 05/24] Avoid hw_desc array overrun in dw-axi-dmac Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 06/24] usb: dwc3: pci: Don't set "linux,phy_charger_detect" property on Lenovo Yoga Tab2 1380 Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 07/24] usb: typec: ucsi_glink: drop special handling for CCI_BUSY Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 08/24] udf: udftime: prevent overflow in udf_disk_stamp_to_time() Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 09/24] PCI/PM: Avoid D3cold for HP Pavilion 17 PC/1972 PCIe Ports Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 10/24] f2fs: don't set RO when shutting down f2fs Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 11/24] MIPS: Octeon: Add PCIe link status check Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 12/24] serial: imx: Introduce timeout when waiting on transmitter empty Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 13/24] serial: exar: adding missing CTI and Exar PCI ids Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 14/24] usb: gadget: function: Remove usage of the deprecated ida_simple_xx() API Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 15/24] usb: dwc3: core: Access XHCI address space temporarily to read port info Sasha Levin
2024-06-05 11:54   ` Johan Hovold
2024-07-22 12:56     ` Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 16/24] f2fs: fix to do sanity check on i_xattr_nid in sanity_check_inode() Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 17/24] tty: add the option to have a tty reject a new ldisc Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 18/24] greybus: Fix use-after-free bug in gb_interface_release due to race condition Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 19/24] cxl: Add post-reset warning if reset results in loss of previously committed HDM decoders Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 20/24] vfio/pci: Collect hot-reset devices to local buffer Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 21/24] cpufreq: amd-pstate: fix memory leak on CPU EPP exit Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 22/24] ACPI: EC: Install address space handler at the namespace root Sasha Levin
2024-06-05 11:50 ` [PATCH AUTOSEL 6.8 23/24] PCI: Do not wait for disconnected devices when resuming Sasha Levin
2024-06-05 11:50 ` Sasha Levin [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240605115101.2962372-24-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=nm@ti.com \
    --cc=rafael@kernel.org \
    --cc=regressions@leemhuis.info \
    --cc=sboyd@kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=ulf.hansson@linaro.org \
    --cc=viresh.kumar@linaro.org \
    --cc=vireshk@kernel.org \
    --cc=vladimir.lypak@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox