#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* */ #include /* For init/exit macros */ #include /* For MODULE_ marcros */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* extern int nr_cpu_ids; */ /* int enable_clock(int id, unsigned char *name); */ static int test_case; module_param(test_case, int, 0664); static DEFINE_SPINLOCK(wdt_test_lock0); static DEFINE_SPINLOCK(wdt_test_lock1); static struct task_struct *wk_tsk[2]; /* cpu: 2 */ static int data; static int __cpuinit cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { int hotcpu = (unsigned long)hcpu; switch (action) { case CPU_UP_PREPARE: case CPU_UP_PREPARE_FROZEN: /* watchdog_prepare_cpu(hotcpu); */ break; case CPU_ONLINE: case CPU_ONLINE_FROZEN: /* */ if (hotcpu < nr_cpu_ids) { kthread_bind(wk_tsk[hotcpu], hotcpu); wake_up_process(wk_tsk[hotcpu]); pr_alert("[WDK-test]cpu %d plug on ", hotcpu); } break; #ifdef CONFIG_HOTPLUG_CPU case CPU_UP_CANCELED: case CPU_UP_CANCELED_FROZEN: case CPU_DEAD: case CPU_DEAD_FROZEN: pr_alert("[WDK-test]:start Stop CPU:%d\n", hotcpu); break; #endif /* CONFIG_HOTPLUG_CPU */ } /* * hardlockup and softlockup are not important enough * to block cpu bring up. Just always succeed and * rely on printk output to flag problems. */ return NOTIFY_OK; } static struct notifier_block cpu_nfb __cpuinitdata = { .notifier_call = cpu_callback }; static int kwdt_thread_test(void *arg) { struct sched_param param = {.sched_priority = 99 }; int cpu; unsigned int flags; sched_setscheduler(current, SCHED_FIFO, ¶m); set_current_state(TASK_INTERRUPTIBLE); for (;;) { pr_debug("wd_test debug start, cpu:%d\n", cpu); spin_lock(&wdt_test_lock0); cpu = smp_processor_id(); spin_unlock(&wdt_test_lock0); if (test_case == (cpu * 10 + 1)) { /* cpu0 Preempt disale */ pr_debug("CPU:%d, Preempt disable\n", cpu); spin_lock(&wdt_test_lock1); } if (test_case == (cpu * 10 + 2)) { /* cpu0 Preempt&irq disale */ pr_debug("CPU:%d, irq & Preempt disable\n", cpu); spin_lock_irqsave(&wdt_test_lock1, flags); } msleep(5 * 1000); /* 5s */ wdt_dump_reg(); pr_debug("wd_test debug end, cpu:%d\n", cpu); } return 0; } static int start_kicker(void) { int i; unsigned char name[64] = { 0 }; for (i = 0; i < nr_cpu_ids; i++) { sprintf(name, "wdtk-test-%d", i); pr_debug("[WDK]:thread name: %s\n", name); wk_tsk[i] = kthread_create(kwdt_thread_test, &data, name); if (IS_ERR(wk_tsk[i])) { int ret = PTR_ERR(wk_tsk[i]); wk_tsk[i] = NULL; return ret; } kthread_bind(wk_tsk[i], i); wake_up_process(wk_tsk[i]); } return 0; } static int __init test_init(void) { /* enable_clock(12, "Vfifo"); */ register_cpu_notifier(&cpu_nfb); start_kicker(); return 0; } static void __init test_exit(void) { } module_init(test_init); module_exit(test_exit);