mirror of
https://github.com/torvalds/linux.git
synced 2026-07-29 10:41:49 +02:00
coresight: Move CPU hotplug callbacks to core layer
This commit moves CPU hotplug callbacks from ETMv4 driver to core layer. The motivation is the core layer can control all components on an activated path rather but not only managing tracer in ETMv4 driver. The perf event layer will disable CoreSight PMU event 'cs_etm' when hotplug off a CPU. That means a perf mode will be always converted to disabled mode in CPU hotplug. Arm CoreSight CPU hotplug callbacks only need to handle the Sysfs mode and ignore the perf mode. Add a 'mode' argument to coresight_pm_get_active_path() so it only returns active paths for the relevant mode. Define the enum with bit flags so it is safe for bitwise operations. Change CPUHP_AP_ARM_CORESIGHT_STARTING to CPUHP_AP_ARM_CORESIGHT_ONLINE so that the CPU hotplug callback runs in the online state and thread context, allowing coresight_disable_sysfs() to be called directly to disable the path. Tested-by: James Clark <james.clark@linaro.org> Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com> Reviewed-by: James Clark <james.clark@linaro.org> Tested-by: Jie Gan <jie.gan@oss.qualcomm.com> Signed-off-by: Leo Yan <leo.yan@arm.com> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> Link: https://lore.kernel.org/r/20260515-arm_coresight_path_power_management_improvement-v14-27-f88c4a3ecfe9@arm.com
This commit is contained in:
parent
bf64b06ede
commit
7105d2aa76
|
|
@ -1847,7 +1847,7 @@ static void coresight_release_device_list(void)
|
|||
}
|
||||
}
|
||||
|
||||
static struct coresight_path *coresight_cpu_get_active_path(void)
|
||||
static struct coresight_path *coresight_cpu_get_active_path(enum cs_mode mode)
|
||||
{
|
||||
struct coresight_device *source;
|
||||
bool is_active = false;
|
||||
|
|
@ -1856,17 +1856,17 @@ static struct coresight_path *coresight_cpu_get_active_path(void)
|
|||
if (!source)
|
||||
return NULL;
|
||||
|
||||
if (coresight_get_mode(source) != CS_MODE_DISABLED)
|
||||
if (coresight_get_mode(source) & mode)
|
||||
is_active = true;
|
||||
|
||||
coresight_put_percpu_source_ref(source);
|
||||
|
||||
/*
|
||||
* It is expected to run in atomic context, so it cannot be preempted
|
||||
* to disable the path. Here returns the active path pointer without
|
||||
* concern that its state may change. Since the build path has taken
|
||||
* a reference on the component, the path can be safely used by the
|
||||
* caller.
|
||||
* It is expected to run in atomic context or with the CPU lock held for
|
||||
* sysfs mode, so it cannot be preempted to disable the path. Here
|
||||
* returns the active path pointer without concern that its state may
|
||||
* change. Since the build path has taken a reference on the component,
|
||||
* the path can be safely used by the caller.
|
||||
*/
|
||||
return is_active ? source->path : NULL;
|
||||
}
|
||||
|
|
@ -1985,7 +1985,8 @@ static void coresight_pm_restore(struct coresight_path *path)
|
|||
static int coresight_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
|
||||
void *v)
|
||||
{
|
||||
struct coresight_path *path = coresight_cpu_get_active_path();
|
||||
struct coresight_path *path =
|
||||
coresight_cpu_get_active_path(CS_MODE_SYSFS | CS_MODE_PERF);
|
||||
int ret;
|
||||
|
||||
ret = coresight_pm_is_needed(path);
|
||||
|
|
@ -2012,13 +2013,42 @@ static struct notifier_block coresight_cpu_pm_nb = {
|
|||
.notifier_call = coresight_cpu_pm_notify,
|
||||
};
|
||||
|
||||
static int coresight_dying_cpu(unsigned int cpu)
|
||||
{
|
||||
struct coresight_path *path;
|
||||
|
||||
/*
|
||||
* The perf event layer will disable PMU events in the CPU
|
||||
* hotplug. Here only handles SYSFS case.
|
||||
*/
|
||||
path = coresight_cpu_get_active_path(CS_MODE_SYSFS);
|
||||
if (!path)
|
||||
return 0;
|
||||
|
||||
coresight_disable_sysfs(coresight_get_source(path));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init coresight_pm_setup(void)
|
||||
{
|
||||
return cpu_pm_register_notifier(&coresight_cpu_pm_nb);
|
||||
int ret;
|
||||
|
||||
ret = cpu_pm_register_notifier(&coresight_cpu_pm_nb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_ONLINE,
|
||||
"arm/coresight-core:dying",
|
||||
NULL, coresight_dying_cpu);
|
||||
if (ret)
|
||||
cpu_pm_unregister_notifier(&coresight_cpu_pm_nb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void coresight_pm_cleanup(void)
|
||||
{
|
||||
cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_ONLINE);
|
||||
cpu_pm_unregister_notifier(&coresight_cpu_pm_nb);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -699,35 +699,6 @@ static int etm_online_cpu(unsigned int cpu)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int etm_starting_cpu(unsigned int cpu)
|
||||
{
|
||||
if (!etmdrvdata[cpu])
|
||||
return 0;
|
||||
|
||||
spin_lock(&etmdrvdata[cpu]->spinlock);
|
||||
if (!etmdrvdata[cpu]->os_unlock) {
|
||||
etm_os_unlock(etmdrvdata[cpu]);
|
||||
etmdrvdata[cpu]->os_unlock = true;
|
||||
}
|
||||
|
||||
if (coresight_get_mode(etmdrvdata[cpu]->csdev))
|
||||
etm_enable_hw(etmdrvdata[cpu]);
|
||||
spin_unlock(&etmdrvdata[cpu]->spinlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int etm_dying_cpu(unsigned int cpu)
|
||||
{
|
||||
if (!etmdrvdata[cpu])
|
||||
return 0;
|
||||
|
||||
spin_lock(&etmdrvdata[cpu]->spinlock);
|
||||
if (coresight_get_mode(etmdrvdata[cpu]->csdev))
|
||||
etm_disable_hw(etmdrvdata[cpu]);
|
||||
spin_unlock(&etmdrvdata[cpu]->spinlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool etm_arch_supported(u8 arch)
|
||||
{
|
||||
switch (arch) {
|
||||
|
|
@ -795,13 +766,6 @@ static int __init etm_hp_setup(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING,
|
||||
"arm/coresight:starting",
|
||||
etm_starting_cpu, etm_dying_cpu);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
|
||||
"arm/coresight:online",
|
||||
etm_online_cpu, NULL);
|
||||
|
|
@ -812,15 +776,11 @@ static int __init etm_hp_setup(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* failed dyn state - remove others */
|
||||
cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void etm_hp_clear(void)
|
||||
{
|
||||
cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
|
||||
if (hp_online) {
|
||||
cpuhp_remove_state_nocalls(hp_online);
|
||||
hp_online = 0;
|
||||
|
|
|
|||
|
|
@ -1833,33 +1833,6 @@ static int etm4_online_cpu(unsigned int cpu)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int etm4_starting_cpu(unsigned int cpu)
|
||||
{
|
||||
if (!etmdrvdata[cpu])
|
||||
return 0;
|
||||
|
||||
raw_spin_lock(&etmdrvdata[cpu]->spinlock);
|
||||
if (!etmdrvdata[cpu]->os_unlock)
|
||||
etm4_os_unlock(etmdrvdata[cpu]);
|
||||
|
||||
if (coresight_get_mode(etmdrvdata[cpu]->csdev))
|
||||
etm4_enable_hw(etmdrvdata[cpu]);
|
||||
raw_spin_unlock(&etmdrvdata[cpu]->spinlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int etm4_dying_cpu(unsigned int cpu)
|
||||
{
|
||||
if (!etmdrvdata[cpu])
|
||||
return 0;
|
||||
|
||||
raw_spin_lock(&etmdrvdata[cpu]->spinlock);
|
||||
if (coresight_get_mode(etmdrvdata[cpu]->csdev))
|
||||
etm4_disable_hw(etmdrvdata[cpu]);
|
||||
raw_spin_unlock(&etmdrvdata[cpu]->spinlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool etm4_pm_save_needed(struct etmv4_drvdata *drvdata)
|
||||
{
|
||||
return !!drvdata->save_state;
|
||||
|
|
@ -2120,13 +2093,6 @@ static int __init etm4_pm_setup(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING,
|
||||
"arm/coresight4:starting",
|
||||
etm4_starting_cpu, etm4_dying_cpu);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
|
||||
"arm/coresight4:online",
|
||||
etm4_online_cpu, NULL);
|
||||
|
|
@ -2137,14 +2103,11 @@ static int __init etm4_pm_setup(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* failed dyn state - remove others */
|
||||
cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void etm4_pm_clear(void)
|
||||
{
|
||||
cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
|
||||
if (hp_online) {
|
||||
cpuhp_remove_state_nocalls(hp_online);
|
||||
hp_online = 0;
|
||||
|
|
|
|||
|
|
@ -344,9 +344,9 @@ struct coresight_path {
|
|||
};
|
||||
|
||||
enum cs_mode {
|
||||
CS_MODE_DISABLED,
|
||||
CS_MODE_SYSFS,
|
||||
CS_MODE_PERF,
|
||||
CS_MODE_DISABLED = 0,
|
||||
CS_MODE_SYSFS = BIT(0),
|
||||
CS_MODE_PERF = BIT(1),
|
||||
};
|
||||
|
||||
#define coresight_ops(csdev) csdev->ops
|
||||
|
|
|
|||
|
|
@ -180,7 +180,6 @@ enum cpuhp_state {
|
|||
CPUHP_AP_DUMMY_TIMER_STARTING,
|
||||
CPUHP_AP_ARM_XEN_STARTING,
|
||||
CPUHP_AP_ARM_XEN_RUNSTATE_STARTING,
|
||||
CPUHP_AP_ARM_CORESIGHT_STARTING,
|
||||
CPUHP_AP_ARM_CORESIGHT_CTI_STARTING,
|
||||
CPUHP_AP_ARM64_ISNDEP_STARTING,
|
||||
CPUHP_AP_SMPCFD_DYING,
|
||||
|
|
@ -200,6 +199,7 @@ enum cpuhp_state {
|
|||
CPUHP_AP_IRQ_AFFINITY_ONLINE,
|
||||
CPUHP_AP_BLK_MQ_ONLINE,
|
||||
CPUHP_AP_ARM_MVEBU_SYNC_CLOCKS,
|
||||
CPUHP_AP_ARM_CORESIGHT_ONLINE,
|
||||
CPUHP_AP_X86_INTEL_EPB_ONLINE,
|
||||
CPUHP_AP_PERF_ONLINE,
|
||||
CPUHP_AP_PERF_X86_ONLINE,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user