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