Good day,
On Wed, 15 May 2019 at 09:01, Mike Leach mike.leach@linaro.org wrote:
Hi Mathieu,
On Tue, 14 May 2019 at 18:01, Mathieu Poirier mathieu.poirier@linaro.org wrote:
On Wed, May 01, 2019 at 09:49:39AM +0100, Mike Leach wrote:
Notification mechanism for CPU power events such as CPU hotplug added as general notification mechnism in CoreSight common code to be used by all CPU bound CS devices.
Provides a per-device registration mechanism with callback fn and event type notifier. Core code now manages the CPU hotplug registrations and calls back any registered device when events occur.
Added registration call from CTI devices.
From what I understand Andrew Murray is currently working on something like that. Have you guys had a chance to talk about this and compare strategies?
I'm not aware of any work in this area - not seen anything on this list, but possible I may have missed something on the linux-arm-kernel ML as I have not looked since before my holiday. Are you aware of any postings I should see?
I haven't seen any patches yet - this came up during an IRC conversation between Suzuki and I.
I know we discussed your intentions re: gen-pd @ connect - but this patch is simply to move the CPUHP out of specific drivers and into the common core code.
Right.
Thereafter it should be possible to a) remove the CPU-HP out of the ETM driver. b) have ETM and CPU-debug drivers use the common code to register with the notifier - this would be a follow-up to the current CTI specific set.
The best way to proceed would be to fix CPU hotplug for ETM and CPU-debug and then use the same mechanism for CTI. Since Andrew is working on doing just that I thought it might be a good idea for you guys to compare strategies. On the flip side I understand you have plenty of work to do with CTI - keep going with the current approach and we'll see how things play out. In the worse case scenarios I'll step in and do the ETM and CPU HP parts.
Regards
Mike
Signed-off-by: Mike Leach mike.leach@linaro.org
drivers/hwtracing/coresight/coresight-cti.c | 54 +++++++- drivers/hwtracing/coresight/coresight-priv.h | 25 ++++ drivers/hwtracing/coresight/coresight.c | 138 +++++++++++++++++++ 3 files changed, 213 insertions(+), 4 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c index e0192fd50804..faae7db44bd6 100644 --- a/drivers/hwtracing/coresight/coresight-cti.c +++ b/drivers/hwtracing/coresight/coresight-cti.c @@ -587,6 +587,38 @@ const struct coresight_ops cti_ops = { .ect_ops = &cti_ops_ect, };
+/* pm event notifiers */ +int cti_cs_cpupm_event(struct coresight_device *csdev, unsigned int cpuid,
enum cs_cpu_pm_events event)
+{
struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
switch (event) {
/* called on the device cpu during registration */
case CS_CPUPM_SMP_ON_REG_CPU:
drvdata->config.hw_powered = true;
break;
/* cpu hotplug start */
case CS_CPUPM_CPUHP_START:
spin_lock(&drvdata->spinlock);
drvdata->config.hw_powered = true;
spin_unlock(&drvdata->spinlock);
if (atomic_read(&drvdata->config.enable_req_count))
cti_enable_hw(drvdata);
break;
/* cpu hotplug stop */
case CS_CPUPM_CPUHP_STOP:
cti_disable_hw(drvdata);
spin_lock(&drvdata->spinlock);
drvdata->config.hw_powered = false;
spin_unlock(&drvdata->spinlock);
break;
}
return 0;
+}
static int cti_probe(struct amba_device *adev, const struct amba_id *id) { int ret = 0; @@ -668,9 +700,6 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) /* initialise default driver values */ cti_set_default_config(&drvdata->config);
/* setup cpu related CTI devices, otherwise assume powered */
drvdata->config.hw_powered = true;
/* create dynamic attributes for connections */ ret = cti_create_cons_sysfs(drvdata); if (ret) {
@@ -693,6 +722,19 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) goto err_out; }
/* setup cpu related CTI PM, otherwise assume powered */
if (drvdata->ctidev.cpu >= 0) {
drvdata->config.hw_powered = false;
ret = coresight_cpupm_register(drvdata->csdev,
drvdata->ctidev.cpu,
cti_cs_cpupm_event);
if (ret) {
pr_err("%s: CS cpu pm register failed\n", pdata->name);
goto err_out;
}
} else
drvdata->config.hw_powered = true;
/* add to list of CTI devices */ mutex_lock(&ect_mutex); ect_nd->cti_drv = drvdata;
@@ -719,6 +761,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) return 0;
err_out:
if (drvdata->csdev && (drvdata->ctidev.cpu >= 0))
coresight_cpupm_unregister(drvdata->csdev, drvdata->ctidev.cpu); kfree(drvdata); kfree(ect_nd); return ret;
@@ -751,8 +795,10 @@ void cti_device_release(struct device *dev) struct ect_node *ect_item, *ect_tmp;
/* free up resources associated with the cti connections */
if (drvdata->ctidev.cpu >= 0)
if (drvdata->ctidev.cpu >= 0) { cti_cpu_drv[drvdata->ctidev.cpu] = 0;
coresight_cpupm_unregister(drvdata->csdev, drvdata->ctidev.cpu);
} /* clear the dynamic sysfs associate with connections */ cti_destroy_cons_sysfs(&drvdata->ctidev);
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index b1fca5c4bdb2..716669b2a40a 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -212,4 +212,29 @@ static inline void *coresight_get_uci_data(const struct amba_id *id) return 0; }
+/*
- cpu power management - allow any CPU bound Coresight device
- to use a common registration infrastructure for notifications.
- */
+/* cpu pm event types */ +enum cs_cpu_pm_events {
CS_CPUPM_SMP_ON_REG_CPU,/* smp call on cpu at registration */
CS_CPUPM_CPUHP_START, /* hotplug starting CPU */
CS_CPUPM_CPUHP_STOP, /* hotplug stopping CPU */
+};
+/* callback function type */ +typedef int (*p_cs_cpu_pm_event)(struct coresight_device *csdev,
unsigned int cpuid,
enum cs_cpu_pm_events event);
+/* registration functions */ +int coresight_cpupm_register(struct coresight_device *csdev,
unsigned int cpuid,
p_cs_cpu_pm_event callback);
+void coresight_cpupm_unregister(struct coresight_device *csdev,
unsigned int cpuid);
#endif diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 9d56b3b32172..afcc330e61eb 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -1295,3 +1295,141 @@ void coresight_unregister(struct coresight_device *csdev) device_unregister(&csdev->dev); } EXPORT_SYMBOL_GPL(coresight_unregister);
+/* cs general CPU bound device pm notification */ +struct coresight_cpupm_item {
struct coresight_device *csdev;
p_cs_cpu_pm_event callback;
struct list_head node;
+};
+/* CS cpu pm notifier lists per cpu */ +static DEFINE_PER_CPU(struct list_head *, cs_cpupm_notifier);
+static enum cpuhp_state cscpu_hp_online; +static int cscpu_dev_reg_cnt;
+static int coresight_iterate_cpu_event_list(unsigned int cpu,
enum cs_cpu_pm_events event)
+{
struct list_head *cpu_list;
struct coresight_cpupm_item *item;
mutex_lock(&coresight_mutex);
cpu_list = per_cpu(cs_cpupm_notifier, cpu);
if (!list_empty(cpu_list)) {
list_for_each_entry(item, cpu_list, node) {
item->callback(item->csdev, cpu, event);
}
}
mutex_unlock(&coresight_mutex);
return 0;
+}
+static int coresight_hp_starting_cpu(unsigned int cpu) +{
return coresight_iterate_cpu_event_list(cpu, CS_CPUPM_CPUHP_START);
+}
+static int coresight_hp_stopping_cpu(unsigned int cpu) +{
return coresight_iterate_cpu_event_list(cpu, CS_CPUPM_CPUHP_STOP);
+}
+struct cs_smp_reg_cb_info {
unsigned int cpu;
struct coresight_cpupm_item *item;
+};
+static void coresight_smp_onreg_callback(void *info) +{
struct cs_smp_reg_cb_info *cb_info = info;
cb_info->item->callback(cb_info->item->csdev, cb_info->cpu,
CS_CPUPM_SMP_ON_REG_CPU);
+}
+int coresight_cpupm_register(struct coresight_device *csdev,
unsigned int cpuid,
p_cs_cpu_pm_event callback)
+{
struct list_head *cpu_list;
struct coresight_cpupm_item *item;
int err = 0;
struct cs_smp_reg_cb_info on_reg_cb_info;
mutex_lock(&coresight_mutex);
cpu_list = per_cpu(cs_cpupm_notifier, cpuid);
/* init list if no head yet */
if (!cpu_list) {
cpu_list = kzalloc(sizeof(struct list_head), GFP_KERNEL);
if (!cpu_list)
goto cpupm_reg_done;
else
INIT_LIST_HEAD(cpu_list);
}
/* create a list item */
item = kzalloc(sizeof(struct coresight_cpupm_item), GFP_KERNEL);
if (!item) {
err = -ENOMEM;
goto cpupm_reg_done;
}
item->csdev = csdev;
item->callback = callback;
/* init the cpu hotplug notification */
cpus_read_lock();
if (!cscpu_dev_reg_cnt) {
cscpu_hp_online = cpuhp_setup_state_nocalls_cpuslocked(
CPUHP_AP_ONLINE_DYN, "arm/coresightcpu:online",
coresight_hp_starting_cpu,
coresight_hp_stopping_cpu);
if (cscpu_hp_online < 0) {
err = cscpu_hp_online;
kfree(item);
goto cpupm_hp_done;
}
}
cscpu_dev_reg_cnt++;
list_add(&item->node, cpu_list);
/* smp callback on dev cpu @ registration */
on_reg_cb_info.item = item;
on_reg_cb_info.cpu = cpuid;
smp_call_function_single(cpuid, coresight_smp_onreg_callback,
&on_reg_cb_info, 1);
+cpupm_hp_done:
cpus_read_unlock();
+cpupm_reg_done:
mutex_unlock(&coresight_mutex);
return err;
+} +EXPORT_SYMBOL_GPL(coresight_cpupm_register);
+void coresight_cpupm_unregister(struct coresight_device *csdev,
unsigned int cpuid)
+{
struct list_head *cpu_list;
struct coresight_cpupm_item *item, *tmp;
mutex_lock(&coresight_mutex);
cpu_list = per_cpu(cs_cpupm_notifier, cpuid);
if (!list_empty(cpu_list)) {
list_for_each_entry_safe(item, tmp, cpu_list, node) {
if (item->csdev == csdev) {
list_del(&item->node);
kfree(item);
goto cs_cpupm_item_removed;
}
}
}
+cs_cpupm_item_removed:
mutex_unlock(&coresight_mutex);
+}
+EXPORT_SYMBOL_GPL(coresight_cpupm_unregister);
2.20.1
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK