Commit c5527c17 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'coresight-next-v6.2' of...

Merge tag 'coresight-next-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/coresight/linux into char-misc-next

Suzuki writes:

coresight: Update for v6.2

CoreSight updatesfor v6.2 includes :

 - Support for ETMv4 probing on hotplugged CPUs
 - Fix TRBE driver for cpuhp state refcounting
 - Fix CTI driver NULL pointer dereferencing
 - Fix comment for repeated word
Signed-off-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>

* tag 'coresight-next-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/coresight/linux:
  coresight: etm4x: fix repeated words in comments
  coresight: cti: Fix null pointer error on CTI init before ETM
  coresight: trbe: remove cpuhp instance node before remove cpuhp state
  coresight: etm4x: add CPU hotplug support for probing
parents ae27e886 c767c347
...@@ -564,7 +564,7 @@ static void cti_add_assoc_to_csdev(struct coresight_device *csdev) ...@@ -564,7 +564,7 @@ static void cti_add_assoc_to_csdev(struct coresight_device *csdev)
* if we found a matching csdev then update the ECT * if we found a matching csdev then update the ECT
* association pointer for the device with this CTI. * association pointer for the device with this CTI.
*/ */
coresight_set_assoc_ectdev_mutex(csdev->ect_dev, coresight_set_assoc_ectdev_mutex(csdev,
ect_item->csdev); ect_item->csdev);
break; break;
} }
......
...@@ -66,10 +66,13 @@ static enum cpuhp_state hp_online; ...@@ -66,10 +66,13 @@ static enum cpuhp_state hp_online;
struct etm4_init_arg { struct etm4_init_arg {
unsigned int pid; unsigned int pid;
struct etmv4_drvdata *drvdata; struct device *dev;
struct csdev_access *csa; struct csdev_access *csa;
}; };
static DEFINE_PER_CPU(struct etm4_init_arg *, delayed_probe);
static int etm4_probe_cpu(unsigned int cpu);
/* /*
* Check if TRCSSPCICRn(i) is implemented for a given instance. * Check if TRCSSPCICRn(i) is implemented for a given instance.
* *
...@@ -1085,7 +1088,7 @@ static void etm4_init_arch_data(void *info) ...@@ -1085,7 +1088,7 @@ static void etm4_init_arch_data(void *info)
struct csdev_access *csa; struct csdev_access *csa;
int i; int i;
drvdata = init_arg->drvdata; drvdata = dev_get_drvdata(init_arg->dev);
csa = init_arg->csa; csa = init_arg->csa;
/* /*
...@@ -1478,7 +1481,7 @@ static int etm4_set_event_filters(struct etmv4_drvdata *drvdata, ...@@ -1478,7 +1481,7 @@ static int etm4_set_event_filters(struct etmv4_drvdata *drvdata,
/* /*
* If filters::ssstatus == 1, trace acquisition was * If filters::ssstatus == 1, trace acquisition was
* started but the process was yanked away before the * started but the process was yanked away before the
* the stop address was hit. As such the start/stop * stop address was hit. As such the start/stop
* logic needs to be re-started so that tracing can * logic needs to be re-started so that tracing can
* resume where it left. * resume where it left.
* *
...@@ -1528,7 +1531,7 @@ void etm4_config_trace_mode(struct etmv4_config *config) ...@@ -1528,7 +1531,7 @@ void etm4_config_trace_mode(struct etmv4_config *config)
static int etm4_online_cpu(unsigned int cpu) static int etm4_online_cpu(unsigned int cpu)
{ {
if (!etmdrvdata[cpu]) if (!etmdrvdata[cpu])
return 0; return etm4_probe_cpu(cpu);
if (etmdrvdata[cpu]->boot_enable && !etmdrvdata[cpu]->sticky_enable) if (etmdrvdata[cpu]->boot_enable && !etmdrvdata[cpu]->sticky_enable)
coresight_enable(etmdrvdata[cpu]->csdev); coresight_enable(etmdrvdata[cpu]->csdev);
...@@ -1904,48 +1907,20 @@ static void etm4_pm_clear(void) ...@@ -1904,48 +1907,20 @@ static void etm4_pm_clear(void)
} }
} }
static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid) static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg)
{ {
int ret; int ret;
struct coresight_platform_data *pdata = NULL; struct coresight_platform_data *pdata = NULL;
struct etmv4_drvdata *drvdata; struct device *dev = init_arg->dev;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
struct coresight_desc desc = { 0 }; struct coresight_desc desc = { 0 };
struct etm4_init_arg init_arg = { 0 };
u8 major, minor; u8 major, minor;
char *type_name; char *type_name;
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata) if (!drvdata)
return -ENOMEM; return -EINVAL;
dev_set_drvdata(dev, drvdata);
if (pm_save_enable == PARAM_PM_SAVE_FIRMWARE)
pm_save_enable = coresight_loses_context_with_cpu(dev) ?
PARAM_PM_SAVE_SELF_HOSTED : PARAM_PM_SAVE_NEVER;
if (pm_save_enable != PARAM_PM_SAVE_NEVER) {
drvdata->save_state = devm_kmalloc(dev,
sizeof(struct etmv4_save_state), GFP_KERNEL);
if (!drvdata->save_state)
return -ENOMEM;
}
drvdata->base = base;
spin_lock_init(&drvdata->spinlock);
drvdata->cpu = coresight_get_cpu(dev);
if (drvdata->cpu < 0)
return drvdata->cpu;
init_arg.drvdata = drvdata;
init_arg.csa = &desc.access;
init_arg.pid = etm_pid;
if (smp_call_function_single(drvdata->cpu, desc.access = *init_arg->csa;
etm4_init_arch_data, &init_arg, 1))
dev_err(dev, "ETM arch init failed\n");
if (!drvdata->arch) if (!drvdata->arch)
return -EINVAL; return -EINVAL;
...@@ -2016,6 +1991,68 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid) ...@@ -2016,6 +1991,68 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
return 0; return 0;
} }
static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
{
struct etmv4_drvdata *drvdata;
struct csdev_access access = { 0 };
struct etm4_init_arg init_arg = { 0 };
struct etm4_init_arg *delayed;
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
dev_set_drvdata(dev, drvdata);
if (pm_save_enable == PARAM_PM_SAVE_FIRMWARE)
pm_save_enable = coresight_loses_context_with_cpu(dev) ?
PARAM_PM_SAVE_SELF_HOSTED : PARAM_PM_SAVE_NEVER;
if (pm_save_enable != PARAM_PM_SAVE_NEVER) {
drvdata->save_state = devm_kmalloc(dev,
sizeof(struct etmv4_save_state), GFP_KERNEL);
if (!drvdata->save_state)
return -ENOMEM;
}
drvdata->base = base;
spin_lock_init(&drvdata->spinlock);
drvdata->cpu = coresight_get_cpu(dev);
if (drvdata->cpu < 0)
return drvdata->cpu;
init_arg.dev = dev;
init_arg.csa = &access;
init_arg.pid = etm_pid;
/*
* Serialize against CPUHP callbacks to avoid race condition
* between the smp call and saving the delayed probe.
*/
cpus_read_lock();
if (smp_call_function_single(drvdata->cpu,
etm4_init_arch_data, &init_arg, 1)) {
/* The CPU was offline, try again once it comes online. */
delayed = devm_kmalloc(dev, sizeof(*delayed), GFP_KERNEL);
if (!delayed) {
cpus_read_unlock();
return -ENOMEM;
}
*delayed = init_arg;
per_cpu(delayed_probe, drvdata->cpu) = delayed;
cpus_read_unlock();
return 0;
}
cpus_read_unlock();
return etm4_add_coresight_dev(&init_arg);
}
static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id) static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id)
{ {
void __iomem *base; void __iomem *base;
...@@ -2054,6 +2091,35 @@ static int etm4_probe_platform_dev(struct platform_device *pdev) ...@@ -2054,6 +2091,35 @@ static int etm4_probe_platform_dev(struct platform_device *pdev)
return ret; return ret;
} }
static int etm4_probe_cpu(unsigned int cpu)
{
int ret;
struct etm4_init_arg init_arg;
struct csdev_access access = { 0 };
struct etm4_init_arg *iap = *this_cpu_ptr(&delayed_probe);
if (!iap)
return 0;
init_arg = *iap;
devm_kfree(init_arg.dev, iap);
*this_cpu_ptr(&delayed_probe) = NULL;
ret = pm_runtime_resume_and_get(init_arg.dev);
if (ret < 0) {
dev_err(init_arg.dev, "Failed to get PM runtime!\n");
return 0;
}
init_arg.csa = &access;
etm4_init_arch_data(&init_arg);
etm4_add_coresight_dev(&init_arg);
pm_runtime_put(init_arg.dev);
return 0;
}
static struct amba_cs_uci_id uci_id_etm4[] = { static struct amba_cs_uci_id uci_id_etm4[] = {
{ {
/* ETMv4 UCI data */ /* ETMv4 UCI data */
...@@ -2068,16 +2134,20 @@ static void clear_etmdrvdata(void *info) ...@@ -2068,16 +2134,20 @@ static void clear_etmdrvdata(void *info)
int cpu = *(int *)info; int cpu = *(int *)info;
etmdrvdata[cpu] = NULL; etmdrvdata[cpu] = NULL;
per_cpu(delayed_probe, cpu) = NULL;
} }
static int __exit etm4_remove_dev(struct etmv4_drvdata *drvdata) static int __exit etm4_remove_dev(struct etmv4_drvdata *drvdata)
{ {
etm_perf_symlink(drvdata->csdev, false); bool had_delayed_probe;
/* /*
* Taking hotplug lock here to avoid racing between etm4_remove_dev() * Taking hotplug lock here to avoid racing between etm4_remove_dev()
* and CPU hotplug call backs. * and CPU hotplug call backs.
*/ */
cpus_read_lock(); cpus_read_lock();
had_delayed_probe = per_cpu(delayed_probe, drvdata->cpu);
/* /*
* The readers for etmdrvdata[] are CPU hotplug call backs * The readers for etmdrvdata[] are CPU hotplug call backs
* and PM notification call backs. Change etmdrvdata[i] on * and PM notification call backs. Change etmdrvdata[i] on
...@@ -2085,12 +2155,15 @@ static int __exit etm4_remove_dev(struct etmv4_drvdata *drvdata) ...@@ -2085,12 +2155,15 @@ static int __exit etm4_remove_dev(struct etmv4_drvdata *drvdata)
* inside one call back function. * inside one call back function.
*/ */
if (smp_call_function_single(drvdata->cpu, clear_etmdrvdata, &drvdata->cpu, 1)) if (smp_call_function_single(drvdata->cpu, clear_etmdrvdata, &drvdata->cpu, 1))
etmdrvdata[drvdata->cpu] = NULL; clear_etmdrvdata(&drvdata->cpu);
cpus_read_unlock(); cpus_read_unlock();
if (!had_delayed_probe) {
etm_perf_symlink(drvdata->csdev, false);
cscfg_unregister_csdev(drvdata->csdev); cscfg_unregister_csdev(drvdata->csdev);
coresight_unregister(drvdata->csdev); coresight_unregister(drvdata->csdev);
}
return 0; return 0;
} }
......
...@@ -1434,6 +1434,7 @@ static int arm_trbe_probe_cpuhp(struct trbe_drvdata *drvdata) ...@@ -1434,6 +1434,7 @@ static int arm_trbe_probe_cpuhp(struct trbe_drvdata *drvdata)
static void arm_trbe_remove_cpuhp(struct trbe_drvdata *drvdata) static void arm_trbe_remove_cpuhp(struct trbe_drvdata *drvdata)
{ {
cpuhp_state_remove_instance(drvdata->trbe_online, &drvdata->hotplug_node);
cpuhp_remove_multi_state(drvdata->trbe_online); cpuhp_remove_multi_state(drvdata->trbe_online);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment