aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/mm/cmm.c54
1 files changed, 35 insertions, 19 deletions
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index f2e00df99bae..607f50ead1fd 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -16,6 +16,7 @@
16#include <linux/sysctl.h> 16#include <linux/sysctl.h>
17#include <linux/ctype.h> 17#include <linux/ctype.h>
18#include <linux/swap.h> 18#include <linux/swap.h>
19#include <linux/kthread.h>
19 20
20#include <asm/pgalloc.h> 21#include <asm/pgalloc.h>
21#include <asm/uaccess.h> 22#include <asm/uaccess.h>
@@ -46,8 +47,7 @@ static struct cmm_page_array *cmm_page_list;
46static struct cmm_page_array *cmm_timed_page_list; 47static struct cmm_page_array *cmm_timed_page_list;
47static DEFINE_SPINLOCK(cmm_lock); 48static DEFINE_SPINLOCK(cmm_lock);
48 49
49static unsigned long cmm_thread_active; 50static struct task_struct *cmm_thread_ptr;
50static struct work_struct cmm_thread_starter;
51static wait_queue_head_t cmm_thread_wait; 51static wait_queue_head_t cmm_thread_wait;
52static struct timer_list cmm_timer; 52static struct timer_list cmm_timer;
53 53
@@ -143,14 +143,12 @@ cmm_thread(void *dummy)
143{ 143{
144 int rc; 144 int rc;
145 145
146 daemonize("cmmthread");
147 while (1) { 146 while (1) {
148 rc = wait_event_interruptible(cmm_thread_wait, 147 rc = wait_event_interruptible(cmm_thread_wait,
149 (cmm_pages != cmm_pages_target || 148 (cmm_pages != cmm_pages_target ||
150 cmm_timed_pages != cmm_timed_pages_target)); 149 cmm_timed_pages != cmm_timed_pages_target ||
151 if (rc == -ERESTARTSYS) { 150 kthread_should_stop()));
152 /* Got kill signal. End thread. */ 151 if (kthread_should_stop() || rc == -ERESTARTSYS) {
153 clear_bit(0, &cmm_thread_active);
154 cmm_pages_target = cmm_pages; 152 cmm_pages_target = cmm_pages;
155 cmm_timed_pages_target = cmm_timed_pages; 153 cmm_timed_pages_target = cmm_timed_pages;
156 break; 154 break;
@@ -176,16 +174,8 @@ cmm_thread(void *dummy)
176} 174}
177 175
178static void 176static void
179cmm_start_thread(void)
180{
181 kernel_thread(cmm_thread, NULL, 0);
182}
183
184static void
185cmm_kick_thread(void) 177cmm_kick_thread(void)
186{ 178{
187 if (!test_and_set_bit(0, &cmm_thread_active))
188 schedule_work(&cmm_thread_starter);
189 wake_up(&cmm_thread_wait); 179 wake_up(&cmm_thread_wait);
190} 180}
191 181
@@ -429,22 +419,48 @@ struct ctl_table_header *cmm_sysctl_header;
429static int 419static int
430cmm_init (void) 420cmm_init (void)
431{ 421{
422 int rc = -ENOMEM;
423
432#ifdef CONFIG_CMM_PROC 424#ifdef CONFIG_CMM_PROC
433 cmm_sysctl_header = register_sysctl_table(cmm_dir_table, 1); 425 cmm_sysctl_header = register_sysctl_table(cmm_dir_table, 1);
426 if (!cmm_sysctl_header)
427 goto out;
434#endif 428#endif
435#ifdef CONFIG_CMM_IUCV 429#ifdef CONFIG_CMM_IUCV
436 smsg_register_callback(SMSG_PREFIX, cmm_smsg_target); 430 rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target);
431 if (rc < 0)
432 goto out_smsg;
437#endif 433#endif
438 register_oom_notifier(&cmm_oom_nb); 434 rc = register_oom_notifier(&cmm_oom_nb);
439 INIT_WORK(&cmm_thread_starter, (void *) cmm_start_thread, NULL); 435 if (rc < 0)
436 goto out_oom_notify;
440 init_waitqueue_head(&cmm_thread_wait); 437 init_waitqueue_head(&cmm_thread_wait);
441 init_timer(&cmm_timer); 438 init_timer(&cmm_timer);
442 return 0; 439 cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
440 rc = IS_ERR(cmm_thread_ptr) ? PTR_ERR(cmm_thread_ptr) : 0;
441 if (!rc)
442 goto out;
443 /*
444 * kthread_create failed. undo all the stuff from above again.
445 */
446 unregister_oom_notifier(&cmm_oom_nb);
447
448out_oom_notify:
449#ifdef CONFIG_CMM_IUCV
450 smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target);
451out_smsg:
452#endif
453#ifdef CONFIG_CMM_PROC
454 unregister_sysctl_table(cmm_sysctl_header);
455#endif
456out:
457 return rc;
443} 458}
444 459
445static void 460static void
446cmm_exit(void) 461cmm_exit(void)
447{ 462{
463 kthread_stop(cmm_thread_ptr);
448 unregister_oom_notifier(&cmm_oom_nb); 464 unregister_oom_notifier(&cmm_oom_nb);
449 cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list); 465 cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list);
450 cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list); 466 cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list);