mirror of
https://github.com/joel16/android_kernel_sony_msm8994_rework.git
synced 2024-11-27 05:40:41 +00:00
arm64: edac: Add workaround for using cti to trigger pmu irq
In MSM8994-V1, for unknown reasons the pmu percpu interrupt was incorrectly connected to the corresponding CPU in the other cluster. To workaround this problem, it was decided that the cti could be used to trigger the percpu pmu interrupt to the right cpu which actually caused the event and can handle it. This patch implements this workaround. Change-Id: I732ad77ed2529a54b85c51b3fadcc53d93d70279 Signed-off-by: Rohit Vaswani <rvaswani@codeaurora.org>
This commit is contained in:
parent
4e4cb0e35a
commit
1b1d3e9fbb
@ -171,6 +171,15 @@ config ARCH_MSM8994_V1_TLBI_WA
|
|||||||
[39:38] bits of VA are tied to zero and due to which TLBI
|
[39:38] bits of VA are tied to zero and due to which TLBI
|
||||||
operations with VA or ASID will not work.
|
operations with VA or ASID will not work.
|
||||||
|
|
||||||
|
config MSM8994_V1_PMUIRQ_WA
|
||||||
|
bool "Enable MSM8994 v1 PMU-CTI IRQ workaround"
|
||||||
|
depends on ARCH_MSM8994 && CORESIGHT_CTI
|
||||||
|
help
|
||||||
|
This enables support for the MSM8994 v1 PMU-CTI IRQ workaround.
|
||||||
|
This workaround is required for MSM8994 V1 revision where the
|
||||||
|
percpu PMU interrupt is incorrectly connected to the corresponding
|
||||||
|
CPUs in the other cluster.
|
||||||
|
|
||||||
config ARCH_XGENE
|
config ARCH_XGENE
|
||||||
bool "AppliedMicro X-Gene SOC Family"
|
bool "AppliedMicro X-Gene SOC Family"
|
||||||
help
|
help
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/percpu.h>
|
#include <linux/percpu.h>
|
||||||
|
#include <soc/qcom/cti-pmu-irq.h>
|
||||||
|
|
||||||
#include <asm/cputype.h>
|
#include <asm/cputype.h>
|
||||||
|
|
||||||
@ -655,9 +656,11 @@ static irqreturn_t arm64_sbe_handler(int irq, void *drvdata)
|
|||||||
u32 pmovsr, cntr;
|
u32 pmovsr, cntr;
|
||||||
struct erp_local_data errdata;
|
struct erp_local_data errdata;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int overflow = 0;
|
int overflow = 0, ret = IRQ_HANDLED;
|
||||||
int cpu = raw_smp_processor_id();
|
int cpu = raw_smp_processor_id();
|
||||||
|
|
||||||
|
msm_cti_pmu_irq_ack(cpu);
|
||||||
|
|
||||||
errdata.drv = *((struct erp_drvdata **)drvdata);
|
errdata.drv = *((struct erp_drvdata **)drvdata);
|
||||||
cntr = errdata.drv->mem_perf_counter;
|
cntr = errdata.drv->mem_perf_counter;
|
||||||
arm64_pmu_lock(NULL, &flags);
|
arm64_pmu_lock(NULL, &flags);
|
||||||
@ -672,10 +675,10 @@ static irqreturn_t arm64_sbe_handler(int irq, void *drvdata)
|
|||||||
arm64_erp_local_handler(&errdata);
|
arm64_erp_local_handler(&errdata);
|
||||||
sbe_enable_event(errdata.drv);
|
sbe_enable_event(errdata.drv);
|
||||||
} else {
|
} else {
|
||||||
return armv8pmu_handle_irq(irq, NULL);
|
ret = armv8pmu_handle_irq(irq, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int request_erp_irq(struct platform_device *pdev, const char *propname,
|
static int request_erp_irq(struct platform_device *pdev, const char *propname,
|
||||||
@ -842,6 +845,7 @@ static int arm64_cpu_erp_probe(struct platform_device *pdev)
|
|||||||
drv->mem_perf_counter = arm64_pmu_get_last_counter();
|
drv->mem_perf_counter = arm64_pmu_get_last_counter();
|
||||||
cpu_pm_register_notifier(&(drv->nb));
|
cpu_pm_register_notifier(&(drv->nb));
|
||||||
arm64_pmu_irq_handled_externally();
|
arm64_pmu_irq_handled_externally();
|
||||||
|
schedule_on_each_cpu(msm_enable_cti_pmu_workaround);
|
||||||
on_each_cpu(sbe_enable_event, drv, 1);
|
on_each_cpu(sbe_enable_event, drv, 1);
|
||||||
on_each_cpu(arm64_enable_pmu_irq, &sbe_irq, 1);
|
on_each_cpu(arm64_enable_pmu_irq, &sbe_irq, 1);
|
||||||
|
|
||||||
|
@ -57,3 +57,4 @@ endif
|
|||||||
obj-$(CONFIG_MSM_SYSMON_COMM) += sysmon.o
|
obj-$(CONFIG_MSM_SYSMON_COMM) += sysmon.o
|
||||||
obj-$(CONFIG_CP_ACCESS64) += cpaccess64.o
|
obj-$(CONFIG_CP_ACCESS64) += cpaccess64.o
|
||||||
obj-$(CONFIG_MSM_CPU_PWR_CTL) += cpu_pwr_ctl.o
|
obj-$(CONFIG_MSM_CPU_PWR_CTL) += cpu_pwr_ctl.o
|
||||||
|
obj-$(CONFIG_MSM8994_V1_PMUIRQ_WA) += cti-pmu-irq.o
|
||||||
|
76
drivers/soc/qcom/cti-pmu-irq.c
Normal file
76
drivers/soc/qcom/cti-pmu-irq.c
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/coresight-cti.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/smp.h>
|
||||||
|
#include <soc/qcom/cti-pmu-irq.h>
|
||||||
|
|
||||||
|
static struct coresight_cti *msm_cti_cpux[NR_CPUS];
|
||||||
|
static const char * const coresight_cpu_name[] = {
|
||||||
|
"coresight-cti-cpu0",
|
||||||
|
"coresight-cti-cpu1",
|
||||||
|
"coresight-cti-cpu2",
|
||||||
|
"coresight-cti-cpu3",
|
||||||
|
"coresight-cti-cpu4",
|
||||||
|
"coresight-cti-cpu5",
|
||||||
|
"coresight-cti-cpu6",
|
||||||
|
"coresight-cti-cpu7",
|
||||||
|
};
|
||||||
|
|
||||||
|
struct coresight_cti *msm_get_cpu_cti(int cpu)
|
||||||
|
{
|
||||||
|
return coresight_cti_get(coresight_cpu_name[cpu]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void msm_cti_pmu_irq_ack(int cpu)
|
||||||
|
{
|
||||||
|
int ret = coresight_cti_ack_trig(msm_cti_cpux[cpu], 2);
|
||||||
|
if (ret)
|
||||||
|
pr_err("Failed to Acknowledge CTI-PMU Irq on CPU %d - %d\n",
|
||||||
|
cpu, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
void msm_enable_cti_pmu_workaround(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct coresight_cti *cti_cpux;
|
||||||
|
int trigin = 1;
|
||||||
|
int trigout = 2;
|
||||||
|
int ch = 2;
|
||||||
|
int cpu = smp_processor_id();
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
cti_cpux = coresight_cti_get(coresight_cpu_name[cpu]);
|
||||||
|
if (IS_ERR(cti_cpux))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
msm_cti_cpux[cpu] = cti_cpux;
|
||||||
|
|
||||||
|
ret = coresight_cti_map_trigin(cti_cpux, trigin, ch);
|
||||||
|
if (ret)
|
||||||
|
goto err_in;
|
||||||
|
ret = coresight_cti_map_trigout(cti_cpux, trigout, ch);
|
||||||
|
if (ret)
|
||||||
|
goto err_out;
|
||||||
|
coresight_cti_enable_gate(cti_cpux, ch);
|
||||||
|
pr_info("%s for CPU %d\n", __func__, cpu);
|
||||||
|
|
||||||
|
return;
|
||||||
|
err_out:
|
||||||
|
coresight_cti_unmap_trigin(cti_cpux, trigin, ch);
|
||||||
|
err_in:
|
||||||
|
coresight_cti_put(cti_cpux);
|
||||||
|
err:
|
||||||
|
pr_err("Failed to enable CTI-PMU workaround on CPU %d - %d\n",
|
||||||
|
cpu, ret);
|
||||||
|
}
|
27
include/soc/qcom/cti-pmu-irq.h
Normal file
27
include/soc/qcom/cti-pmu-irq.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MSM_CTI_PMU_IRQ_H
|
||||||
|
#define __MSM_CTI_PMU_IRQ_H
|
||||||
|
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_MSM8994_V1_PMUIRQ_WA
|
||||||
|
void msm_enable_cti_pmu_workaround(struct work_struct *work);
|
||||||
|
struct coresight_cti *msm_get_cpu_cti(int cpu);
|
||||||
|
void msm_cti_pmu_irq_ack(int cpu);
|
||||||
|
#else
|
||||||
|
static inline void msm_enable_cti_pmu_workaround(struct work_struct *work) { }
|
||||||
|
static inline struct coresight_cti *msm_get_cpu_cti(int cpu) { return NULL; }
|
||||||
|
static inline void msm_cti_pmu_irq_ack(int cpu) { }
|
||||||
|
#endif
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user