diff options
author | Andy Quan <andyq@google.com> | 2017-10-19 09:25:57 +0000 |
---|---|---|
committer | Android Partner Code Review <android-gerrit-partner@google.com> | 2017-10-19 09:25:57 +0000 |
commit | 70b0e352e1dd2a663bcd88bda1dcc8f3d9731b30 (patch) | |
tree | 03de4fbfa1f95abefd492a20d5eb739a7a52640b | |
parent | d7a5c1d4e38adaea27e120f9d2529d06e350cf7c (diff) | |
parent | a2bdad8f32f3f1d4b1ec8297c7567dd7822035af (diff) | |
download | mediatek-70b0e352e1dd2a663bcd88bda1dcc8f3d9731b30.tar.gz |
Merge "Move WDT interrupt to FIQ" into android-mediatek-mooneye-4.4
-rw-r--r-- | arch/arm/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/common/fiq_glue_setup.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-mt2601/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-mt2601/fiq_smp_call.c | 194 | ||||
-rw-r--r-- | arch/arm/mach-mt2601/include/mach/fiq_smp_call.h | 8 | ||||
-rw-r--r-- | drivers/misc/mediatek/aee/common/wdt-handler.c | 5 | ||||
-rw-r--r-- | drivers/misc/mediatek/aee/ipanic/ipanic_rom.c | 2 |
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 |