aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm/cmm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/mm/cmm.c')
-rw-r--r--arch/s390/mm/cmm.c110
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
27static char *sender = "VMRMSVM"; 26static char *sender = "VMRMSVM";
@@ -52,14 +51,14 @@ static struct cmm_page_array *cmm_timed_page_list;
52static DEFINE_SPINLOCK(cmm_lock); 51static DEFINE_SPINLOCK(cmm_lock);
53 52
54static struct task_struct *cmm_thread_ptr; 53static struct task_struct *cmm_thread_ptr;
55static wait_queue_head_t cmm_thread_wait; 54static DECLARE_WAIT_QUEUE_HEAD(cmm_thread_wait);
56static struct timer_list cmm_timer; 55static DEFINE_TIMER(cmm_timer, NULL, 0, 0);
57 56
58static void cmm_timer_fn(unsigned long); 57static void cmm_timer_fn(unsigned long);
59static void cmm_set_timer(void); 58static void cmm_set_timer(void);
60 59
61static long 60static long cmm_alloc_pages(long nr, long *counter,
62cmm_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
101static long 100static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
102cmm_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
141static struct notifier_block cmm_oom_nb = { 139static struct notifier_block cmm_oom_nb = {
142 .notifier_call = cmm_oom_notify 140 .notifier_call = cmm_oom_notify,
143}; 141};
144 142
145static int 143static int cmm_thread(void *dummy)
146cmm_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
180static void 177static void cmm_kick_thread(void)
181cmm_kick_thread(void)
182{ 178{
183 wake_up(&cmm_thread_wait); 179 wake_up(&cmm_thread_wait);
184} 180}
185 181
186static void 182static void cmm_set_timer(void)
187cmm_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
204static void 199static void cmm_timer_fn(unsigned long ignored)
205cmm_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
218void 212static void cmm_set_pages(long nr)
219cmm_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
225long 218static long cmm_get_pages(void)
226cmm_get_pages(void)
227{ 219{
228 return cmm_pages; 220 return cmm_pages;
229} 221}
230 222
231void 223static void cmm_add_timed_pages(long nr)
232cmm_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
238long 229static long cmm_get_timed_pages(void)
239cmm_get_timed_pages(void)
240{ 230{
241 return cmm_timed_pages; 231 return cmm_timed_pages;
242} 232}
243 233
244void 234static void cmm_set_timeout(long nr, long seconds)
245cmm_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
252static int 241static int cmm_skip_blanks(char *cp, char **endp)
253cmm_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
264static struct ctl_table cmm_table[]; 251static struct ctl_table cmm_table[];
265 252
266static int 253static int cmm_pages_handler(ctl_table *ctl, int write, void __user *buffer,
267cmm_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
307static int 293static int cmm_timeout_handler(ctl_table *ctl, int write, void __user *buffer,
308cmm_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"
376static void 360static void cmm_smsg_target(const char *from, char *msg)
377cmm_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
447static int 430static int cmm_init(void)
448cmm_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);
483out_smsg: 461out_smsg:
484#endif 462#endif
485#ifdef CONFIG_CMM_PROC
486 unregister_sysctl_table(cmm_sysctl_header); 463 unregister_sysctl_table(cmm_sysctl_header);
487out_sysctl: 464out_sysctl:
488#endif 465 del_timer_sync(&cmm_timer);
489 return rc; 466 return rc;
490} 467}
468module_init(cmm_init);
491 469
492static void 470static void cmm_exit(void)
493cmm_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
508module_init(cmm_init);
509module_exit(cmm_exit); 483module_exit(cmm_exit);
510 484
511EXPORT_SYMBOL(cmm_set_pages);
512EXPORT_SYMBOL(cmm_get_pages);
513EXPORT_SYMBOL(cmm_add_timed_pages);
514EXPORT_SYMBOL(cmm_get_timed_pages);
515EXPORT_SYMBOL(cmm_set_timeout);
516
517MODULE_LICENSE("GPL"); 485MODULE_LICENSE("GPL");