diff options
Diffstat (limited to 'arch/s390/mm/cmm.c')
-rw-r--r-- | arch/s390/mm/cmm.c | 110 |
1 files changed, 39 insertions, 71 deletions
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index 76a3637b88e0..eb6a2ef5f82e 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c | |||
@@ -1,17 +1,16 @@ | |||
1 | /* | 1 | /* |
2 | * arch/s390/mm/cmm.c | 2 | * Collaborative memory management interface. |
3 | * | 3 | * |
4 | * S390 version | 4 | * Copyright IBM Corp 2003,2010 |
5 | * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation | 5 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>, |
6 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) | ||
7 | * | 6 | * |
8 | * Collaborative memory management interface. | ||
9 | */ | 7 | */ |
10 | 8 | ||
11 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
12 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
13 | #include <linux/init.h> | 11 | #include <linux/init.h> |
14 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/gfp.h> | ||
15 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
16 | #include <linux/sysctl.h> | 15 | #include <linux/sysctl.h> |
17 | #include <linux/ctype.h> | 16 | #include <linux/ctype.h> |
@@ -19,9 +18,9 @@ | |||
19 | #include <linux/kthread.h> | 18 | #include <linux/kthread.h> |
20 | #include <linux/oom.h> | 19 | #include <linux/oom.h> |
21 | #include <linux/suspend.h> | 20 | #include <linux/suspend.h> |
21 | #include <linux/uaccess.h> | ||
22 | 22 | ||
23 | #include <asm/pgalloc.h> | 23 | #include <asm/pgalloc.h> |
24 | #include <asm/uaccess.h> | ||
25 | #include <asm/diag.h> | 24 | #include <asm/diag.h> |
26 | 25 | ||
27 | static char *sender = "VMRMSVM"; | 26 | static char *sender = "VMRMSVM"; |
@@ -52,14 +51,14 @@ static struct cmm_page_array *cmm_timed_page_list; | |||
52 | static DEFINE_SPINLOCK(cmm_lock); | 51 | static DEFINE_SPINLOCK(cmm_lock); |
53 | 52 | ||
54 | static struct task_struct *cmm_thread_ptr; | 53 | static struct task_struct *cmm_thread_ptr; |
55 | static wait_queue_head_t cmm_thread_wait; | 54 | static DECLARE_WAIT_QUEUE_HEAD(cmm_thread_wait); |
56 | static struct timer_list cmm_timer; | 55 | static DEFINE_TIMER(cmm_timer, NULL, 0, 0); |
57 | 56 | ||
58 | static void cmm_timer_fn(unsigned long); | 57 | static void cmm_timer_fn(unsigned long); |
59 | static void cmm_set_timer(void); | 58 | static void cmm_set_timer(void); |
60 | 59 | ||
61 | static long | 60 | static long cmm_alloc_pages(long nr, long *counter, |
62 | cmm_alloc_pages(long nr, long *counter, struct cmm_page_array **list) | 61 | struct cmm_page_array **list) |
63 | { | 62 | { |
64 | struct cmm_page_array *pa, *npa; | 63 | struct cmm_page_array *pa, *npa; |
65 | unsigned long addr; | 64 | unsigned long addr; |
@@ -98,8 +97,7 @@ cmm_alloc_pages(long nr, long *counter, struct cmm_page_array **list) | |||
98 | return nr; | 97 | return nr; |
99 | } | 98 | } |
100 | 99 | ||
101 | static long | 100 | static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list) |
102 | cmm_free_pages(long nr, long *counter, struct cmm_page_array **list) | ||
103 | { | 101 | { |
104 | struct cmm_page_array *pa; | 102 | struct cmm_page_array *pa; |
105 | unsigned long addr; | 103 | unsigned long addr; |
@@ -139,11 +137,10 @@ static int cmm_oom_notify(struct notifier_block *self, | |||
139 | } | 137 | } |
140 | 138 | ||
141 | static struct notifier_block cmm_oom_nb = { | 139 | static struct notifier_block cmm_oom_nb = { |
142 | .notifier_call = cmm_oom_notify | 140 | .notifier_call = cmm_oom_notify, |
143 | }; | 141 | }; |
144 | 142 | ||
145 | static int | 143 | static int cmm_thread(void *dummy) |
146 | cmm_thread(void *dummy) | ||
147 | { | 144 | { |
148 | int rc; | 145 | int rc; |
149 | 146 | ||
@@ -169,7 +166,7 @@ cmm_thread(void *dummy) | |||
169 | cmm_timed_pages_target = cmm_timed_pages; | 166 | cmm_timed_pages_target = cmm_timed_pages; |
170 | } else if (cmm_timed_pages_target < cmm_timed_pages) { | 167 | } else if (cmm_timed_pages_target < cmm_timed_pages) { |
171 | cmm_free_pages(1, &cmm_timed_pages, | 168 | cmm_free_pages(1, &cmm_timed_pages, |
172 | &cmm_timed_page_list); | 169 | &cmm_timed_page_list); |
173 | } | 170 | } |
174 | if (cmm_timed_pages > 0 && !timer_pending(&cmm_timer)) | 171 | if (cmm_timed_pages > 0 && !timer_pending(&cmm_timer)) |
175 | cmm_set_timer(); | 172 | cmm_set_timer(); |
@@ -177,14 +174,12 @@ cmm_thread(void *dummy) | |||
177 | return 0; | 174 | return 0; |
178 | } | 175 | } |
179 | 176 | ||
180 | static void | 177 | static void cmm_kick_thread(void) |
181 | cmm_kick_thread(void) | ||
182 | { | 178 | { |
183 | wake_up(&cmm_thread_wait); | 179 | wake_up(&cmm_thread_wait); |
184 | } | 180 | } |
185 | 181 | ||
186 | static void | 182 | static void cmm_set_timer(void) |
187 | cmm_set_timer(void) | ||
188 | { | 183 | { |
189 | if (cmm_timed_pages_target <= 0 || cmm_timeout_seconds <= 0) { | 184 | if (cmm_timed_pages_target <= 0 || cmm_timeout_seconds <= 0) { |
190 | if (timer_pending(&cmm_timer)) | 185 | if (timer_pending(&cmm_timer)) |
@@ -201,8 +196,7 @@ cmm_set_timer(void) | |||
201 | add_timer(&cmm_timer); | 196 | add_timer(&cmm_timer); |
202 | } | 197 | } |
203 | 198 | ||
204 | static void | 199 | static void cmm_timer_fn(unsigned long ignored) |
205 | cmm_timer_fn(unsigned long ignored) | ||
206 | { | 200 | { |
207 | long nr; | 201 | long nr; |
208 | 202 | ||
@@ -215,57 +209,49 @@ cmm_timer_fn(unsigned long ignored) | |||
215 | cmm_set_timer(); | 209 | cmm_set_timer(); |
216 | } | 210 | } |
217 | 211 | ||
218 | void | 212 | static void cmm_set_pages(long nr) |
219 | cmm_set_pages(long nr) | ||
220 | { | 213 | { |
221 | cmm_pages_target = nr; | 214 | cmm_pages_target = nr; |
222 | cmm_kick_thread(); | 215 | cmm_kick_thread(); |
223 | } | 216 | } |
224 | 217 | ||
225 | long | 218 | static long cmm_get_pages(void) |
226 | cmm_get_pages(void) | ||
227 | { | 219 | { |
228 | return cmm_pages; | 220 | return cmm_pages; |
229 | } | 221 | } |
230 | 222 | ||
231 | void | 223 | static void cmm_add_timed_pages(long nr) |
232 | cmm_add_timed_pages(long nr) | ||
233 | { | 224 | { |
234 | cmm_timed_pages_target += nr; | 225 | cmm_timed_pages_target += nr; |
235 | cmm_kick_thread(); | 226 | cmm_kick_thread(); |
236 | } | 227 | } |
237 | 228 | ||
238 | long | 229 | static long cmm_get_timed_pages(void) |
239 | cmm_get_timed_pages(void) | ||
240 | { | 230 | { |
241 | return cmm_timed_pages; | 231 | return cmm_timed_pages; |
242 | } | 232 | } |
243 | 233 | ||
244 | void | 234 | static void cmm_set_timeout(long nr, long seconds) |
245 | cmm_set_timeout(long nr, long seconds) | ||
246 | { | 235 | { |
247 | cmm_timeout_pages = nr; | 236 | cmm_timeout_pages = nr; |
248 | cmm_timeout_seconds = seconds; | 237 | cmm_timeout_seconds = seconds; |
249 | cmm_set_timer(); | 238 | cmm_set_timer(); |
250 | } | 239 | } |
251 | 240 | ||
252 | static int | 241 | static int cmm_skip_blanks(char *cp, char **endp) |
253 | cmm_skip_blanks(char *cp, char **endp) | ||
254 | { | 242 | { |
255 | char *str; | 243 | char *str; |
256 | 244 | ||
257 | for (str = cp; *str == ' ' || *str == '\t'; str++); | 245 | for (str = cp; *str == ' ' || *str == '\t'; str++) |
246 | ; | ||
258 | *endp = str; | 247 | *endp = str; |
259 | return str != cp; | 248 | return str != cp; |
260 | } | 249 | } |
261 | 250 | ||
262 | #ifdef CONFIG_CMM_PROC | ||
263 | |||
264 | static struct ctl_table cmm_table[]; | 251 | static struct ctl_table cmm_table[]; |
265 | 252 | ||
266 | static int | 253 | static int cmm_pages_handler(ctl_table *ctl, int write, void __user *buffer, |
267 | cmm_pages_handler(ctl_table *ctl, int write, | 254 | size_t *lenp, loff_t *ppos) |
268 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
269 | { | 255 | { |
270 | char buf[16], *p; | 256 | char buf[16], *p; |
271 | long nr; | 257 | long nr; |
@@ -304,9 +290,8 @@ cmm_pages_handler(ctl_table *ctl, int write, | |||
304 | return 0; | 290 | return 0; |
305 | } | 291 | } |
306 | 292 | ||
307 | static int | 293 | static int cmm_timeout_handler(ctl_table *ctl, int write, void __user *buffer, |
308 | cmm_timeout_handler(ctl_table *ctl, int write, | 294 | size_t *lenp, loff_t *ppos) |
309 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
310 | { | 295 | { |
311 | char buf[64], *p; | 296 | char buf[64], *p; |
312 | long nr, seconds; | 297 | long nr, seconds; |
@@ -369,12 +354,10 @@ static struct ctl_table cmm_dir_table[] = { | |||
369 | }, | 354 | }, |
370 | { } | 355 | { } |
371 | }; | 356 | }; |
372 | #endif | ||
373 | 357 | ||
374 | #ifdef CONFIG_CMM_IUCV | 358 | #ifdef CONFIG_CMM_IUCV |
375 | #define SMSG_PREFIX "CMM" | 359 | #define SMSG_PREFIX "CMM" |
376 | static void | 360 | static void cmm_smsg_target(const char *from, char *msg) |
377 | cmm_smsg_target(char *from, char *msg) | ||
378 | { | 361 | { |
379 | long nr, seconds; | 362 | long nr, seconds; |
380 | 363 | ||
@@ -444,16 +427,13 @@ static struct notifier_block cmm_power_notifier = { | |||
444 | .notifier_call = cmm_power_event, | 427 | .notifier_call = cmm_power_event, |
445 | }; | 428 | }; |
446 | 429 | ||
447 | static int | 430 | static int cmm_init(void) |
448 | cmm_init (void) | ||
449 | { | 431 | { |
450 | int rc = -ENOMEM; | 432 | int rc = -ENOMEM; |
451 | 433 | ||
452 | #ifdef CONFIG_CMM_PROC | ||
453 | cmm_sysctl_header = register_sysctl_table(cmm_dir_table); | 434 | cmm_sysctl_header = register_sysctl_table(cmm_dir_table); |
454 | if (!cmm_sysctl_header) | 435 | if (!cmm_sysctl_header) |
455 | goto out_sysctl; | 436 | goto out_sysctl; |
456 | #endif | ||
457 | #ifdef CONFIG_CMM_IUCV | 437 | #ifdef CONFIG_CMM_IUCV |
458 | rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target); | 438 | rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target); |
459 | if (rc < 0) | 439 | if (rc < 0) |
@@ -465,8 +445,6 @@ cmm_init (void) | |||
465 | rc = register_pm_notifier(&cmm_power_notifier); | 445 | rc = register_pm_notifier(&cmm_power_notifier); |
466 | if (rc) | 446 | if (rc) |
467 | goto out_pm; | 447 | goto out_pm; |
468 | init_waitqueue_head(&cmm_thread_wait); | ||
469 | init_timer(&cmm_timer); | ||
470 | cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread"); | 448 | cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread"); |
471 | rc = IS_ERR(cmm_thread_ptr) ? PTR_ERR(cmm_thread_ptr) : 0; | 449 | rc = IS_ERR(cmm_thread_ptr) ? PTR_ERR(cmm_thread_ptr) : 0; |
472 | if (rc) | 450 | if (rc) |
@@ -482,36 +460,26 @@ out_oom_notify: | |||
482 | smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target); | 460 | smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target); |
483 | out_smsg: | 461 | out_smsg: |
484 | #endif | 462 | #endif |
485 | #ifdef CONFIG_CMM_PROC | ||
486 | unregister_sysctl_table(cmm_sysctl_header); | 463 | unregister_sysctl_table(cmm_sysctl_header); |
487 | out_sysctl: | 464 | out_sysctl: |
488 | #endif | 465 | del_timer_sync(&cmm_timer); |
489 | return rc; | 466 | return rc; |
490 | } | 467 | } |
468 | module_init(cmm_init); | ||
491 | 469 | ||
492 | static void | 470 | static void cmm_exit(void) |
493 | cmm_exit(void) | ||
494 | { | 471 | { |
495 | kthread_stop(cmm_thread_ptr); | ||
496 | unregister_pm_notifier(&cmm_power_notifier); | ||
497 | unregister_oom_notifier(&cmm_oom_nb); | ||
498 | cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list); | ||
499 | cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list); | ||
500 | #ifdef CONFIG_CMM_PROC | ||
501 | unregister_sysctl_table(cmm_sysctl_header); | 472 | unregister_sysctl_table(cmm_sysctl_header); |
502 | #endif | ||
503 | #ifdef CONFIG_CMM_IUCV | 473 | #ifdef CONFIG_CMM_IUCV |
504 | smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target); | 474 | smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target); |
505 | #endif | 475 | #endif |
476 | unregister_pm_notifier(&cmm_power_notifier); | ||
477 | unregister_oom_notifier(&cmm_oom_nb); | ||
478 | kthread_stop(cmm_thread_ptr); | ||
479 | del_timer_sync(&cmm_timer); | ||
480 | cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list); | ||
481 | cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list); | ||
506 | } | 482 | } |
507 | |||
508 | module_init(cmm_init); | ||
509 | module_exit(cmm_exit); | 483 | module_exit(cmm_exit); |
510 | 484 | ||
511 | EXPORT_SYMBOL(cmm_set_pages); | ||
512 | EXPORT_SYMBOL(cmm_get_pages); | ||
513 | EXPORT_SYMBOL(cmm_add_timed_pages); | ||
514 | EXPORT_SYMBOL(cmm_get_timed_pages); | ||
515 | EXPORT_SYMBOL(cmm_set_timeout); | ||
516 | |||
517 | MODULE_LICENSE("GPL"); | 485 | MODULE_LICENSE("GPL"); |