edac: arm64: Enable cti pmu workaround on CPUs onlined post-boot

The CTI PMU workaround for the EDAC interrupt is enabled at probe
only on the CPUs that are online during boot-up. Some of the CPUs
can be onlined at a later point from userspace.
Ensure that the workaround is enabled on those CPUs as well.

Change-Id: I551b228d3df3f7ed7d935a55aec6474339d569a6
Signed-off-by: Rohit Vaswani <rvaswani@codeaurora.org>
This commit is contained in:
Rohit Vaswani 2014-08-01 18:55:27 -07:00
parent 7dd146b7f3
commit 8a138da0fc
2 changed files with 30 additions and 5 deletions

View File

@ -111,7 +111,9 @@ struct erp_drvdata {
struct edac_device_ctl_info *edev_ctl;
void __iomem *cci_base;
u32 mem_perf_counter;
struct notifier_block nb;
struct notifier_block nb_pm;
struct notifier_block nb_cpu;
struct work_struct work;
};
static struct erp_drvdata *abort_handler_drvdata;
@ -754,7 +756,7 @@ static void check_sbe_event(struct erp_drvdata *drv)
static int arm64_pmu_cpu_pm_notify(struct notifier_block *self,
unsigned long action, void *v)
{
struct erp_drvdata *drv = container_of(self, struct erp_drvdata, nb);
struct erp_drvdata *drv = container_of(self, struct erp_drvdata, nb_pm);
switch (action) {
case CPU_PM_EXIT:
@ -766,6 +768,20 @@ static int arm64_pmu_cpu_pm_notify(struct notifier_block *self,
return NOTIFY_OK;
}
static int msm_cti_pmu_wa_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
struct erp_drvdata *drv = container_of(self, struct erp_drvdata,
nb_cpu);
switch (action) {
case CPU_ONLINE:
schedule_work_on((unsigned long)hcpu, &drv->work);
break;
};
return NOTIFY_OK;
}
static int arm64_cpu_erp_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@ -852,11 +868,14 @@ static int arm64_cpu_erp_probe(struct platform_device *pdev)
goto out_irq;
}
drv->nb.notifier_call = arm64_pmu_cpu_pm_notify;
drv->nb_pm.notifier_call = arm64_pmu_cpu_pm_notify;
drv->mem_perf_counter = arm64_pmu_get_last_counter();
cpu_pm_register_notifier(&(drv->nb));
cpu_pm_register_notifier(&(drv->nb_pm));
drv->nb_cpu.notifier_call = msm_cti_pmu_wa_cpu_notify;
register_cpu_notifier(&drv->nb_cpu);
arm64_pmu_irq_handled_externally();
schedule_on_each_cpu(msm_enable_cti_pmu_workaround);
INIT_WORK(&drv->work, msm_enable_cti_pmu_workaround);
on_each_cpu(sbe_enable_event, drv, 1);
on_each_cpu(arm64_enable_pmu_irq, &sbe_irq, 1);

View File

@ -13,9 +13,11 @@
#include <linux/coresight-cti.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/percpu.h>
#include <linux/smp.h>
#include <soc/qcom/cti-pmu-irq.h>
static DEFINE_PER_CPU(int, msm_cti_pmu_wa_done);
static struct coresight_cti *msm_cti_cpux[NR_CPUS];
static const char * const coresight_cpu_name[] = {
"coresight-cti-cpu0",
@ -47,9 +49,12 @@ void msm_enable_cti_pmu_workaround(struct work_struct *work)
int trigin = 1;
int trigout = 2;
int ch = 2;
int cpu = smp_processor_id();
int cpu = raw_smp_processor_id();
int ret;
if (per_cpu(msm_cti_pmu_wa_done, cpu) == true)
return;
cti_cpux = coresight_cti_get(coresight_cpu_name[cpu]);
if (IS_ERR(cti_cpux))
goto err;
@ -63,6 +68,7 @@ void msm_enable_cti_pmu_workaround(struct work_struct *work)
if (ret)
goto err_out;
coresight_cti_enable_gate(cti_cpux, ch);
per_cpu(msm_cti_pmu_wa_done, cpu) = true;
pr_info("%s for CPU %d\n", __func__, cpu);
return;