mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-28 16:56:26 +00:00
pmdomain: Merge branch fixes into next
Merge the pmdomain fixes for v6.12-rc[n] into the next branch, to allow them to get tested together with the new changes that are targeted for v6.13. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
commit
cc8eeff3e8
@ -125,7 +125,8 @@ static int scmi_perf_domain_probe(struct scmi_device *sdev)
|
||||
scmi_pd->ph = ph;
|
||||
scmi_pd->genpd.name = scmi_pd->info->name;
|
||||
scmi_pd->genpd.flags = GENPD_FLAG_ALWAYS_ON |
|
||||
GENPD_FLAG_OPP_TABLE_FW;
|
||||
GENPD_FLAG_OPP_TABLE_FW |
|
||||
GENPD_FLAG_DEV_NAME_FW;
|
||||
scmi_pd->genpd.set_performance_state = scmi_pd_set_perf_state;
|
||||
scmi_pd->genpd.attach_dev = scmi_pd_attach_dev;
|
||||
scmi_pd->genpd.detach_dev = scmi_pd_detach_dev;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#define pr_fmt(fmt) "PM: " fmt
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
@ -23,6 +24,9 @@
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
/* Provides a unique ID for each genpd device */
|
||||
static DEFINE_IDA(genpd_ida);
|
||||
|
||||
#define GENPD_RETRY_MAX_MS 250 /* Approximate */
|
||||
|
||||
#define GENPD_DEV_CALLBACK(genpd, type, callback, dev) \
|
||||
@ -171,6 +175,7 @@ static const struct genpd_lock_ops genpd_raw_spin_ops = {
|
||||
#define genpd_is_cpu_domain(genpd) (genpd->flags & GENPD_FLAG_CPU_DOMAIN)
|
||||
#define genpd_is_rpm_always_on(genpd) (genpd->flags & GENPD_FLAG_RPM_ALWAYS_ON)
|
||||
#define genpd_is_opp_table_fw(genpd) (genpd->flags & GENPD_FLAG_OPP_TABLE_FW)
|
||||
#define genpd_is_dev_name_fw(genpd) (genpd->flags & GENPD_FLAG_DEV_NAME_FW)
|
||||
|
||||
static inline bool irq_safe_dev_in_sleep_domain(struct device *dev,
|
||||
const struct generic_pm_domain *genpd)
|
||||
@ -189,7 +194,7 @@ static inline bool irq_safe_dev_in_sleep_domain(struct device *dev,
|
||||
|
||||
if (ret)
|
||||
dev_warn_once(dev, "PM domain %s will not be powered off\n",
|
||||
genpd->name);
|
||||
dev_name(&genpd->dev));
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -274,7 +279,7 @@ static void genpd_debug_remove(struct generic_pm_domain *genpd)
|
||||
if (!genpd_debugfs_dir)
|
||||
return;
|
||||
|
||||
debugfs_lookup_and_remove(genpd->name, genpd_debugfs_dir);
|
||||
debugfs_lookup_and_remove(dev_name(&genpd->dev), genpd_debugfs_dir);
|
||||
}
|
||||
|
||||
static void genpd_update_accounting(struct generic_pm_domain *genpd)
|
||||
@ -731,7 +736,7 @@ static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed)
|
||||
genpd->states[state_idx].power_on_latency_ns = elapsed_ns;
|
||||
genpd->gd->max_off_time_changed = true;
|
||||
pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n",
|
||||
genpd->name, "on", elapsed_ns);
|
||||
dev_name(&genpd->dev), "on", elapsed_ns);
|
||||
|
||||
out:
|
||||
raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL);
|
||||
@ -782,7 +787,7 @@ static int _genpd_power_off(struct generic_pm_domain *genpd, bool timed)
|
||||
genpd->states[state_idx].power_off_latency_ns = elapsed_ns;
|
||||
genpd->gd->max_off_time_changed = true;
|
||||
pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n",
|
||||
genpd->name, "off", elapsed_ns);
|
||||
dev_name(&genpd->dev), "off", elapsed_ns);
|
||||
|
||||
out:
|
||||
raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF,
|
||||
@ -1941,7 +1946,7 @@ int dev_pm_genpd_add_notifier(struct device *dev, struct notifier_block *nb)
|
||||
|
||||
if (ret) {
|
||||
dev_warn(dev, "failed to add notifier for PM domain %s\n",
|
||||
genpd->name);
|
||||
dev_name(&genpd->dev));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1988,7 +1993,7 @@ int dev_pm_genpd_remove_notifier(struct device *dev)
|
||||
|
||||
if (ret) {
|
||||
dev_warn(dev, "failed to remove notifier for PM domain %s\n",
|
||||
genpd->name);
|
||||
dev_name(&genpd->dev));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2014,7 +2019,7 @@ static int genpd_add_subdomain(struct generic_pm_domain *genpd,
|
||||
*/
|
||||
if (!genpd_is_irq_safe(genpd) && genpd_is_irq_safe(subdomain)) {
|
||||
WARN(1, "Parent %s of subdomain %s must be IRQ safe\n",
|
||||
genpd->name, subdomain->name);
|
||||
dev_name(&genpd->dev), subdomain->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -2089,7 +2094,7 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
|
||||
|
||||
if (!list_empty(&subdomain->parent_links) || subdomain->device_count) {
|
||||
pr_warn("%s: unable to remove subdomain %s\n",
|
||||
genpd->name, subdomain->name);
|
||||
dev_name(&genpd->dev), subdomain->name);
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
@ -2226,6 +2231,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
|
||||
genpd->status = is_off ? GENPD_STATE_OFF : GENPD_STATE_ON;
|
||||
genpd->device_count = 0;
|
||||
genpd->provider = NULL;
|
||||
genpd->device_id = -ENXIO;
|
||||
genpd->has_provider = false;
|
||||
genpd->accounting_time = ktime_get_mono_fast_ns();
|
||||
genpd->domain.ops.runtime_suspend = genpd_runtime_suspend;
|
||||
@ -2266,7 +2272,18 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
|
||||
return ret;
|
||||
|
||||
device_initialize(&genpd->dev);
|
||||
dev_set_name(&genpd->dev, "%s", genpd->name);
|
||||
|
||||
if (!genpd_is_dev_name_fw(genpd)) {
|
||||
dev_set_name(&genpd->dev, "%s", genpd->name);
|
||||
} else {
|
||||
ret = ida_alloc(&genpd_ida, GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
put_device(&genpd->dev);
|
||||
return ret;
|
||||
}
|
||||
genpd->device_id = ret;
|
||||
dev_set_name(&genpd->dev, "%s_%u", genpd->name, genpd->device_id);
|
||||
}
|
||||
|
||||
mutex_lock(&gpd_list_lock);
|
||||
list_add(&genpd->gpd_list_node, &gpd_list);
|
||||
@ -2288,13 +2305,13 @@ static int genpd_remove(struct generic_pm_domain *genpd)
|
||||
|
||||
if (genpd->has_provider) {
|
||||
genpd_unlock(genpd);
|
||||
pr_err("Provider present, unable to remove %s\n", genpd->name);
|
||||
pr_err("Provider present, unable to remove %s\n", dev_name(&genpd->dev));
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!list_empty(&genpd->parent_links) || genpd->device_count) {
|
||||
genpd_unlock(genpd);
|
||||
pr_err("%s: unable to remove %s\n", __func__, genpd->name);
|
||||
pr_err("%s: unable to remove %s\n", __func__, dev_name(&genpd->dev));
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@ -2308,9 +2325,11 @@ static int genpd_remove(struct generic_pm_domain *genpd)
|
||||
genpd_unlock(genpd);
|
||||
genpd_debug_remove(genpd);
|
||||
cancel_work_sync(&genpd->power_off_work);
|
||||
if (genpd->device_id != -ENXIO)
|
||||
ida_free(&genpd_ida, genpd->device_id);
|
||||
genpd_free_data(genpd);
|
||||
|
||||
pr_debug("%s: removed %s\n", __func__, genpd->name);
|
||||
pr_debug("%s: removed %s\n", __func__, dev_name(&genpd->dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3320,12 +3339,12 @@ static int genpd_summary_one(struct seq_file *s,
|
||||
else
|
||||
snprintf(state, sizeof(state), "%s",
|
||||
status_lookup[genpd->status]);
|
||||
seq_printf(s, "%-30s %-30s %u", genpd->name, state, genpd->performance_state);
|
||||
seq_printf(s, "%-30s %-30s %u", dev_name(&genpd->dev), state, genpd->performance_state);
|
||||
|
||||
/*
|
||||
* Modifications on the list require holding locks on both
|
||||
* parent and child, so we are safe.
|
||||
* Also genpd->name is immutable.
|
||||
* Also the device name is immutable.
|
||||
*/
|
||||
list_for_each_entry(link, &genpd->parent_links, parent_node) {
|
||||
if (list_is_first(&link->parent_node, &genpd->parent_links))
|
||||
@ -3550,7 +3569,7 @@ static void genpd_debug_add(struct generic_pm_domain *genpd)
|
||||
if (!genpd_debugfs_dir)
|
||||
return;
|
||||
|
||||
d = debugfs_create_dir(genpd->name, genpd_debugfs_dir);
|
||||
d = debugfs_create_dir(dev_name(&genpd->dev), genpd_debugfs_dir);
|
||||
|
||||
debugfs_create_file("current_state", 0444,
|
||||
d, genpd, &status_fops);
|
||||
|
@ -100,6 +100,10 @@ struct dev_pm_domain_list {
|
||||
* GENPD_FLAG_OPP_TABLE_FW: The genpd provider supports performance states,
|
||||
* but its corresponding OPP tables are not
|
||||
* described in DT, but are given directly by FW.
|
||||
*
|
||||
* GENPD_FLAG_DEV_NAME_FW: Instructs genpd to generate an unique device name
|
||||
* using ida. It is used by genpd providers which
|
||||
* get their genpd-names directly from FW.
|
||||
*/
|
||||
#define GENPD_FLAG_PM_CLK (1U << 0)
|
||||
#define GENPD_FLAG_IRQ_SAFE (1U << 1)
|
||||
@ -109,6 +113,7 @@ struct dev_pm_domain_list {
|
||||
#define GENPD_FLAG_RPM_ALWAYS_ON (1U << 5)
|
||||
#define GENPD_FLAG_MIN_RESIDENCY (1U << 6)
|
||||
#define GENPD_FLAG_OPP_TABLE_FW (1U << 7)
|
||||
#define GENPD_FLAG_DEV_NAME_FW (1U << 8)
|
||||
|
||||
enum gpd_status {
|
||||
GENPD_STATE_ON = 0, /* PM domain is on */
|
||||
@ -171,6 +176,7 @@ struct generic_pm_domain {
|
||||
atomic_t sd_count; /* Number of subdomains with power "on" */
|
||||
enum gpd_status status; /* Current state of the domain */
|
||||
unsigned int device_count; /* Number of devices */
|
||||
unsigned int device_id; /* unique device id */
|
||||
unsigned int suspended_count; /* System suspend device counter */
|
||||
unsigned int prepared_count; /* Suspend counter of prepared devices */
|
||||
unsigned int performance_state; /* Aggregated max performance state */
|
||||
|
Loading…
Reference in New Issue
Block a user