mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
Power management fixes for 6.10-rc1
- Fix a memory leak in the exit path of amd-pstate (Peng Ma). - Fix required_opp_tables handling in the cases when multiple generic PM domains share one OPP table (Viresh Kumar). -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEE4fcc61cGeeHD/fCwgsRv/nhiVHEFAmZMYk8SHHJqd0Byand5 c29ja2kubmV0AAoJEILEb/54YlRxdUIP/31SNqWSNni7aiUirnMIg60UbpM3jTMm apkqHaSqdpL4ExM/Y8caSL9rIQD3P1GhWHy+0JVuK5tNiFH84oyMmKYd0v01QVy/ DLDs55XpPAgbkEjCcloe3QaR8mWgnQIXatjQkVoXZu3LAH6QLnDzT5w7C4HFXFEL 4gVlBvM/S69pf6FBG0SZhKLON3zryGHCBQMqOFcowJ8QGnfQsC+YzEWwvyncsDv4 nFV/lje/LwARlsxUfjc7EZmf8tRtfgkgSFm+3pI/EtQikKwI0ttheF8eE4MEtpxe 0A3xCV1aDq+tQEXgU7IIqVvsuu5xOcdfJ3rfYm5GmgZSh1RU1b80S7MJPWBJn0ip PTjVZ3UyaW+YhGw5br2uXWK427PRhPHUyfCPO1UiSSDu0qZPNNHIjv5RQk336Sbt NQUl7XO45Lv5XwGq8uqCXxnxN8LaNiOd+JZ6xm3R34Pc/vR6zEptOc/748WS2cxV O2h1F6u0MiFqP9ieTcY23anrZqU//a61P8xz9e6oRfieUylOExG/aAsNrZ9Q2J6Z T9mMj9OQlcbXIu7X2Ai6Fn3ppWR8/rVJu2i2WwrsGYkdnWuJ3BqdMOpnKw1438bb 2AC2Pc0hC22p8/tpqckcwSHJOOYCynOc7y/2/X7skcY+jkXg5zhPtBCx3GhCsEjV RUj9L2CTorvS =mGfT -----END PGP SIGNATURE----- Merge tag 'pm-6.10-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm Pull power management fixes from Rafael Wysocki: "These fix the amd-pstate driver and the operating performance point (OPP) handling related to generic PM domains. Specifics: - Fix a memory leak in the exit path of amd-pstate (Peng Ma) - Fix required_opp_tables handling in the cases when multiple generic PM domains share one OPP table (Viresh Kumar)" * tag 'pm-6.10-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: OPP: Fix required_opp_tables for multiple genpds using same table cpufreq: amd-pstate: fix memory leak on CPU EPP exit
This commit is contained in:
commit
98f312bc58
@ -1441,6 +1441,13 @@ free_cpudata1:
|
||||
|
||||
static int amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
|
||||
if (cpudata) {
|
||||
kfree(cpudata);
|
||||
policy->driver_data = NULL;
|
||||
}
|
||||
|
||||
pr_debug("CPU %d exiting\n", policy->cpu);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2394,7 +2394,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;
|
||||
|
||||
@ -2427,6 +2428,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.
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -260,6 +260,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);
|
||||
@ -307,6 +308,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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user