blob: 42befd11225856ceefee1ebee13c3ab884e2f0d0 [file] [log] [blame]
Dave Hansen3947be12005-10-29 18:16:54 -07001/*
2 * drivers/base/memory.c - basic Memory class support
3 *
4 * Written by Matt Tolentino <matthew.e.tolentino@intel.com>
5 * Dave Hansen <haveblue@us.ibm.com>
6 *
7 * This file provides the necessary infrastructure to represent
8 * a SPARSEMEM-memory-model system's physical memory in /sysfs.
9 * All arch-independent code that assumes MEMORY_HOTPLUG requires
10 * SPARSEMEM should be contained here, or in mm/memory_hotplug.c.
11 */
12
13#include <linux/sysdev.h>
14#include <linux/module.h>
15#include <linux/init.h>
Dave Hansen3947be12005-10-29 18:16:54 -070016#include <linux/topology.h>
Randy.Dunlapc59ede72006-01-11 12:17:46 -080017#include <linux/capability.h>
Dave Hansen3947be12005-10-29 18:16:54 -070018#include <linux/device.h>
19#include <linux/memory.h>
20#include <linux/kobject.h>
21#include <linux/memory_hotplug.h>
22#include <linux/mm.h>
Daniel Walkerda19cbc2008-02-04 23:35:47 -080023#include <linux/mutex.h>
Shaohua Li9f1b16a2008-10-18 20:27:12 -070024#include <linux/stat.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090025#include <linux/slab.h>
Shaohua Li9f1b16a2008-10-18 20:27:12 -070026
Dave Hansen3947be12005-10-29 18:16:54 -070027#include <asm/atomic.h>
28#include <asm/uaccess.h>
29
Nathan Fontenot2938ffb2010-10-19 12:45:24 -050030static DEFINE_MUTEX(mem_sysfs_mutex);
31
Dave Hansen3947be12005-10-29 18:16:54 -070032#define MEMORY_CLASS_NAME "memory"
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -060033
34static int sections_per_block;
35
36static inline int base_memory_block_id(int section_nr)
37{
38 return section_nr / sections_per_block;
39}
Dave Hansen3947be12005-10-29 18:16:54 -070040
41static struct sysdev_class memory_sysdev_class = {
Kay Sieversaf5ca3f2007-12-20 02:09:39 +010042 .name = MEMORY_CLASS_NAME,
Dave Hansen3947be12005-10-29 18:16:54 -070043};
Dave Hansen3947be12005-10-29 18:16:54 -070044
Kay Sievers312c0042005-11-16 09:00:00 +010045static const char *memory_uevent_name(struct kset *kset, struct kobject *kobj)
Dave Hansen3947be12005-10-29 18:16:54 -070046{
47 return MEMORY_CLASS_NAME;
48}
49
Wanlong Gao85723942011-04-23 22:18:26 +080050static int memory_uevent(struct kset *kset, struct kobject *obj,
51 struct kobj_uevent_env *env)
Dave Hansen3947be12005-10-29 18:16:54 -070052{
53 int retval = 0;
54
55 return retval;
56}
57
Emese Revfy9cd43612009-12-31 14:52:51 +010058static const struct kset_uevent_ops memory_uevent_ops = {
Kay Sievers312c0042005-11-16 09:00:00 +010059 .name = memory_uevent_name,
60 .uevent = memory_uevent,
Dave Hansen3947be12005-10-29 18:16:54 -070061};
62
Alan Sterne041c682006-03-27 01:16:30 -080063static BLOCKING_NOTIFIER_HEAD(memory_chain);
Dave Hansen3947be12005-10-29 18:16:54 -070064
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070065unsigned long movable_reserved_start, movable_reserved_size;
66unsigned long low_power_memory_start, low_power_memory_size;
67
Andy Whitcroft98a38eb2006-01-06 00:10:35 -080068int register_memory_notifier(struct notifier_block *nb)
Dave Hansen3947be12005-10-29 18:16:54 -070069{
Alan Sterne041c682006-03-27 01:16:30 -080070 return blocking_notifier_chain_register(&memory_chain, nb);
Dave Hansen3947be12005-10-29 18:16:54 -070071}
Hannes Hering3c82c302008-05-07 14:43:01 +020072EXPORT_SYMBOL(register_memory_notifier);
Dave Hansen3947be12005-10-29 18:16:54 -070073
Andy Whitcroft98a38eb2006-01-06 00:10:35 -080074void unregister_memory_notifier(struct notifier_block *nb)
Dave Hansen3947be12005-10-29 18:16:54 -070075{
Alan Sterne041c682006-03-27 01:16:30 -080076 blocking_notifier_chain_unregister(&memory_chain, nb);
Dave Hansen3947be12005-10-29 18:16:54 -070077}
Hannes Hering3c82c302008-05-07 14:43:01 +020078EXPORT_SYMBOL(unregister_memory_notifier);
Dave Hansen3947be12005-10-29 18:16:54 -070079
Robert Jennings925cc712009-12-17 14:44:38 +000080static ATOMIC_NOTIFIER_HEAD(memory_isolate_chain);
81
82int register_memory_isolate_notifier(struct notifier_block *nb)
83{
84 return atomic_notifier_chain_register(&memory_isolate_chain, nb);
85}
86EXPORT_SYMBOL(register_memory_isolate_notifier);
87
88void unregister_memory_isolate_notifier(struct notifier_block *nb)
89{
90 atomic_notifier_chain_unregister(&memory_isolate_chain, nb);
91}
92EXPORT_SYMBOL(unregister_memory_isolate_notifier);
93
Dave Hansen3947be12005-10-29 18:16:54 -070094/*
95 * register_memory - Setup a sysfs device for a memory block
96 */
Badari Pulavarty00a41db2008-02-11 09:23:18 -080097static
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -060098int register_memory(struct memory_block *memory)
Dave Hansen3947be12005-10-29 18:16:54 -070099{
100 int error;
101
102 memory->sysdev.cls = &memory_sysdev_class;
Nathan Fontenotd3360162011-01-20 10:44:29 -0600103 memory->sysdev.id = memory->start_section_nr / sections_per_block;
Dave Hansen3947be12005-10-29 18:16:54 -0700104
105 error = sysdev_register(&memory->sysdev);
Dave Hansen3947be12005-10-29 18:16:54 -0700106 return error;
107}
108
109static void
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600110unregister_memory(struct memory_block *memory)
Dave Hansen3947be12005-10-29 18:16:54 -0700111{
112 BUG_ON(memory->sysdev.cls != &memory_sysdev_class);
Dave Hansen3947be12005-10-29 18:16:54 -0700113
Badari Pulavarty00a41db2008-02-11 09:23:18 -0800114 /* drop the ref. we got in remove_memory_block() */
115 kobject_put(&memory->sysdev.kobj);
Dave Hansen3947be12005-10-29 18:16:54 -0700116 sysdev_unregister(&memory->sysdev);
Dave Hansen3947be12005-10-29 18:16:54 -0700117}
118
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600119unsigned long __weak memory_block_size_bytes(void)
120{
121 return MIN_MEMORY_BLOCK_SIZE;
122}
123
124static unsigned long get_memory_block_size(void)
125{
126 unsigned long block_sz;
127
128 block_sz = memory_block_size_bytes();
129
130 /* Validate blk_sz is a power of 2 and not less than section size */
131 if ((block_sz & (block_sz - 1)) || (block_sz < MIN_MEMORY_BLOCK_SIZE)) {
132 WARN_ON(1);
133 block_sz = MIN_MEMORY_BLOCK_SIZE;
134 }
135
136 return block_sz;
137}
138
Dave Hansen3947be12005-10-29 18:16:54 -0700139/*
140 * use this as the physical section index that this memsection
141 * uses.
142 */
143
Nathan Fontenotd3360162011-01-20 10:44:29 -0600144static ssize_t show_mem_start_phys_index(struct sys_device *dev,
Andi Kleen4a0b2b42008-07-01 18:48:41 +0200145 struct sysdev_attribute *attr, char *buf)
Dave Hansen3947be12005-10-29 18:16:54 -0700146{
147 struct memory_block *mem =
148 container_of(dev, struct memory_block, sysdev);
Nathan Fontenotd3360162011-01-20 10:44:29 -0600149 unsigned long phys_index;
150
151 phys_index = mem->start_section_nr / sections_per_block;
152 return sprintf(buf, "%08lx\n", phys_index);
153}
154
155static ssize_t show_mem_end_phys_index(struct sys_device *dev,
156 struct sysdev_attribute *attr, char *buf)
157{
158 struct memory_block *mem =
159 container_of(dev, struct memory_block, sysdev);
160 unsigned long phys_index;
161
162 phys_index = mem->end_section_nr / sections_per_block;
163 return sprintf(buf, "%08lx\n", phys_index);
Dave Hansen3947be12005-10-29 18:16:54 -0700164}
165
166/*
Badari Pulavarty5c755e92008-07-23 21:28:19 -0700167 * Show whether the section of memory is likely to be hot-removable
168 */
Stephen Rothwell1f07be12008-07-28 11:05:04 +1000169static ssize_t show_mem_removable(struct sys_device *dev,
170 struct sysdev_attribute *attr, char *buf)
Badari Pulavarty5c755e92008-07-23 21:28:19 -0700171{
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600172 unsigned long i, pfn;
173 int ret = 1;
Badari Pulavarty5c755e92008-07-23 21:28:19 -0700174 struct memory_block *mem =
175 container_of(dev, struct memory_block, sysdev);
176
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600177 for (i = 0; i < sections_per_block; i++) {
Nathan Fontenotd3360162011-01-20 10:44:29 -0600178 pfn = section_nr_to_pfn(mem->start_section_nr + i);
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600179 ret &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
180 }
181
Badari Pulavarty5c755e92008-07-23 21:28:19 -0700182 return sprintf(buf, "%d\n", ret);
183}
184
185/*
Dave Hansen3947be12005-10-29 18:16:54 -0700186 * online, offline, going offline, etc.
187 */
Andi Kleen4a0b2b42008-07-01 18:48:41 +0200188static ssize_t show_mem_state(struct sys_device *dev,
189 struct sysdev_attribute *attr, char *buf)
Dave Hansen3947be12005-10-29 18:16:54 -0700190{
191 struct memory_block *mem =
192 container_of(dev, struct memory_block, sysdev);
193 ssize_t len = 0;
194
195 /*
196 * We can probably put these states in a nice little array
197 * so that they're not open-coded
198 */
199 switch (mem->state) {
200 case MEM_ONLINE:
201 len = sprintf(buf, "online\n");
202 break;
203 case MEM_OFFLINE:
204 len = sprintf(buf, "offline\n");
205 break;
206 case MEM_GOING_OFFLINE:
207 len = sprintf(buf, "going-offline\n");
208 break;
209 default:
210 len = sprintf(buf, "ERROR-UNKNOWN-%ld\n",
211 mem->state);
212 WARN_ON(1);
213 break;
214 }
215
216 return len;
217}
218
Yasunori Goto7b78d332007-10-21 16:41:36 -0700219int memory_notify(unsigned long val, void *v)
Dave Hansen3947be12005-10-29 18:16:54 -0700220{
Alan Sterne041c682006-03-27 01:16:30 -0800221 return blocking_notifier_call_chain(&memory_chain, val, v);
Dave Hansen3947be12005-10-29 18:16:54 -0700222}
223
Robert Jennings925cc712009-12-17 14:44:38 +0000224int memory_isolate_notify(unsigned long val, void *v)
225{
226 return atomic_notifier_call_chain(&memory_isolate_chain, val, v);
227}
228
Dave Hansen3947be12005-10-29 18:16:54 -0700229/*
230 * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is
231 * OK to have direct references to sparsemem variables in here.
232 */
233static int
Anton Blanchard5409d2c2011-05-11 17:25:14 +1000234memory_block_action(unsigned long phys_index, unsigned long action)
Dave Hansen3947be12005-10-29 18:16:54 -0700235{
236 int i;
Dave Hansen3947be12005-10-29 18:16:54 -0700237 unsigned long start_pfn, start_paddr;
Anton Blanchard5409d2c2011-05-11 17:25:14 +1000238 unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
Dave Hansen3947be12005-10-29 18:16:54 -0700239 struct page *first_page;
240 int ret;
Dave Hansen3947be12005-10-29 18:16:54 -0700241
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600242 first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT);
Dave Hansen3947be12005-10-29 18:16:54 -0700243
244 /*
245 * The probe routines leave the pages reserved, just
246 * as the bootmem code does. Make sure they're still
247 * that way.
248 */
249 if (action == MEM_ONLINE) {
Anton Blanchard5409d2c2011-05-11 17:25:14 +1000250 for (i = 0; i < nr_pages; i++) {
Dave Hansen3947be12005-10-29 18:16:54 -0700251 if (PageReserved(first_page+i))
252 continue;
253
254 printk(KERN_WARNING "section number %ld page number %d "
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600255 "not reserved, was it already online?\n",
256 phys_index, i);
Dave Hansen3947be12005-10-29 18:16:54 -0700257 return -EBUSY;
258 }
259 }
260
261 switch (action) {
262 case MEM_ONLINE:
263 start_pfn = page_to_pfn(first_page);
Anton Blanchard5409d2c2011-05-11 17:25:14 +1000264 ret = online_pages(start_pfn, nr_pages);
Dave Hansen3947be12005-10-29 18:16:54 -0700265 break;
266 case MEM_OFFLINE:
Dave Hansen3947be12005-10-29 18:16:54 -0700267 start_paddr = page_to_pfn(first_page) << PAGE_SHIFT;
268 ret = remove_memory(start_paddr,
Anton Blanchard5409d2c2011-05-11 17:25:14 +1000269 nr_pages << PAGE_SHIFT);
Dave Hansen3947be12005-10-29 18:16:54 -0700270 break;
271 default:
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600272 WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: "
273 "%ld\n", __func__, phys_index, action, action);
Dave Hansen3947be12005-10-29 18:16:54 -0700274 ret = -EINVAL;
275 }
Dave Hansen3947be12005-10-29 18:16:54 -0700276
277 return ret;
278}
279
280static int memory_block_change_state(struct memory_block *mem,
281 unsigned long to_state, unsigned long from_state_req)
282{
Andrew Mortona236c712011-05-12 12:45:31 -0700283 int ret = 0;
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600284
Daniel Walkerda19cbc2008-02-04 23:35:47 -0800285 mutex_lock(&mem->state_mutex);
Dave Hansen3947be12005-10-29 18:16:54 -0700286
287 if (mem->state != from_state_req) {
288 ret = -EINVAL;
289 goto out;
290 }
291
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600292 if (to_state == MEM_OFFLINE)
293 mem->state = MEM_GOING_OFFLINE;
294
Anton Blanchard5409d2c2011-05-11 17:25:14 +1000295 ret = memory_block_action(mem->start_section_nr, to_state);
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600296
Anton Blanchard5409d2c2011-05-11 17:25:14 +1000297 if (ret)
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600298 mem->state = from_state_req;
Anton Blanchard5409d2c2011-05-11 17:25:14 +1000299 else
Dave Hansen3947be12005-10-29 18:16:54 -0700300 mem->state = to_state;
301
302out:
Daniel Walkerda19cbc2008-02-04 23:35:47 -0800303 mutex_unlock(&mem->state_mutex);
Dave Hansen3947be12005-10-29 18:16:54 -0700304 return ret;
305}
306
307static ssize_t
Andi Kleen4a0b2b42008-07-01 18:48:41 +0200308store_mem_state(struct sys_device *dev,
309 struct sysdev_attribute *attr, const char *buf, size_t count)
Dave Hansen3947be12005-10-29 18:16:54 -0700310{
311 struct memory_block *mem;
Dave Hansen3947be12005-10-29 18:16:54 -0700312 int ret = -EINVAL;
313
314 mem = container_of(dev, struct memory_block, sysdev);
Dave Hansen3947be12005-10-29 18:16:54 -0700315
316 if (!strncmp(buf, "online", min((int)count, 6)))
317 ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
318 else if(!strncmp(buf, "offline", min((int)count, 7)))
319 ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600320
Dave Hansen3947be12005-10-29 18:16:54 -0700321 if (ret)
322 return ret;
323 return count;
324}
325
326/*
327 * phys_device is a bad name for this. What I really want
328 * is a way to differentiate between memory ranges that
329 * are part of physical devices that constitute
330 * a complete removable unit or fru.
331 * i.e. do these ranges belong to the same physical device,
332 * s.t. if I offline all of these sections I can then
333 * remove the physical device?
334 */
Andi Kleen4a0b2b42008-07-01 18:48:41 +0200335static ssize_t show_phys_device(struct sys_device *dev,
336 struct sysdev_attribute *attr, char *buf)
Dave Hansen3947be12005-10-29 18:16:54 -0700337{
338 struct memory_block *mem =
339 container_of(dev, struct memory_block, sysdev);
340 return sprintf(buf, "%d\n", mem->phys_device);
341}
342
Nathan Fontenotd3360162011-01-20 10:44:29 -0600343static SYSDEV_ATTR(phys_index, 0444, show_mem_start_phys_index, NULL);
344static SYSDEV_ATTR(end_phys_index, 0444, show_mem_end_phys_index, NULL);
Dave Hansen3947be12005-10-29 18:16:54 -0700345static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state);
346static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL);
Badari Pulavarty5c755e92008-07-23 21:28:19 -0700347static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL);
Dave Hansen3947be12005-10-29 18:16:54 -0700348
349#define mem_create_simple_file(mem, attr_name) \
350 sysdev_create_file(&mem->sysdev, &attr_##attr_name)
351#define mem_remove_simple_file(mem, attr_name) \
352 sysdev_remove_file(&mem->sysdev, &attr_##attr_name)
353
354/*
355 * Block size attribute stuff
356 */
357static ssize_t
Andi Kleen8564a6c2010-01-05 12:48:06 +0100358print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr,
359 char *buf)
Dave Hansen3947be12005-10-29 18:16:54 -0700360{
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600361 return sprintf(buf, "%lx\n", get_memory_block_size());
Dave Hansen3947be12005-10-29 18:16:54 -0700362}
363
Andi Kleen8564a6c2010-01-05 12:48:06 +0100364static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
Dave Hansen3947be12005-10-29 18:16:54 -0700365
366static int block_size_init(void)
367{
Andrew Morton28ec24e2006-12-06 20:37:29 -0800368 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
Andi Kleen8564a6c2010-01-05 12:48:06 +0100369 &attr_block_size_bytes.attr);
Dave Hansen3947be12005-10-29 18:16:54 -0700370}
371
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700372static ssize_t
373print_movable_size(struct class *class, struct class_attribute *attr, char *buf)
374{
375 return sprintf(buf, "%lx\n", movable_reserved_size);
376}
377
378static CLASS_ATTR(movable_size_bytes, 0444, print_movable_size, NULL);
379
380static int movable_size_init(void)
381{
382 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
383 &class_attr_movable_size_bytes.attr);
384}
385
386static ssize_t
387print_movable_start(struct class *class, struct class_attribute *attr, char *buf)
388{
389 return sprintf(buf, "%lx\n", movable_reserved_start);
390}
391
392static CLASS_ATTR(movable_start_bytes, 0444, print_movable_start, NULL);
393
394static int movable_start_init(void)
395{
396 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
397 &class_attr_movable_start_bytes.attr);
398}
399
400static ssize_t
401print_low_power_memory_size(struct class *class, struct class_attribute *attr, char *buf)
402{
403 return sprintf(buf, "%lx\n", low_power_memory_size);
404}
405
406static CLASS_ATTR(low_power_memory_size_bytes, 0444,
407 print_low_power_memory_size, NULL);
408
409static int low_power_memory_size_init(void)
410{
411 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
412 &class_attr_low_power_memory_size_bytes.attr);
413}
414
415static ssize_t
416print_low_power_memory_start(struct class *class, struct class_attribute *attr, char *buf)
417{
418 return sprintf(buf, "%lx\n", low_power_memory_start);
419}
420
421static CLASS_ATTR(low_power_memory_start_bytes, 0444,
422 print_low_power_memory_start, NULL);
423
424static int low_power_memory_start_init(void)
425{
426 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
427 &class_attr_low_power_memory_start_bytes.attr);
428}
429
Dave Hansen3947be12005-10-29 18:16:54 -0700430/*
431 * Some architectures will have custom drivers to do this, and
432 * will not need to do it from userspace. The fake hot-add code
433 * as well as ppc64 will do all of their discovery in userspace
434 * and will require this interface.
435 */
436#ifdef CONFIG_ARCH_MEMORY_PROBE
437static ssize_t
Andi Kleen28812fe2010-01-05 12:48:07 +0100438memory_probe_store(struct class *class, struct class_attribute *attr,
439 const char *buf, size_t count)
Dave Hansen3947be12005-10-29 18:16:54 -0700440{
441 u64 phys_addr;
Yasunori Gotobc02af92006-06-27 02:53:30 -0700442 int nid;
Nathan Fontenot6add7cd2011-01-31 10:55:23 -0600443 int i, ret;
Dave Hansen3947be12005-10-29 18:16:54 -0700444
445 phys_addr = simple_strtoull(buf, NULL, 0);
446
Nathan Fontenot6add7cd2011-01-31 10:55:23 -0600447 for (i = 0; i < sections_per_block; i++) {
448 nid = memory_add_physaddr_to_nid(phys_addr);
449 ret = add_memory(nid, phys_addr,
450 PAGES_PER_SECTION << PAGE_SHIFT);
451 if (ret)
Nikanth Karthikesan9f0af692011-03-24 11:46:18 +0530452 goto out;
Nathan Fontenot6add7cd2011-01-31 10:55:23 -0600453
454 phys_addr += MIN_MEMORY_BLOCK_SIZE;
455 }
Dave Hansen3947be12005-10-29 18:16:54 -0700456
Nikanth Karthikesan9f0af692011-03-24 11:46:18 +0530457 ret = count;
458out:
459 return ret;
Dave Hansen3947be12005-10-29 18:16:54 -0700460}
Greg Kroah-Hartmanbd796672010-01-19 13:08:16 -0800461static CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store);
Dave Hansen3947be12005-10-29 18:16:54 -0700462
463static int memory_probe_init(void)
464{
Andrew Morton28ec24e2006-12-06 20:37:29 -0800465 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
Greg Kroah-Hartmanbd796672010-01-19 13:08:16 -0800466 &class_attr_probe.attr);
Dave Hansen3947be12005-10-29 18:16:54 -0700467}
468#else
Andrew Morton28ec24e2006-12-06 20:37:29 -0800469static inline int memory_probe_init(void)
470{
471 return 0;
472}
Dave Hansen3947be12005-10-29 18:16:54 -0700473#endif
474
Andi Kleenfacb6012009-12-16 12:20:00 +0100475#ifdef CONFIG_MEMORY_FAILURE
476/*
477 * Support for offlining pages of memory
478 */
479
480/* Soft offline a page */
481static ssize_t
Andi Kleen28812fe2010-01-05 12:48:07 +0100482store_soft_offline_page(struct class *class,
483 struct class_attribute *attr,
484 const char *buf, size_t count)
Andi Kleenfacb6012009-12-16 12:20:00 +0100485{
486 int ret;
487 u64 pfn;
488 if (!capable(CAP_SYS_ADMIN))
489 return -EPERM;
490 if (strict_strtoull(buf, 0, &pfn) < 0)
491 return -EINVAL;
492 pfn >>= PAGE_SHIFT;
493 if (!pfn_valid(pfn))
494 return -ENXIO;
495 ret = soft_offline_page(pfn_to_page(pfn), 0);
496 return ret == 0 ? count : ret;
497}
498
499/* Forcibly offline a page, including killing processes. */
500static ssize_t
Andi Kleen28812fe2010-01-05 12:48:07 +0100501store_hard_offline_page(struct class *class,
502 struct class_attribute *attr,
503 const char *buf, size_t count)
Andi Kleenfacb6012009-12-16 12:20:00 +0100504{
505 int ret;
506 u64 pfn;
507 if (!capable(CAP_SYS_ADMIN))
508 return -EPERM;
509 if (strict_strtoull(buf, 0, &pfn) < 0)
510 return -EINVAL;
511 pfn >>= PAGE_SHIFT;
512 ret = __memory_failure(pfn, 0, 0);
513 return ret ? ret : count;
514}
515
Greg Kroah-Hartmanbd796672010-01-19 13:08:16 -0800516static CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page);
517static CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page);
Andi Kleenfacb6012009-12-16 12:20:00 +0100518
519static __init int memory_fail_init(void)
520{
521 int err;
522
523 err = sysfs_create_file(&memory_sysdev_class.kset.kobj,
Greg Kroah-Hartmanbd796672010-01-19 13:08:16 -0800524 &class_attr_soft_offline_page.attr);
Andi Kleenfacb6012009-12-16 12:20:00 +0100525 if (!err)
526 err = sysfs_create_file(&memory_sysdev_class.kset.kobj,
Greg Kroah-Hartmanbd796672010-01-19 13:08:16 -0800527 &class_attr_hard_offline_page.attr);
Andi Kleenfacb6012009-12-16 12:20:00 +0100528 return err;
529}
530#else
531static inline int memory_fail_init(void)
532{
533 return 0;
534}
535#endif
536
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700537#ifdef CONFIG_ARCH_MEMORY_REMOVE
538static ssize_t
539memory_remove_store(struct class *class, struct class_attribute *attr,
540 const char *buf, size_t count)
541{
542 u64 phys_addr;
543 int ret;
544
545 phys_addr = simple_strtoull(buf, NULL, 0);
546
547 ret = physical_remove_memory(phys_addr,
548 PAGES_PER_SECTION << PAGE_SHIFT);
549
550 if (ret)
551 count = ret;
552
553 return count;
554}
555static CLASS_ATTR(remove, S_IWUSR, NULL, memory_remove_store);
556
557static int memory_remove_init(void)
558{
559 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
560 &class_attr_remove.attr);
561}
562
563static ssize_t
564memory_active_store(struct class *class, struct class_attribute *attr,
565 const char *buf, size_t count)
566{
567 u64 phys_addr;
568 int ret;
569
570 phys_addr = simple_strtoull(buf, NULL, 0);
571
572 ret = physical_active_memory(phys_addr,
573 PAGES_PER_SECTION << PAGE_SHIFT);
574
575 if (ret)
576 count = ret;
577
578 return count;
579}
580static CLASS_ATTR(active, S_IWUSR, NULL, memory_active_store);
581
582static int memory_active_init(void)
583{
584 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
585 &class_attr_active.attr);
586}
587
588static ssize_t
589memory_low_power_store(struct class *class, struct class_attribute *attr,
590 const char *buf, size_t count)
591{
592 u64 phys_addr;
593 int ret;
594
595 phys_addr = simple_strtoull(buf, NULL, 0);
596
597 ret = physical_low_power_memory(phys_addr,
598 PAGES_PER_SECTION << PAGE_SHIFT);
599
600 if (ret)
601 count = ret;
602
603 return count;
604}
605static CLASS_ATTR(low_power, S_IWUSR, NULL, memory_low_power_store);
606
607static int memory_low_power_init(void)
608{
609 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
610 &class_attr_low_power.attr);
611}
612#else
613static inline int memory_remove_init(void)
614{
615 return 0;
616}
617static inline int memory_active_init(void)
618{
619 return 0;
620}
621static inline int memory_low_power_init(void)
622{
623 return 0;
624}
625#endif
626
Dave Hansen3947be12005-10-29 18:16:54 -0700627/*
628 * Note that phys_device is optional. It is here to allow for
629 * differentiation between which *physical* devices each
630 * section belongs to...
631 */
Heiko Carstensbc32df02010-03-15 00:35:03 -0400632int __weak arch_get_memory_phys_device(unsigned long start_pfn)
633{
634 return 0;
635}
Dave Hansen3947be12005-10-29 18:16:54 -0700636
Robin Holt98383032010-09-29 14:00:55 -0500637struct memory_block *find_memory_block_hinted(struct mem_section *section,
638 struct memory_block *hint)
639{
640 struct kobject *kobj;
641 struct sys_device *sysdev;
642 struct memory_block *mem;
643 char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600644 int block_id = base_memory_block_id(__section_nr(section));
Robin Holt98383032010-09-29 14:00:55 -0500645
646 kobj = hint ? &hint->sysdev.kobj : NULL;
647
648 /*
649 * This only works because we know that section == sysdev->id
650 * slightly redundant with sysdev_register()
651 */
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600652 sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, block_id);
Robin Holt98383032010-09-29 14:00:55 -0500653
654 kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj);
655 if (!kobj)
656 return NULL;
657
658 sysdev = container_of(kobj, struct sys_device, kobj);
659 mem = container_of(sysdev, struct memory_block, sysdev);
660
661 return mem;
662}
663
Dave Hansen3947be12005-10-29 18:16:54 -0700664/*
665 * For now, we have a linear search to go find the appropriate
666 * memory_block corresponding to a particular phys_index. If
667 * this gets to be a real problem, we can always use a radix
668 * tree or something here.
669 *
670 * This could be made generic for all sysdev classes.
671 */
Gary Hadec04fc582009-01-06 14:39:14 -0800672struct memory_block *find_memory_block(struct mem_section *section)
Dave Hansen3947be12005-10-29 18:16:54 -0700673{
Robin Holt98383032010-09-29 14:00:55 -0500674 return find_memory_block_hinted(section, NULL);
Dave Hansen3947be12005-10-29 18:16:54 -0700675}
676
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600677static int init_memory_block(struct memory_block **memory,
678 struct mem_section *section, unsigned long state)
Nathan Fontenote4619c82010-10-19 12:44:20 -0500679{
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600680 struct memory_block *mem;
Nathan Fontenote4619c82010-10-19 12:44:20 -0500681 unsigned long start_pfn;
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600682 int scn_nr;
Nathan Fontenote4619c82010-10-19 12:44:20 -0500683 int ret = 0;
684
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600685 mem = kzalloc(sizeof(*mem), GFP_KERNEL);
Nathan Fontenote4619c82010-10-19 12:44:20 -0500686 if (!mem)
687 return -ENOMEM;
688
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600689 scn_nr = __section_nr(section);
Nathan Fontenotd3360162011-01-20 10:44:29 -0600690 mem->start_section_nr =
691 base_memory_block_id(scn_nr) * sections_per_block;
692 mem->end_section_nr = mem->start_section_nr + sections_per_block - 1;
Nathan Fontenote4619c82010-10-19 12:44:20 -0500693 mem->state = state;
Nathan Fontenot07681212010-10-19 12:46:19 -0500694 mem->section_count++;
Nathan Fontenote4619c82010-10-19 12:44:20 -0500695 mutex_init(&mem->state_mutex);
Nathan Fontenotd3360162011-01-20 10:44:29 -0600696 start_pfn = section_nr_to_pfn(mem->start_section_nr);
Nathan Fontenote4619c82010-10-19 12:44:20 -0500697 mem->phys_device = arch_get_memory_phys_device(start_pfn);
698
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600699 ret = register_memory(mem);
Nathan Fontenote4619c82010-10-19 12:44:20 -0500700 if (!ret)
701 ret = mem_create_simple_file(mem, phys_index);
702 if (!ret)
Nathan Fontenotd3360162011-01-20 10:44:29 -0600703 ret = mem_create_simple_file(mem, end_phys_index);
704 if (!ret)
Nathan Fontenote4619c82010-10-19 12:44:20 -0500705 ret = mem_create_simple_file(mem, state);
706 if (!ret)
707 ret = mem_create_simple_file(mem, phys_device);
708 if (!ret)
709 ret = mem_create_simple_file(mem, removable);
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600710
711 *memory = mem;
712 return ret;
713}
714
715static int add_memory_section(int nid, struct mem_section *section,
716 unsigned long state, enum mem_add_context context)
717{
718 struct memory_block *mem;
719 int ret = 0;
720
721 mutex_lock(&mem_sysfs_mutex);
722
723 mem = find_memory_block(section);
724 if (mem) {
725 mem->section_count++;
726 kobject_put(&mem->sysdev.kobj);
727 } else
728 ret = init_memory_block(&mem, section, state);
729
Nathan Fontenote4619c82010-10-19 12:44:20 -0500730 if (!ret) {
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600731 if (context == HOTPLUG &&
732 mem->section_count == sections_per_block)
Nathan Fontenote4619c82010-10-19 12:44:20 -0500733 ret = register_mem_sect_under_node(mem, nid);
734 }
735
Nathan Fontenot2938ffb2010-10-19 12:45:24 -0500736 mutex_unlock(&mem_sysfs_mutex);
Nathan Fontenote4619c82010-10-19 12:44:20 -0500737 return ret;
738}
739
Dave Hansen3947be12005-10-29 18:16:54 -0700740int remove_memory_block(unsigned long node_id, struct mem_section *section,
741 int phys_device)
742{
743 struct memory_block *mem;
744
Nathan Fontenot2938ffb2010-10-19 12:45:24 -0500745 mutex_lock(&mem_sysfs_mutex);
Dave Hansen3947be12005-10-29 18:16:54 -0700746 mem = find_memory_block(section);
Nathan Fontenotd3360162011-01-20 10:44:29 -0600747 unregister_mem_sect_under_nodes(mem, __section_nr(section));
Nathan Fontenot07681212010-10-19 12:46:19 -0500748
749 mem->section_count--;
750 if (mem->section_count == 0) {
Nathan Fontenot07681212010-10-19 12:46:19 -0500751 mem_remove_simple_file(mem, phys_index);
Nathan Fontenotd3360162011-01-20 10:44:29 -0600752 mem_remove_simple_file(mem, end_phys_index);
Nathan Fontenot07681212010-10-19 12:46:19 -0500753 mem_remove_simple_file(mem, state);
754 mem_remove_simple_file(mem, phys_device);
755 mem_remove_simple_file(mem, removable);
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600756 unregister_memory(mem);
757 kfree(mem);
758 } else
759 kobject_put(&mem->sysdev.kobj);
Dave Hansen3947be12005-10-29 18:16:54 -0700760
Nathan Fontenot2938ffb2010-10-19 12:45:24 -0500761 mutex_unlock(&mem_sysfs_mutex);
Dave Hansen3947be12005-10-29 18:16:54 -0700762 return 0;
763}
764
765/*
766 * need an interface for the VM to add new memory regions,
767 * but without onlining it.
768 */
Gary Hadec04fc582009-01-06 14:39:14 -0800769int register_new_memory(int nid, struct mem_section *section)
Dave Hansen3947be12005-10-29 18:16:54 -0700770{
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600771 return add_memory_section(nid, section, MEM_OFFLINE, HOTPLUG);
Dave Hansen3947be12005-10-29 18:16:54 -0700772}
773
774int unregister_memory_section(struct mem_section *section)
775{
Andy Whitcroft540557b2007-10-16 01:24:11 -0700776 if (!present_section(section))
Dave Hansen3947be12005-10-29 18:16:54 -0700777 return -EINVAL;
778
779 return remove_memory_block(0, section, 0);
780}
781
782/*
783 * Initialize the sysfs support for memory devices...
784 */
785int __init memory_dev_init(void)
786{
787 unsigned int i;
788 int ret;
Andrew Morton28ec24e2006-12-06 20:37:29 -0800789 int err;
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600790 unsigned long block_sz;
Dave Hansen3947be12005-10-29 18:16:54 -0700791
Kay Sievers312c0042005-11-16 09:00:00 +0100792 memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops;
Dave Hansen3947be12005-10-29 18:16:54 -0700793 ret = sysdev_class_register(&memory_sysdev_class);
Andrew Morton28ec24e2006-12-06 20:37:29 -0800794 if (ret)
795 goto out;
Dave Hansen3947be12005-10-29 18:16:54 -0700796
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600797 block_sz = get_memory_block_size();
798 sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
799
Dave Hansen3947be12005-10-29 18:16:54 -0700800 /*
801 * Create entries for memory sections that were found
802 * during boot and have been initialized
803 */
804 for (i = 0; i < NR_MEM_SECTIONS; i++) {
Andy Whitcroft540557b2007-10-16 01:24:11 -0700805 if (!present_section_nr(i))
Dave Hansen3947be12005-10-29 18:16:54 -0700806 continue;
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600807 err = add_memory_section(0, __nr_to_section(i), MEM_ONLINE,
808 BOOT);
Andrew Morton28ec24e2006-12-06 20:37:29 -0800809 if (!ret)
810 ret = err;
Dave Hansen3947be12005-10-29 18:16:54 -0700811 }
812
Andrew Morton28ec24e2006-12-06 20:37:29 -0800813 err = memory_probe_init();
814 if (!ret)
815 ret = err;
Andi Kleenfacb6012009-12-16 12:20:00 +0100816 err = memory_fail_init();
817 if (!ret)
818 ret = err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700819 err = memory_remove_init();
820 if (!ret)
821 ret = err;
822 err = memory_active_init();
823 if (!ret)
824 ret = err;
825 err = memory_low_power_init();
826 if (!ret)
827 ret = err;
Andrew Morton28ec24e2006-12-06 20:37:29 -0800828 err = block_size_init();
829 if (!ret)
830 ret = err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700831 err = movable_size_init();
832 if (!ret)
833 ret = err;
834 err = movable_start_init();
835 if (!ret)
836 ret = err;
837 err = low_power_memory_size_init();
838 if (!ret)
839 ret = err;
840 err = low_power_memory_start_init();
841 if (!ret)
842 ret = err;
Andrew Morton28ec24e2006-12-06 20:37:29 -0800843out:
844 if (ret)
Harvey Harrison2b3a3022008-03-04 16:41:05 -0800845 printk(KERN_ERR "%s() failed: %d\n", __func__, ret);
Dave Hansen3947be12005-10-29 18:16:54 -0700846 return ret;
847}