hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/arch/powerpc/platforms/pseries/cmm.c
....@@ -1,23 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Collaborative memory management interface.
34 *
45 * Copyright (C) 2008 IBM Corporation
56 * Author(s): Brian King (brking@linux.vnet.ibm.com),
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation; either version 2 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * This program is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- * GNU General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU General Public License
18
- * along with this program; if not, write to the Free Software
19
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
- *
217 */
228
239 #include <linux/ctype.h>
....@@ -33,10 +19,13 @@
3319 #include <linux/stringify.h>
3420 #include <linux/swap.h>
3521 #include <linux/device.h>
22
+#include <linux/mount.h>
23
+#include <linux/pseudo_fs.h>
24
+#include <linux/magic.h>
25
+#include <linux/balloon_compaction.h>
3626 #include <asm/firmware.h>
3727 #include <asm/hvcall.h>
3828 #include <asm/mmu.h>
39
-#include <asm/pgalloc.h>
4029 #include <linux/uaccess.h>
4130 #include <linux/memory.h>
4231 #include <asm/plpar_wrappers.h>
....@@ -52,12 +41,8 @@
5241 #define CMM_MIN_MEM_MB 256
5342 #define KB2PAGES(_p) ((_p)>>(PAGE_SHIFT-10))
5443 #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
55
-/*
56
- * The priority level tries to ensure that this notifier is called as
57
- * late as possible to reduce thrashing in the shared memory pool.
58
- */
44
+
5945 #define CMM_MEM_HOTPLUG_PRI 1
60
-#define CMM_MEM_ISOLATE_PRI 15
6146
6247 static unsigned int delay = CMM_DEFAULT_DELAY;
6348 static unsigned int hotplug_delay = CMM_HOTPLUG_DELAY;
....@@ -65,6 +50,8 @@
6550 static unsigned int cmm_debug = CMM_DEBUG;
6651 static unsigned int cmm_disabled = CMM_DISABLE;
6752 static unsigned long min_mem_mb = CMM_MIN_MEM_MB;
53
+static bool __read_mostly simulate;
54
+static unsigned long simulate_loan_target_kb;
6855 static struct device cmm_dev;
6956
7057 MODULE_AUTHOR("Brian King <brking@linux.vnet.ibm.com>");
....@@ -88,34 +75,30 @@
8875 module_param_named(debug, cmm_debug, uint, 0644);
8976 MODULE_PARM_DESC(debug, "Enable module debugging logging. Set to 1 to enable. "
9077 "[Default=" __stringify(CMM_DEBUG) "]");
91
-
92
-#define CMM_NR_PAGES ((PAGE_SIZE - sizeof(void *) - sizeof(unsigned long)) / sizeof(unsigned long))
78
+module_param_named(simulate, simulate, bool, 0444);
79
+MODULE_PARM_DESC(simulate, "Enable simulation mode (no communication with hw).");
9380
9481 #define cmm_dbg(...) if (cmm_debug) { printk(KERN_INFO "cmm: "__VA_ARGS__); }
9582
96
-struct cmm_page_array {
97
- struct cmm_page_array *next;
98
- unsigned long index;
99
- unsigned long page[CMM_NR_PAGES];
100
-};
101
-
102
-static unsigned long loaned_pages;
83
+static atomic_long_t loaned_pages;
10384 static unsigned long loaned_pages_target;
10485 static unsigned long oom_freed_pages;
105
-
106
-static struct cmm_page_array *cmm_page_list;
107
-static DEFINE_SPINLOCK(cmm_lock);
10886
10987 static DEFINE_MUTEX(hotplug_mutex);
11088 static int hotplug_occurred; /* protected by the hotplug mutex */
11189
11290 static struct task_struct *cmm_thread_ptr;
91
+static struct balloon_dev_info b_dev_info;
11392
114
-static long plpar_page_set_loaned(unsigned long vpa)
93
+static long plpar_page_set_loaned(struct page *page)
11594 {
95
+ const unsigned long vpa = page_to_phys(page);
11696 unsigned long cmo_page_sz = cmo_get_page_size();
11797 long rc = 0;
11898 int i;
99
+
100
+ if (unlikely(simulate))
101
+ return 0;
119102
120103 for (i = 0; !rc && i < PAGE_SIZE; i += cmo_page_sz)
121104 rc = plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED, vpa + i, 0);
....@@ -127,11 +110,15 @@
127110 return rc;
128111 }
129112
130
-static long plpar_page_set_active(unsigned long vpa)
113
+static long plpar_page_set_active(struct page *page)
131114 {
115
+ const unsigned long vpa = page_to_phys(page);
132116 unsigned long cmo_page_sz = cmo_get_page_size();
133117 long rc = 0;
134118 int i;
119
+
120
+ if (unlikely(simulate))
121
+ return 0;
135122
136123 for (i = 0; !rc && i < PAGE_SIZE; i += cmo_page_sz)
137124 rc = plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE, vpa + i, 0);
....@@ -152,8 +139,7 @@
152139 **/
153140 static long cmm_alloc_pages(long nr)
154141 {
155
- struct cmm_page_array *pa, *npa;
156
- unsigned long addr;
142
+ struct page *page;
157143 long rc;
158144
159145 cmm_dbg("Begin request for %ld pages\n", nr);
....@@ -170,46 +156,19 @@
170156 break;
171157 }
172158
173
- addr = __get_free_page(GFP_NOIO | __GFP_NOWARN |
174
- __GFP_NORETRY | __GFP_NOMEMALLOC);
175
- if (!addr)
159
+ page = balloon_page_alloc();
160
+ if (!page)
176161 break;
177
- spin_lock(&cmm_lock);
178
- pa = cmm_page_list;
179
- if (!pa || pa->index >= CMM_NR_PAGES) {
180
- /* Need a new page for the page list. */
181
- spin_unlock(&cmm_lock);
182
- npa = (struct cmm_page_array *)__get_free_page(
183
- GFP_NOIO | __GFP_NOWARN |
184
- __GFP_NORETRY | __GFP_NOMEMALLOC);
185
- if (!npa) {
186
- pr_info("%s: Can not allocate new page list\n", __func__);
187
- free_page(addr);
188
- break;
189
- }
190
- spin_lock(&cmm_lock);
191
- pa = cmm_page_list;
192
-
193
- if (!pa || pa->index >= CMM_NR_PAGES) {
194
- npa->next = pa;
195
- npa->index = 0;
196
- pa = npa;
197
- cmm_page_list = pa;
198
- } else
199
- free_page((unsigned long) npa);
200
- }
201
-
202
- if ((rc = plpar_page_set_loaned(__pa(addr)))) {
162
+ rc = plpar_page_set_loaned(page);
163
+ if (rc) {
203164 pr_err("%s: Can not set page to loaned. rc=%ld\n", __func__, rc);
204
- spin_unlock(&cmm_lock);
205
- free_page(addr);
165
+ __free_page(page);
206166 break;
207167 }
208168
209
- pa->page[pa->index++] = addr;
210
- loaned_pages++;
211
- totalram_pages--;
212
- spin_unlock(&cmm_lock);
169
+ balloon_page_enqueue(&b_dev_info, page);
170
+ atomic_long_inc(&loaned_pages);
171
+ adjust_managed_page_count(page, -1);
213172 nr--;
214173 }
215174
....@@ -226,30 +185,19 @@
226185 **/
227186 static long cmm_free_pages(long nr)
228187 {
229
- struct cmm_page_array *pa;
230
- unsigned long addr;
188
+ struct page *page;
231189
232190 cmm_dbg("Begin free of %ld pages.\n", nr);
233
- spin_lock(&cmm_lock);
234
- pa = cmm_page_list;
235191 while (nr) {
236
- if (!pa || pa->index <= 0)
192
+ page = balloon_page_dequeue(&b_dev_info);
193
+ if (!page)
237194 break;
238
- addr = pa->page[--pa->index];
239
-
240
- if (pa->index == 0) {
241
- pa = pa->next;
242
- free_page((unsigned long) cmm_page_list);
243
- cmm_page_list = pa;
244
- }
245
-
246
- plpar_page_set_active(__pa(addr));
247
- free_page(addr);
248
- loaned_pages--;
195
+ plpar_page_set_active(page);
196
+ adjust_managed_page_count(page, 1);
197
+ __free_page(page);
198
+ atomic_long_dec(&loaned_pages);
249199 nr--;
250
- totalram_pages++;
251200 }
252
- spin_unlock(&cmm_lock);
253201 cmm_dbg("End request with %ld pages unfulfilled\n", nr);
254202 return nr;
255203 }
....@@ -271,7 +219,7 @@
271219
272220 cmm_dbg("OOM processing started\n");
273221 nr = cmm_free_pages(nr);
274
- loaned_pages_target = loaned_pages;
222
+ loaned_pages_target = atomic_long_read(&loaned_pages);
275223 *freed += KB2PAGES(oom_kb) - nr;
276224 oom_freed_pages += KB2PAGES(oom_kb) - nr;
277225 cmm_dbg("OOM processing complete\n");
....@@ -288,19 +236,24 @@
288236 **/
289237 static void cmm_get_mpp(void)
290238 {
239
+ const long __loaned_pages = atomic_long_read(&loaned_pages);
240
+ const long total_pages = totalram_pages() + __loaned_pages;
291241 int rc;
292242 struct hvcall_mpp_data mpp_data;
293243 signed long active_pages_target, page_loan_request, target;
294
- signed long total_pages = totalram_pages + loaned_pages;
295244 signed long min_mem_pages = (min_mem_mb * 1024 * 1024) / PAGE_SIZE;
296245
297
- rc = h_get_mpp(&mpp_data);
298
-
299
- if (rc != H_SUCCESS)
300
- return;
301
-
302
- page_loan_request = div_s64((s64)mpp_data.loan_request, PAGE_SIZE);
303
- target = page_loan_request + (signed long)loaned_pages;
246
+ if (likely(!simulate)) {
247
+ rc = h_get_mpp(&mpp_data);
248
+ if (rc != H_SUCCESS)
249
+ return;
250
+ page_loan_request = div_s64((s64)mpp_data.loan_request,
251
+ PAGE_SIZE);
252
+ target = page_loan_request + __loaned_pages;
253
+ } else {
254
+ target = KB2PAGES(simulate_loan_target_kb);
255
+ page_loan_request = target - __loaned_pages;
256
+ }
304257
305258 if (target < 0 || total_pages < min_mem_pages)
306259 target = 0;
....@@ -321,8 +274,8 @@
321274 loaned_pages_target = target;
322275
323276 cmm_dbg("delta = %ld, loaned = %lu, target = %lu, oom = %lu, totalram = %lu\n",
324
- page_loan_request, loaned_pages, loaned_pages_target,
325
- oom_freed_pages, totalram_pages);
277
+ page_loan_request, __loaned_pages, loaned_pages_target,
278
+ oom_freed_pages, totalram_pages());
326279 }
327280
328281 static struct notifier_block cmm_oom_nb = {
....@@ -339,6 +292,7 @@
339292 static int cmm_thread(void *dummy)
340293 {
341294 unsigned long timeleft;
295
+ long __loaned_pages;
342296
343297 while (1) {
344298 timeleft = msleep_interruptible(delay * 1000);
....@@ -369,11 +323,12 @@
369323
370324 cmm_get_mpp();
371325
372
- if (loaned_pages_target > loaned_pages) {
373
- if (cmm_alloc_pages(loaned_pages_target - loaned_pages))
374
- loaned_pages_target = loaned_pages;
375
- } else if (loaned_pages_target < loaned_pages)
376
- cmm_free_pages(loaned_pages - loaned_pages_target);
326
+ __loaned_pages = atomic_long_read(&loaned_pages);
327
+ if (loaned_pages_target > __loaned_pages) {
328
+ if (cmm_alloc_pages(loaned_pages_target - __loaned_pages))
329
+ loaned_pages_target = __loaned_pages;
330
+ } else if (loaned_pages_target < __loaned_pages)
331
+ cmm_free_pages(__loaned_pages - loaned_pages_target);
377332 }
378333 return 0;
379334 }
....@@ -387,7 +342,7 @@
387342 } \
388343 static DEVICE_ATTR(name, 0444, show_##name, NULL)
389344
390
-CMM_SHOW(loaned_kb, "%lu\n", PAGES2KB(loaned_pages));
345
+CMM_SHOW(loaned_kb, "%lu\n", PAGES2KB(atomic_long_read(&loaned_pages)));
391346 CMM_SHOW(loaned_target_kb, "%lu\n", PAGES2KB(loaned_pages_target));
392347
393348 static ssize_t show_oom_pages(struct device *dev,
....@@ -419,6 +374,9 @@
419374 &dev_attr_loaned_target_kb,
420375 &dev_attr_oom_freed_kb,
421376 };
377
+
378
+static DEVICE_ULONG_ATTR(simulate_loan_target_kb, 0644,
379
+ simulate_loan_target_kb);
422380
423381 static struct bus_type cmm_subsys = {
424382 .name = "cmm",
....@@ -454,6 +412,11 @@
454412 goto fail;
455413 }
456414
415
+ if (!simulate)
416
+ return 0;
417
+ rc = device_create_file(dev, &dev_attr_simulate_loan_target_kb.attr);
418
+ if (rc)
419
+ goto fail;
457420 return 0;
458421
459422 fail:
....@@ -490,7 +453,7 @@
490453 if (cmm_thread_ptr)
491454 kthread_stop(cmm_thread_ptr);
492455 cmm_thread_ptr = NULL;
493
- cmm_free_pages(loaned_pages);
456
+ cmm_free_pages(atomic_long_read(&loaned_pages));
494457 }
495458 return NOTIFY_DONE;
496459 }
....@@ -498,142 +461,6 @@
498461 static struct notifier_block cmm_reboot_nb = {
499462 .notifier_call = cmm_reboot_notifier,
500463 };
501
-
502
-/**
503
- * cmm_count_pages - Count the number of pages loaned in a particular range.
504
- *
505
- * @arg: memory_isolate_notify structure with address range and count
506
- *
507
- * Return value:
508
- * 0 on success
509
- **/
510
-static unsigned long cmm_count_pages(void *arg)
511
-{
512
- struct memory_isolate_notify *marg = arg;
513
- struct cmm_page_array *pa;
514
- unsigned long start = (unsigned long)pfn_to_kaddr(marg->start_pfn);
515
- unsigned long end = start + (marg->nr_pages << PAGE_SHIFT);
516
- unsigned long idx;
517
-
518
- spin_lock(&cmm_lock);
519
- pa = cmm_page_list;
520
- while (pa) {
521
- if ((unsigned long)pa >= start && (unsigned long)pa < end)
522
- marg->pages_found++;
523
- for (idx = 0; idx < pa->index; idx++)
524
- if (pa->page[idx] >= start && pa->page[idx] < end)
525
- marg->pages_found++;
526
- pa = pa->next;
527
- }
528
- spin_unlock(&cmm_lock);
529
- return 0;
530
-}
531
-
532
-/**
533
- * cmm_memory_isolate_cb - Handle memory isolation notifier calls
534
- * @self: notifier block struct
535
- * @action: action to take
536
- * @arg: struct memory_isolate_notify data for handler
537
- *
538
- * Return value:
539
- * NOTIFY_OK or notifier error based on subfunction return value
540
- **/
541
-static int cmm_memory_isolate_cb(struct notifier_block *self,
542
- unsigned long action, void *arg)
543
-{
544
- int ret = 0;
545
-
546
- if (action == MEM_ISOLATE_COUNT)
547
- ret = cmm_count_pages(arg);
548
-
549
- return notifier_from_errno(ret);
550
-}
551
-
552
-static struct notifier_block cmm_mem_isolate_nb = {
553
- .notifier_call = cmm_memory_isolate_cb,
554
- .priority = CMM_MEM_ISOLATE_PRI
555
-};
556
-
557
-/**
558
- * cmm_mem_going_offline - Unloan pages where memory is to be removed
559
- * @arg: memory_notify structure with page range to be offlined
560
- *
561
- * Return value:
562
- * 0 on success
563
- **/
564
-static int cmm_mem_going_offline(void *arg)
565
-{
566
- struct memory_notify *marg = arg;
567
- unsigned long start_page = (unsigned long)pfn_to_kaddr(marg->start_pfn);
568
- unsigned long end_page = start_page + (marg->nr_pages << PAGE_SHIFT);
569
- struct cmm_page_array *pa_curr, *pa_last, *npa;
570
- unsigned long idx;
571
- unsigned long freed = 0;
572
-
573
- cmm_dbg("Memory going offline, searching 0x%lx (%ld pages).\n",
574
- start_page, marg->nr_pages);
575
- spin_lock(&cmm_lock);
576
-
577
- /* Search the page list for pages in the range to be offlined */
578
- pa_last = pa_curr = cmm_page_list;
579
- while (pa_curr) {
580
- for (idx = (pa_curr->index - 1); (idx + 1) > 0; idx--) {
581
- if ((pa_curr->page[idx] < start_page) ||
582
- (pa_curr->page[idx] >= end_page))
583
- continue;
584
-
585
- plpar_page_set_active(__pa(pa_curr->page[idx]));
586
- free_page(pa_curr->page[idx]);
587
- freed++;
588
- loaned_pages--;
589
- totalram_pages++;
590
- pa_curr->page[idx] = pa_last->page[--pa_last->index];
591
- if (pa_last->index == 0) {
592
- if (pa_curr == pa_last)
593
- pa_curr = pa_last->next;
594
- pa_last = pa_last->next;
595
- free_page((unsigned long)cmm_page_list);
596
- cmm_page_list = pa_last;
597
- }
598
- }
599
- pa_curr = pa_curr->next;
600
- }
601
-
602
- /* Search for page list structures in the range to be offlined */
603
- pa_last = NULL;
604
- pa_curr = cmm_page_list;
605
- while (pa_curr) {
606
- if (((unsigned long)pa_curr >= start_page) &&
607
- ((unsigned long)pa_curr < end_page)) {
608
- npa = (struct cmm_page_array *)__get_free_page(
609
- GFP_NOIO | __GFP_NOWARN |
610
- __GFP_NORETRY | __GFP_NOMEMALLOC);
611
- if (!npa) {
612
- spin_unlock(&cmm_lock);
613
- cmm_dbg("Failed to allocate memory for list "
614
- "management. Memory hotplug "
615
- "failed.\n");
616
- return -ENOMEM;
617
- }
618
- memcpy(npa, pa_curr, PAGE_SIZE);
619
- if (pa_curr == cmm_page_list)
620
- cmm_page_list = npa;
621
- if (pa_last)
622
- pa_last->next = npa;
623
- free_page((unsigned long) pa_curr);
624
- freed++;
625
- pa_curr = npa;
626
- }
627
-
628
- pa_last = pa_curr;
629
- pa_curr = pa_curr->next;
630
- }
631
-
632
- spin_unlock(&cmm_lock);
633
- cmm_dbg("Released %ld pages in the search range.\n", freed);
634
-
635
- return 0;
636
-}
637464
638465 /**
639466 * cmm_memory_cb - Handle memory hotplug notifier calls
....@@ -654,7 +481,6 @@
654481 case MEM_GOING_OFFLINE:
655482 mutex_lock(&hotplug_mutex);
656483 hotplug_occurred = 1;
657
- ret = cmm_mem_going_offline(arg);
658484 break;
659485 case MEM_OFFLINE:
660486 case MEM_CANCEL_OFFLINE:
....@@ -675,6 +501,116 @@
675501 .priority = CMM_MEM_HOTPLUG_PRI
676502 };
677503
504
+#ifdef CONFIG_BALLOON_COMPACTION
505
+static struct vfsmount *balloon_mnt;
506
+
507
+static int cmm_init_fs_context(struct fs_context *fc)
508
+{
509
+ return init_pseudo(fc, PPC_CMM_MAGIC) ? 0 : -ENOMEM;
510
+}
511
+
512
+static struct file_system_type balloon_fs = {
513
+ .name = "ppc-cmm",
514
+ .init_fs_context = cmm_init_fs_context,
515
+ .kill_sb = kill_anon_super,
516
+};
517
+
518
+static int cmm_migratepage(struct balloon_dev_info *b_dev_info,
519
+ struct page *newpage, struct page *page,
520
+ enum migrate_mode mode)
521
+{
522
+ unsigned long flags;
523
+
524
+ /*
525
+ * loan/"inflate" the newpage first.
526
+ *
527
+ * We might race against the cmm_thread who might discover after our
528
+ * loan request that another page is to be unloaned. However, once
529
+ * the cmm_thread runs again later, this error will automatically
530
+ * be corrected.
531
+ */
532
+ if (plpar_page_set_loaned(newpage)) {
533
+ /* Unlikely, but possible. Tell the caller not to retry now. */
534
+ pr_err_ratelimited("%s: Cannot set page to loaned.", __func__);
535
+ return -EBUSY;
536
+ }
537
+
538
+ /* balloon page list reference */
539
+ get_page(newpage);
540
+
541
+ /*
542
+ * When we migrate a page to a different zone, we have to fixup the
543
+ * count of both involved zones as we adjusted the managed page count
544
+ * when inflating.
545
+ */
546
+ if (page_zone(page) != page_zone(newpage)) {
547
+ adjust_managed_page_count(page, 1);
548
+ adjust_managed_page_count(newpage, -1);
549
+ }
550
+
551
+ spin_lock_irqsave(&b_dev_info->pages_lock, flags);
552
+ balloon_page_insert(b_dev_info, newpage);
553
+ balloon_page_delete(page);
554
+ b_dev_info->isolated_pages--;
555
+ spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
556
+
557
+ /*
558
+ * activate/"deflate" the old page. We ignore any errors just like the
559
+ * other callers.
560
+ */
561
+ plpar_page_set_active(page);
562
+
563
+ /* balloon page list reference */
564
+ put_page(page);
565
+
566
+ return MIGRATEPAGE_SUCCESS;
567
+}
568
+
569
+static int cmm_balloon_compaction_init(void)
570
+{
571
+ int rc;
572
+
573
+ balloon_devinfo_init(&b_dev_info);
574
+ b_dev_info.migratepage = cmm_migratepage;
575
+
576
+ balloon_mnt = kern_mount(&balloon_fs);
577
+ if (IS_ERR(balloon_mnt)) {
578
+ rc = PTR_ERR(balloon_mnt);
579
+ balloon_mnt = NULL;
580
+ return rc;
581
+ }
582
+
583
+ b_dev_info.inode = alloc_anon_inode(balloon_mnt->mnt_sb);
584
+ if (IS_ERR(b_dev_info.inode)) {
585
+ rc = PTR_ERR(b_dev_info.inode);
586
+ b_dev_info.inode = NULL;
587
+ kern_unmount(balloon_mnt);
588
+ balloon_mnt = NULL;
589
+ return rc;
590
+ }
591
+
592
+ b_dev_info.inode->i_mapping->a_ops = &balloon_aops;
593
+ return 0;
594
+}
595
+static void cmm_balloon_compaction_deinit(void)
596
+{
597
+ if (b_dev_info.inode)
598
+ iput(b_dev_info.inode);
599
+ b_dev_info.inode = NULL;
600
+ kern_unmount(balloon_mnt);
601
+ balloon_mnt = NULL;
602
+}
603
+#else /* CONFIG_BALLOON_COMPACTION */
604
+static int cmm_balloon_compaction_init(void)
605
+{
606
+ return 0;
607
+}
608
+
609
+static void cmm_balloon_compaction_deinit(void)
610
+{
611
+}
612
+#endif /* CONFIG_BALLOON_COMPACTION */
613
+
678614 /**
679615 * cmm_init - Module initialization
680616 *
....@@ -683,13 +619,18 @@
683619 **/
684620 static int cmm_init(void)
685621 {
686
- int rc = -ENOMEM;
622
+ int rc;
687623
688
- if (!firmware_has_feature(FW_FEATURE_CMO))
624
+ if (!firmware_has_feature(FW_FEATURE_CMO) && !simulate)
689625 return -EOPNOTSUPP;
690626
691
- if ((rc = register_oom_notifier(&cmm_oom_nb)) < 0)
627
+ rc = cmm_balloon_compaction_init();
628
+ if (rc)
692629 return rc;
630
+
631
+ rc = register_oom_notifier(&cmm_oom_nb);
632
+ if (rc < 0)
633
+ goto out_balloon_compaction;
693634
694635 if ((rc = register_reboot_notifier(&cmm_reboot_nb)))
695636 goto out_oom_notifier;
....@@ -697,12 +638,12 @@
697638 if ((rc = cmm_sysfs_register(&cmm_dev)))
698639 goto out_reboot_notifier;
699640
700
- if (register_memory_notifier(&cmm_mem_nb) ||
701
- register_memory_isolate_notifier(&cmm_mem_isolate_nb))
641
+ rc = register_memory_notifier(&cmm_mem_nb);
642
+ if (rc)
702643 goto out_unregister_notifier;
703644
704645 if (cmm_disabled)
705
- return rc;
646
+ return 0;
706647
707648 cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
708649 if (IS_ERR(cmm_thread_ptr)) {
....@@ -710,16 +651,16 @@
710651 goto out_unregister_notifier;
711652 }
712653
713
- return rc;
714
-
654
+ return 0;
715655 out_unregister_notifier:
716656 unregister_memory_notifier(&cmm_mem_nb);
717
- unregister_memory_isolate_notifier(&cmm_mem_isolate_nb);
718657 cmm_unregister_sysfs(&cmm_dev);
719658 out_reboot_notifier:
720659 unregister_reboot_notifier(&cmm_reboot_nb);
721660 out_oom_notifier:
722661 unregister_oom_notifier(&cmm_oom_nb);
662
+out_balloon_compaction:
663
+ cmm_balloon_compaction_deinit();
723664 return rc;
724665 }
725666
....@@ -736,9 +677,9 @@
736677 unregister_oom_notifier(&cmm_oom_nb);
737678 unregister_reboot_notifier(&cmm_reboot_nb);
738679 unregister_memory_notifier(&cmm_mem_nb);
739
- unregister_memory_isolate_notifier(&cmm_mem_isolate_nb);
740
- cmm_free_pages(loaned_pages);
680
+ cmm_free_pages(atomic_long_read(&loaned_pages));
741681 cmm_unregister_sysfs(&cmm_dev);
682
+ cmm_balloon_compaction_deinit();
742683 }
743684
744685 /**
....@@ -758,7 +699,7 @@
758699 if (cmm_thread_ptr)
759700 kthread_stop(cmm_thread_ptr);
760701 cmm_thread_ptr = NULL;
761
- cmm_free_pages(loaned_pages);
702
+ cmm_free_pages(atomic_long_read(&loaned_pages));
762703 } else if (!disable && cmm_disabled) {
763704 cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
764705 if (IS_ERR(cmm_thread_ptr))