aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/edac/edac_mc.c88
1 files changed, 10 insertions, 78 deletions
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 9c205274c1cb..8a7a3ab745aa 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -29,6 +29,7 @@
29#include <linux/list.h> 29#include <linux/list.h>
30#include <linux/sysdev.h> 30#include <linux/sysdev.h>
31#include <linux/ctype.h> 31#include <linux/ctype.h>
32#include <linux/kthread.h>
32 33
33#include <asm/uaccess.h> 34#include <asm/uaccess.h>
34#include <asm/page.h> 35#include <asm/page.h>
@@ -64,6 +65,8 @@ static atomic_t pci_parity_count = ATOMIC_INIT(0);
64static DECLARE_MUTEX(mem_ctls_mutex); 65static DECLARE_MUTEX(mem_ctls_mutex);
65static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices); 66static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices);
66 67
68static struct task_struct *edac_thread;
69
67/* Structure of the whitelist and blacklist arrays */ 70/* Structure of the whitelist and blacklist arrays */
68struct edac_pci_device_list { 71struct edac_pci_device_list {
69 unsigned int vendor; /* Vendor ID */ 72 unsigned int vendor; /* Vendor ID */
@@ -2073,7 +2076,6 @@ static inline void check_mc_devices (void)
2073 */ 2076 */
2074static void do_edac_check(void) 2077static void do_edac_check(void)
2075{ 2078{
2076
2077 debugf3("MC: " __FILE__ ": %s()\n", __func__); 2079 debugf3("MC: " __FILE__ ": %s()\n", __func__);
2078 2080
2079 check_mc_devices(); 2081 check_mc_devices();
@@ -2081,62 +2083,16 @@ static void do_edac_check(void)
2081 do_pci_parity_check(); 2083 do_pci_parity_check();
2082} 2084}
2083 2085
2084
2085/*
2086 * EDAC thread state information
2087 */
2088struct bs_thread_info
2089{
2090 struct task_struct *task;
2091 struct completion *event;
2092 char *name;
2093 void (*run)(void);
2094};
2095
2096static struct bs_thread_info bs_thread;
2097
2098/*
2099 * edac_kernel_thread
2100 * This the kernel thread that processes edac operations
2101 * in a normal thread environment
2102 */
2103static int edac_kernel_thread(void *arg) 2086static int edac_kernel_thread(void *arg)
2104{ 2087{
2105 struct bs_thread_info *thread = (struct bs_thread_info *) arg; 2088 while (!kthread_should_stop()) {
2106 2089 do_edac_check();
2107 /* detach thread */
2108 daemonize(thread->name);
2109
2110 current->exit_signal = SIGCHLD;
2111 allow_signal(SIGKILL);
2112 thread->task = current;
2113
2114 /* indicate to starting task we have started */
2115 complete(thread->event);
2116
2117 /* loop forever, until we are told to stop */
2118 while(thread->run != NULL) {
2119 void (*run)(void);
2120
2121 /* call the function to check the memory controllers */
2122 run = thread->run;
2123 if (run)
2124 run();
2125
2126 if (signal_pending(current))
2127 flush_signals(current);
2128
2129 /* ensure we are interruptable */
2130 set_current_state(TASK_INTERRUPTIBLE);
2131 2090
2132 /* goto sleep for the interval */ 2091 /* goto sleep for the interval */
2133 schedule_timeout((HZ * poll_msec) / 1000); 2092 schedule_timeout_interruptible((HZ * poll_msec) / 1000);
2134 try_to_freeze(); 2093 try_to_freeze();
2135 } 2094 }
2136 2095
2137 /* notify waiter that we are exiting */
2138 complete(thread->event);
2139
2140 return 0; 2096 return 0;
2141} 2097}
2142 2098
@@ -2146,9 +2102,6 @@ static int edac_kernel_thread(void *arg)
2146 */ 2102 */
2147static int __init edac_mc_init(void) 2103static int __init edac_mc_init(void)
2148{ 2104{
2149 int ret;
2150 struct completion event;
2151
2152 printk(KERN_INFO "MC: " __FILE__ " version " EDAC_MC_VERSION "\n"); 2105 printk(KERN_INFO "MC: " __FILE__ " version " EDAC_MC_VERSION "\n");
2153 2106
2154 /* 2107 /*
@@ -2176,24 +2129,15 @@ static int __init edac_mc_init(void)
2176 return -ENODEV; 2129 return -ENODEV;
2177 } 2130 }
2178 2131
2179 /* Create our kernel thread */
2180 init_completion(&event);
2181 bs_thread.event = &event;
2182 bs_thread.name = "kedac";
2183 bs_thread.run = do_edac_check;
2184
2185 /* create our kernel thread */ 2132 /* create our kernel thread */
2186 ret = kernel_thread(edac_kernel_thread, &bs_thread, CLONE_KERNEL); 2133 edac_thread = kthread_run(edac_kernel_thread, NULL, "kedac");
2187 if (ret < 0) { 2134 if (IS_ERR(edac_thread)) {
2188 /* remove the sysfs entries */ 2135 /* remove the sysfs entries */
2189 edac_sysfs_memctrl_teardown(); 2136 edac_sysfs_memctrl_teardown();
2190 edac_sysfs_pci_teardown(); 2137 edac_sysfs_pci_teardown();
2191 return -ENOMEM; 2138 return PTR_ERR(edac_thread);
2192 } 2139 }
2193 2140
2194 /* wait for our kernel theard ack that it is up and running */
2195 wait_for_completion(&event);
2196
2197 return 0; 2141 return 0;
2198} 2142}
2199 2143
@@ -2204,21 +2148,9 @@ static int __init edac_mc_init(void)
2204 */ 2148 */
2205static void __exit edac_mc_exit(void) 2149static void __exit edac_mc_exit(void)
2206{ 2150{
2207 struct completion event;
2208
2209 debugf0("MC: " __FILE__ ": %s()\n", __func__); 2151 debugf0("MC: " __FILE__ ": %s()\n", __func__);
2210 2152
2211 init_completion(&event); 2153 kthread_stop(edac_thread);
2212 bs_thread.event = &event;
2213
2214 /* As soon as ->run is set to NULL, the task could disappear,
2215 * so we need to hold tasklist_lock until we have sent the signal
2216 */
2217 read_lock(&tasklist_lock);
2218 bs_thread.run = NULL;
2219 send_sig(SIGKILL, bs_thread.task, 1);
2220 read_unlock(&tasklist_lock);
2221 wait_for_completion(&event);
2222 2154
2223 /* tear down the sysfs device */ 2155 /* tear down the sysfs device */
2224 edac_sysfs_memctrl_teardown(); 2156 edac_sysfs_memctrl_teardown();