summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Quan <andyq@google.com>2017-10-19 09:25:57 +0000
committerAndroid Partner Code Review <android-gerrit-partner@google.com>2017-10-19 09:25:57 +0000
commit70b0e352e1dd2a663bcd88bda1dcc8f3d9731b30 (patch)
tree03de4fbfa1f95abefd492a20d5eb739a7a52640b
parentd7a5c1d4e38adaea27e120f9d2529d06e350cf7c (diff)
parenta2bdad8f32f3f1d4b1ec8297c7567dd7822035af (diff)
downloadmediatek-70b0e352e1dd2a663bcd88bda1dcc8f3d9731b30.tar.gz
Merge "Move WDT interrupt to FIQ" into android-mediatek-mooneye-4.4
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/arm/common/fiq_glue_setup.c4
-rw-r--r--arch/arm/mach-mt2601/Makefile1
-rw-r--r--arch/arm/mach-mt2601/fiq_smp_call.c194
-rw-r--r--arch/arm/mach-mt2601/include/mach/fiq_smp_call.h8
-rw-r--r--drivers/misc/mediatek/aee/common/wdt-handler.c5
-rw-r--r--drivers/misc/mediatek/aee/ipanic/ipanic_rom.c2
7 files changed, 208 insertions, 8 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 866a1e81bca2..00deaed8d380 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -768,7 +768,7 @@ config ARCH_MT2601
select MFD_SYSCON
select ARM_HAS_SG_CHAIN
select KERNEL_MODE_NEON
- select FIQ
+ select FIQ_GLUE
help
This enable support for MediaTek MT2601
diff --git a/arch/arm/common/fiq_glue_setup.c b/arch/arm/common/fiq_glue_setup.c
index 8cb1b611c6d5..b0ca76bcd63f 100644
--- a/arch/arm/common/fiq_glue_setup.c
+++ b/arch/arm/common/fiq_glue_setup.c
@@ -33,7 +33,7 @@ static void fiq_glue_setup_helper(void *info)
{
struct fiq_glue_handler *handler = info;
fiq_glue_setup(handler->fiq, handler,
- __get_cpu_var(fiq_stack) + THREAD_START_SP,
+ *this_cpu_ptr(&fiq_stack) + THREAD_START_SP,
fiq_return_handler);
}
@@ -139,7 +139,7 @@ void fiq_glue_resume(void)
if (!current_handler)
return;
fiq_glue_setup(current_handler->fiq, current_handler,
- __get_cpu_var(fiq_stack) + THREAD_START_SP,
+ *this_cpu_ptr(&fiq_stack) + THREAD_START_SP,
fiq_return_handler);
if (current_handler->resume)
current_handler->resume(current_handler);
diff --git a/arch/arm/mach-mt2601/Makefile b/arch/arm/mach-mt2601/Makefile
index 0b1cc7347190..17c48a79d9a6 100644
--- a/arch/arm/mach-mt2601/Makefile
+++ b/arch/arm/mach-mt2601/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_MTK_CIRQ) += mt_cirq.o
obj-$(CONFIG_MTK_MCI) += mt_mci.o
obj-y += mtk_ccci_helper.o
obj-y += cache-mtk-v7.o
+obj-$(CONFIG_FIQ_GLUE) += fiq_smp_call.o
# Hibernation
AFLAGS_swsusp.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
diff --git a/arch/arm/mach-mt2601/fiq_smp_call.c b/arch/arm/mach-mt2601/fiq_smp_call.c
new file mode 100644
index 000000000000..3dcaf8ae7759
--- /dev/null
+++ b/arch/arm/mach-mt2601/fiq_smp_call.c
@@ -0,0 +1,194 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/percpu.h>
+#include <linux/smp.h>
+#include <mach/smp.h>
+#include <mach/irqs.h>
+#include <mach/fiq_smp_call.h>
+#include <asm/cputype.h>
+
+#if defined(CONFIG_FIQ_GLUE)
+
+enum {
+ CSD_FLAG_LOCK = 0x01,
+};
+
+struct fiq_call_single_data {
+ struct list_head list;
+ smp_call_func_t func;
+ void *info;
+ cpumask_var_t cpumask;
+ u16 flags;
+ u16 priv;
+};
+
+struct call_function_data {
+ struct fiq_call_single_data csd;
+ fiq_smp_call_func_t func;
+ atomic_t refs;
+ cpumask_var_t cpumask;
+};
+
+static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_function_data, fiq_cfd_data);
+static struct call_function_data *current_cfd_data;
+
+extern void irq_raise_softirq(const struct cpumask *mask, unsigned int irq);
+
+static int __csd_lock_wait(struct fiq_call_single_data *data)
+{
+ int cpu, nr_online_cpus = 0;
+
+ while (data->flags & CSD_FLAG_LOCK) {
+ for_each_cpu(cpu, data->cpumask) {
+ if (cpu_online(cpu)) {
+ nr_online_cpus++;
+ }
+ }
+ if (!nr_online_cpus)
+ return -ENXIO;
+ cpu_relax();
+ }
+
+ return 0;
+}
+
+static void __csd_lock(struct fiq_call_single_data *data)
+{
+ __csd_lock_wait(data);
+ data->flags = CSD_FLAG_LOCK;
+
+ /*
+ * prevent CPU from reordering the above assignment
+ * to ->flags with any subsequent assignments to other
+ * fields of the specified fiq_call_single_data structure:
+ */
+ smp_mb();
+}
+
+static void __csd_unlock(struct fiq_call_single_data *data)
+{
+ WARN_ON(!(data->flags & CSD_FLAG_LOCK));
+
+ /*
+ * ensure we're all done before releasing data:
+ */
+ smp_mb();
+
+ data->flags &= ~CSD_FLAG_LOCK;
+}
+
+/*
+ * fiq_smp_call_function: FIQ version of smp_call_function.
+ * @func:
+ * @info:
+ * @wait:
+ * Return 0 for success and error code for failure.
+ *
+ * This function is designed for the debugger only.
+ * Other kernel code or drivers should NOT use this function.
+ * This function can only be used in the FIQ-WDT handler.
+ */
+int fiq_smp_call_function(fiq_smp_call_func_t func, void *info, int wait)
+{
+ struct cpumask *mask = (struct cpumask *)cpu_online_mask;
+ struct call_function_data *data;
+ int refs, install_csd, this_cpu = 0;
+
+ this_cpu = smp_processor_id();
+ data = this_cpu_ptr(&fiq_cfd_data);
+ __csd_lock(&data->csd);
+
+ atomic_set(&data->refs, 0);
+
+ data->func = func;
+ data->csd.info = info;
+
+ smp_wmb();
+
+ cpumask_and(data->cpumask, mask, cpu_online_mask);
+ cpumask_clear_cpu(this_cpu, data->cpumask);
+ refs = cpumask_weight(data->cpumask);
+ cpumask_and(data->csd.cpumask, data->cpumask, data->cpumask);
+
+ if (unlikely(!refs)) {
+ __csd_unlock(&data->csd);
+ goto fiq_smp_call_function_exit;
+ }
+
+ /* poll to install data on current_cfd_data */
+ install_csd = 0;
+ do {
+#if 0 /* no need to protect due to FIQ-WDT */
+ spin_lock(&fiq_smp_call_lock);
+#endif
+
+ if (!current_cfd_data) {
+ atomic_set(&data->refs, refs);
+ current_cfd_data = data;
+ install_csd = 1;
+ }
+#if 0
+ spin_unlock(&fiq_smp_call_lock);
+#endif
+ } while (!install_csd);
+
+ smp_mb();
+
+ /* send a message to all CPUs in the map */
+ irq_raise_softirq(data->cpumask, FIQ_SMP_CALL_SGI);
+
+ if (wait)
+ __csd_lock_wait(&data->csd);
+
+ fiq_smp_call_function_exit:
+ return 0;
+}
+
+static void fiq_smp_call_handler(void *arg, void *regs, void *svc_sp)
+{
+ struct call_function_data *data;
+ int cpu = 0, refs;
+ fiq_smp_call_func_t func;
+
+ /* get the current cpu id */
+ asm volatile ("MRC p15, 0, %0, c0, c0, 5\n" "AND %0, %0, #0xf\n":"+r" (cpu)
+ : : "cc");
+
+ data = current_cfd_data;
+ if (data) {
+ func = data->func;
+ func(data->csd.info, regs, svc_sp);
+
+ cpumask_clear_cpu(cpu, data->csd.cpumask);
+ refs = atomic_dec_return(&data->refs);
+
+ if (refs == 0) {
+ __csd_unlock(&data->csd);
+ current_cfd_data = NULL;
+ }
+ }
+}
+
+static void __fiq_smp_call_init(void *info)
+{
+ int err;
+
+ err = request_fiq(FIQ_SMP_CALL_SGI, fiq_smp_call_handler, 0, NULL);
+ if (err) {
+ pr_err("fail to request FIQ for FIQ_SMP_CALL_SGI\n");
+ } else {
+ pr_debug("Request FIQ for FIQ_SMP_CALL_SGI\n");
+ }
+}
+
+static int __init fiq_smp_call_init(void)
+{
+ __fiq_smp_call_init(NULL);
+ smp_call_function(__fiq_smp_call_init, NULL, 1);
+
+ return 0;
+}
+arch_initcall(fiq_smp_call_init);
+
+#endif /* CONFIG_FIQ_GLUE */
diff --git a/arch/arm/mach-mt2601/include/mach/fiq_smp_call.h b/arch/arm/mach-mt2601/include/mach/fiq_smp_call.h
new file mode 100644
index 000000000000..caf03290c5f0
--- /dev/null
+++ b/arch/arm/mach-mt2601/include/mach/fiq_smp_call.h
@@ -0,0 +1,8 @@
+#ifndef __FIQ_SMP_CALL_H
+#define __FIQ_SMP_CALL_H
+
+typedef void (*fiq_smp_call_func_t) (void *info, void *regs, void *svc_sp);
+
+extern int fiq_smp_call_function(fiq_smp_call_func_t func, void *info, int wait);
+
+#endif /* !__FIQ_SMP_CALL_H */
diff --git a/drivers/misc/mediatek/aee/common/wdt-handler.c b/drivers/misc/mediatek/aee/common/wdt-handler.c
index a18b55fdba32..d04f26dc8e5e 100644
--- a/drivers/misc/mediatek/aee/common/wdt-handler.c
+++ b/drivers/misc/mediatek/aee/common/wdt-handler.c
@@ -32,7 +32,7 @@
#include <asm/memory.h>
#include <asm/traps.h>
#if defined(CONFIG_FIQ_GLUE)
-#include <asm/fiq_smp_call.h>
+#include <mach/fiq_smp_call.h>
#endif
#include <mach/wd_api.h>
#include <mt-plat/mtk_ram_console.h>
@@ -521,9 +521,6 @@ void aee_wdt_fiq_info(void *arg, void *regs, void *svc_sp)
aee_rr_rec_fiq_step(AEE_FIQ_STEP_WDT_FIQ_DONE);
- /* FIXME: correct mrdump function if necessary */
- __mrdump_create_oops_dump(AEE_REBOOT_MODE_WDT, regs, "WDT/HWT");
-
aee_wdt_irq_info();
}
#endif /* CONFIG_FIQ_GLUE */
diff --git a/drivers/misc/mediatek/aee/ipanic/ipanic_rom.c b/drivers/misc/mediatek/aee/ipanic/ipanic_rom.c
index ecbfc8663e8f..678a0e3bdaf1 100644
--- a/drivers/misc/mediatek/aee/ipanic/ipanic_rom.c
+++ b/drivers/misc/mediatek/aee/ipanic/ipanic_rom.c
@@ -683,7 +683,7 @@ static int ipanic_die(struct notifier_block *self, unsigned long cmd, void *ptr)
aee_rr_rec_fiq_step(AEE_FIQ_STEP_KE_IPANIC_DIE);
#endif
aee_disable_api();
- __mrdump_create_oops_dump(AEE_REBOOT_MODE_KERNEL_OOPS, dargs->regs, "Kernel Oops");
+ smp_send_stop();
__show_regs(dargs->regs);
#ifdef CONFIG_MTK_RAM_CONSOLE