blob: 8a46a2e59eabca17d932b1be2d82fb5166c85252 [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++) {
Hanumant Singh28976a82012-04-18 14:14:21 -0700251 if (page_is_ram(page_to_pfn(first_page+i))) {
252 if (PageReserved(first_page+i))
253 continue;
254 printk(KERN_WARNING
255 "section number %ld page number"
256 " %d not reserved, was it "
257 " already online?\n",
258 phys_index, i);
259 return -EBUSY;
260 }
Dave Hansen3947be12005-10-29 18:16:54 -0700261 }
262 }
263
264 switch (action) {
265 case MEM_ONLINE:
266 start_pfn = page_to_pfn(first_page);
Anton Blanchard5409d2c2011-05-11 17:25:14 +1000267 ret = online_pages(start_pfn, nr_pages);
Dave Hansen3947be12005-10-29 18:16:54 -0700268 break;
269 case MEM_OFFLINE:
Dave Hansen3947be12005-10-29 18:16:54 -0700270 start_paddr = page_to_pfn(first_page) << PAGE_SHIFT;
271 ret = remove_memory(start_paddr,
Anton Blanchard5409d2c2011-05-11 17:25:14 +1000272 nr_pages << PAGE_SHIFT);
Dave Hansen3947be12005-10-29 18:16:54 -0700273 break;
274 default:
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600275 WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: "
276 "%ld\n", __func__, phys_index, action, action);
Dave Hansen3947be12005-10-29 18:16:54 -0700277 ret = -EINVAL;
278 }
Dave Hansen3947be12005-10-29 18:16:54 -0700279
280 return ret;
281}
282
283static int memory_block_change_state(struct memory_block *mem,
284 unsigned long to_state, unsigned long from_state_req)
285{
Andrew Mortona236c712011-05-12 12:45:31 -0700286 int ret = 0;
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600287
Daniel Walkerda19cbc2008-02-04 23:35:47 -0800288 mutex_lock(&mem->state_mutex);
Dave Hansen3947be12005-10-29 18:16:54 -0700289
290 if (mem->state != from_state_req) {
291 ret = -EINVAL;
292 goto out;
293 }
294
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600295 if (to_state == MEM_OFFLINE)
296 mem->state = MEM_GOING_OFFLINE;
297
Anton Blanchard5409d2c2011-05-11 17:25:14 +1000298 ret = memory_block_action(mem->start_section_nr, to_state);
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600299
Anton Blanchard5409d2c2011-05-11 17:25:14 +1000300 if (ret)
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600301 mem->state = from_state_req;
Anton Blanchard5409d2c2011-05-11 17:25:14 +1000302 else
Dave Hansen3947be12005-10-29 18:16:54 -0700303 mem->state = to_state;
304
305out:
Daniel Walkerda19cbc2008-02-04 23:35:47 -0800306 mutex_unlock(&mem->state_mutex);
Dave Hansen3947be12005-10-29 18:16:54 -0700307 return ret;
308}
309
310static ssize_t
Andi Kleen4a0b2b42008-07-01 18:48:41 +0200311store_mem_state(struct sys_device *dev,
312 struct sysdev_attribute *attr, const char *buf, size_t count)
Dave Hansen3947be12005-10-29 18:16:54 -0700313{
314 struct memory_block *mem;
Dave Hansen3947be12005-10-29 18:16:54 -0700315 int ret = -EINVAL;
316
317 mem = container_of(dev, struct memory_block, sysdev);
Dave Hansen3947be12005-10-29 18:16:54 -0700318
319 if (!strncmp(buf, "online", min((int)count, 6)))
320 ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
321 else if(!strncmp(buf, "offline", min((int)count, 7)))
322 ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600323
Dave Hansen3947be12005-10-29 18:16:54 -0700324 if (ret)
325 return ret;
326 return count;
327}
328
329/*
330 * phys_device is a bad name for this. What I really want
331 * is a way to differentiate between memory ranges that
332 * are part of physical devices that constitute
333 * a complete removable unit or fru.
334 * i.e. do these ranges belong to the same physical device,
335 * s.t. if I offline all of these sections I can then
336 * remove the physical device?
337 */
Andi Kleen4a0b2b42008-07-01 18:48:41 +0200338static ssize_t show_phys_device(struct sys_device *dev,
339 struct sysdev_attribute *attr, char *buf)
Dave Hansen3947be12005-10-29 18:16:54 -0700340{
341 struct memory_block *mem =
342 container_of(dev, struct memory_block, sysdev);
343 return sprintf(buf, "%d\n", mem->phys_device);
344}
345
Nathan Fontenotd3360162011-01-20 10:44:29 -0600346static SYSDEV_ATTR(phys_index, 0444, show_mem_start_phys_index, NULL);
347static SYSDEV_ATTR(end_phys_index, 0444, show_mem_end_phys_index, NULL);
Dave Hansen3947be12005-10-29 18:16:54 -0700348static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state);
349static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL);
Badari Pulavarty5c755e92008-07-23 21:28:19 -0700350static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL);
Dave Hansen3947be12005-10-29 18:16:54 -0700351
352#define mem_create_simple_file(mem, attr_name) \
353 sysdev_create_file(&mem->sysdev, &attr_##attr_name)
354#define mem_remove_simple_file(mem, attr_name) \
355 sysdev_remove_file(&mem->sysdev, &attr_##attr_name)
356
357/*
358 * Block size attribute stuff
359 */
360static ssize_t
Andi Kleen8564a6c2010-01-05 12:48:06 +0100361print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr,
362 char *buf)
Dave Hansen3947be12005-10-29 18:16:54 -0700363{
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600364 return sprintf(buf, "%lx\n", get_memory_block_size());
Dave Hansen3947be12005-10-29 18:16:54 -0700365}
366
Andi Kleen8564a6c2010-01-05 12:48:06 +0100367static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
Dave Hansen3947be12005-10-29 18:16:54 -0700368
369static int block_size_init(void)
370{
Andrew Morton28ec24e2006-12-06 20:37:29 -0800371 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
Andi Kleen8564a6c2010-01-05 12:48:06 +0100372 &attr_block_size_bytes.attr);
Dave Hansen3947be12005-10-29 18:16:54 -0700373}
374
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700375static ssize_t
376print_movable_size(struct class *class, struct class_attribute *attr, char *buf)
377{
378 return sprintf(buf, "%lx\n", movable_reserved_size);
379}
380
381static CLASS_ATTR(movable_size_bytes, 0444, print_movable_size, NULL);
382
383static int movable_size_init(void)
384{
385 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
386 &class_attr_movable_size_bytes.attr);
387}
388
389static ssize_t
390print_movable_start(struct class *class, struct class_attribute *attr, char *buf)
391{
392 return sprintf(buf, "%lx\n", movable_reserved_start);
393}
394
395static CLASS_ATTR(movable_start_bytes, 0444, print_movable_start, NULL);
396
397static int movable_start_init(void)
398{
399 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
400 &class_attr_movable_start_bytes.attr);
401}
402
403static ssize_t
404print_low_power_memory_size(struct class *class, struct class_attribute *attr, char *buf)
405{
406 return sprintf(buf, "%lx\n", low_power_memory_size);
407}
408
409static CLASS_ATTR(low_power_memory_size_bytes, 0444,
410 print_low_power_memory_size, NULL);
411
412static int low_power_memory_size_init(void)
413{
414 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
415 &class_attr_low_power_memory_size_bytes.attr);
416}
417
418static ssize_t
419print_low_power_memory_start(struct class *class, struct class_attribute *attr, char *buf)
420{
421 return sprintf(buf, "%lx\n", low_power_memory_start);
422}
423
424static CLASS_ATTR(low_power_memory_start_bytes, 0444,
425 print_low_power_memory_start, NULL);
426
427static int low_power_memory_start_init(void)
428{
429 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
430 &class_attr_low_power_memory_start_bytes.attr);
431}
432
Dave Hansen3947be12005-10-29 18:16:54 -0700433/*
434 * Some architectures will have custom drivers to do this, and
435 * will not need to do it from userspace. The fake hot-add code
436 * as well as ppc64 will do all of their discovery in userspace
437 * and will require this interface.
438 */
439#ifdef CONFIG_ARCH_MEMORY_PROBE
440static ssize_t
Andi Kleen28812fe2010-01-05 12:48:07 +0100441memory_probe_store(struct class *class, struct class_attribute *attr,
442 const char *buf, size_t count)
Dave Hansen3947be12005-10-29 18:16:54 -0700443{
444 u64 phys_addr;
Yasunori Gotobc02af92006-06-27 02:53:30 -0700445 int nid;
Nathan Fontenot6add7cd2011-01-31 10:55:23 -0600446 int i, ret;
Dave Hansen3947be12005-10-29 18:16:54 -0700447
448 phys_addr = simple_strtoull(buf, NULL, 0);
449
Nathan Fontenot6add7cd2011-01-31 10:55:23 -0600450 for (i = 0; i < sections_per_block; i++) {
451 nid = memory_add_physaddr_to_nid(phys_addr);
452 ret = add_memory(nid, phys_addr,
453 PAGES_PER_SECTION << PAGE_SHIFT);
454 if (ret)
Nikanth Karthikesan9f0af692011-03-24 11:46:18 +0530455 goto out;
Nathan Fontenot6add7cd2011-01-31 10:55:23 -0600456
457 phys_addr += MIN_MEMORY_BLOCK_SIZE;
458 }
Dave Hansen3947be12005-10-29 18:16:54 -0700459
Nikanth Karthikesan9f0af692011-03-24 11:46:18 +0530460 ret = count;
461out:
462 return ret;
Dave Hansen3947be12005-10-29 18:16:54 -0700463}
Greg Kroah-Hartmanbd796672010-01-19 13:08:16 -0800464static CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store);
Dave Hansen3947be12005-10-29 18:16:54 -0700465
466static int memory_probe_init(void)
467{
Andrew Morton28ec24e2006-12-06 20:37:29 -0800468 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
Greg Kroah-Hartmanbd796672010-01-19 13:08:16 -0800469 &class_attr_probe.attr);
Dave Hansen3947be12005-10-29 18:16:54 -0700470}
471#else
Andrew Morton28ec24e2006-12-06 20:37:29 -0800472static inline int memory_probe_init(void)
473{
474 return 0;
475}
Dave Hansen3947be12005-10-29 18:16:54 -0700476#endif
477
Andi Kleenfacb6012009-12-16 12:20:00 +0100478#ifdef CONFIG_MEMORY_FAILURE
479/*
480 * Support for offlining pages of memory
481 */
482
483/* Soft offline a page */
484static ssize_t
Andi Kleen28812fe2010-01-05 12:48:07 +0100485store_soft_offline_page(struct class *class,
486 struct class_attribute *attr,
487 const char *buf, size_t count)
Andi Kleenfacb6012009-12-16 12:20:00 +0100488{
489 int ret;
490 u64 pfn;
491 if (!capable(CAP_SYS_ADMIN))
492 return -EPERM;
493 if (strict_strtoull(buf, 0, &pfn) < 0)
494 return -EINVAL;
495 pfn >>= PAGE_SHIFT;
496 if (!pfn_valid(pfn))
497 return -ENXIO;
498 ret = soft_offline_page(pfn_to_page(pfn), 0);
499 return ret == 0 ? count : ret;
500}
501
502/* Forcibly offline a page, including killing processes. */
503static ssize_t
Andi Kleen28812fe2010-01-05 12:48:07 +0100504store_hard_offline_page(struct class *class,
505 struct class_attribute *attr,
506 const char *buf, size_t count)
Andi Kleenfacb6012009-12-16 12:20:00 +0100507{
508 int ret;
509 u64 pfn;
510 if (!capable(CAP_SYS_ADMIN))
511 return -EPERM;
512 if (strict_strtoull(buf, 0, &pfn) < 0)
513 return -EINVAL;
514 pfn >>= PAGE_SHIFT;
515 ret = __memory_failure(pfn, 0, 0);
516 return ret ? ret : count;
517}
518
Greg Kroah-Hartmanbd796672010-01-19 13:08:16 -0800519static CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page);
520static CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page);
Andi Kleenfacb6012009-12-16 12:20:00 +0100521
522static __init int memory_fail_init(void)
523{
524 int err;
525
526 err = sysfs_create_file(&memory_sysdev_class.kset.kobj,
Greg Kroah-Hartmanbd796672010-01-19 13:08:16 -0800527 &class_attr_soft_offline_page.attr);
Andi Kleenfacb6012009-12-16 12:20:00 +0100528 if (!err)
529 err = sysfs_create_file(&memory_sysdev_class.kset.kobj,
Greg Kroah-Hartmanbd796672010-01-19 13:08:16 -0800530 &class_attr_hard_offline_page.attr);
Andi Kleenfacb6012009-12-16 12:20:00 +0100531 return err;
532}
533#else
534static inline int memory_fail_init(void)
535{
536 return 0;
537}
538#endif
539
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700540#ifdef CONFIG_ARCH_MEMORY_REMOVE
541static ssize_t
542memory_remove_store(struct class *class, struct class_attribute *attr,
543 const char *buf, size_t count)
544{
545 u64 phys_addr;
546 int ret;
547
548 phys_addr = simple_strtoull(buf, NULL, 0);
549
550 ret = physical_remove_memory(phys_addr,
551 PAGES_PER_SECTION << PAGE_SHIFT);
552
553 if (ret)
554 count = ret;
555
556 return count;
557}
558static CLASS_ATTR(remove, S_IWUSR, NULL, memory_remove_store);
559
560static int memory_remove_init(void)
561{
562 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
563 &class_attr_remove.attr);
564}
565
566static ssize_t
567memory_active_store(struct class *class, struct class_attribute *attr,
568 const char *buf, size_t count)
569{
570 u64 phys_addr;
571 int ret;
572
573 phys_addr = simple_strtoull(buf, NULL, 0);
574
575 ret = physical_active_memory(phys_addr,
576 PAGES_PER_SECTION << PAGE_SHIFT);
577
578 if (ret)
579 count = ret;
580
581 return count;
582}
583static CLASS_ATTR(active, S_IWUSR, NULL, memory_active_store);
584
585static int memory_active_init(void)
586{
587 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
588 &class_attr_active.attr);
589}
590
591static ssize_t
592memory_low_power_store(struct class *class, struct class_attribute *attr,
593 const char *buf, size_t count)
594{
595 u64 phys_addr;
596 int ret;
597
598 phys_addr = simple_strtoull(buf, NULL, 0);
599
600 ret = physical_low_power_memory(phys_addr,
601 PAGES_PER_SECTION << PAGE_SHIFT);
602
603 if (ret)
604 count = ret;
605
606 return count;
607}
608static CLASS_ATTR(low_power, S_IWUSR, NULL, memory_low_power_store);
609
610static int memory_low_power_init(void)
611{
612 return sysfs_create_file(&memory_sysdev_class.kset.kobj,
613 &class_attr_low_power.attr);
614}
615#else
616static inline int memory_remove_init(void)
617{
618 return 0;
619}
620static inline int memory_active_init(void)
621{
622 return 0;
623}
624static inline int memory_low_power_init(void)
625{
626 return 0;
627}
628#endif
629
Dave Hansen3947be12005-10-29 18:16:54 -0700630/*
631 * Note that phys_device is optional. It is here to allow for
632 * differentiation between which *physical* devices each
633 * section belongs to...
634 */
Heiko Carstensbc32df02010-03-15 00:35:03 -0400635int __weak arch_get_memory_phys_device(unsigned long start_pfn)
636{
637 return 0;
638}
Dave Hansen3947be12005-10-29 18:16:54 -0700639
Robin Holt98383032010-09-29 14:00:55 -0500640struct memory_block *find_memory_block_hinted(struct mem_section *section,
641 struct memory_block *hint)
642{
643 struct kobject *kobj;
644 struct sys_device *sysdev;
645 struct memory_block *mem;
646 char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600647 int block_id = base_memory_block_id(__section_nr(section));
Robin Holt98383032010-09-29 14:00:55 -0500648
649 kobj = hint ? &hint->sysdev.kobj : NULL;
650
651 /*
652 * This only works because we know that section == sysdev->id
653 * slightly redundant with sysdev_register()
654 */
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600655 sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, block_id);
Robin Holt98383032010-09-29 14:00:55 -0500656
657 kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj);
658 if (!kobj)
659 return NULL;
660
661 sysdev = container_of(kobj, struct sys_device, kobj);
662 mem = container_of(sysdev, struct memory_block, sysdev);
663
664 return mem;
665}
666
Dave Hansen3947be12005-10-29 18:16:54 -0700667/*
668 * For now, we have a linear search to go find the appropriate
669 * memory_block corresponding to a particular phys_index. If
670 * this gets to be a real problem, we can always use a radix
671 * tree or something here.
672 *
673 * This could be made generic for all sysdev classes.
674 */
Gary Hadec04fc582009-01-06 14:39:14 -0800675struct memory_block *find_memory_block(struct mem_section *section)
Dave Hansen3947be12005-10-29 18:16:54 -0700676{
Robin Holt98383032010-09-29 14:00:55 -0500677 return find_memory_block_hinted(section, NULL);
Dave Hansen3947be12005-10-29 18:16:54 -0700678}
679
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600680static int init_memory_block(struct memory_block **memory,
681 struct mem_section *section, unsigned long state)
Nathan Fontenote4619c82010-10-19 12:44:20 -0500682{
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600683 struct memory_block *mem;
Nathan Fontenote4619c82010-10-19 12:44:20 -0500684 unsigned long start_pfn;
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600685 int scn_nr;
Nathan Fontenote4619c82010-10-19 12:44:20 -0500686 int ret = 0;
687
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600688 mem = kzalloc(sizeof(*mem), GFP_KERNEL);
Nathan Fontenote4619c82010-10-19 12:44:20 -0500689 if (!mem)
690 return -ENOMEM;
691
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600692 scn_nr = __section_nr(section);
Nathan Fontenotd3360162011-01-20 10:44:29 -0600693 mem->start_section_nr =
694 base_memory_block_id(scn_nr) * sections_per_block;
695 mem->end_section_nr = mem->start_section_nr + sections_per_block - 1;
Nathan Fontenote4619c82010-10-19 12:44:20 -0500696 mem->state = state;
Nathan Fontenot07681212010-10-19 12:46:19 -0500697 mem->section_count++;
Nathan Fontenote4619c82010-10-19 12:44:20 -0500698 mutex_init(&mem->state_mutex);
Nathan Fontenotd3360162011-01-20 10:44:29 -0600699 start_pfn = section_nr_to_pfn(mem->start_section_nr);
Nathan Fontenote4619c82010-10-19 12:44:20 -0500700 mem->phys_device = arch_get_memory_phys_device(start_pfn);
701
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600702 ret = register_memory(mem);
Nathan Fontenote4619c82010-10-19 12:44:20 -0500703 if (!ret)
704 ret = mem_create_simple_file(mem, phys_index);
705 if (!ret)
Nathan Fontenotd3360162011-01-20 10:44:29 -0600706 ret = mem_create_simple_file(mem, end_phys_index);
707 if (!ret)
Nathan Fontenote4619c82010-10-19 12:44:20 -0500708 ret = mem_create_simple_file(mem, state);
709 if (!ret)
710 ret = mem_create_simple_file(mem, phys_device);
711 if (!ret)
712 ret = mem_create_simple_file(mem, removable);
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600713
714 *memory = mem;
715 return ret;
716}
717
718static int add_memory_section(int nid, struct mem_section *section,
719 unsigned long state, enum mem_add_context context)
720{
721 struct memory_block *mem;
722 int ret = 0;
723
724 mutex_lock(&mem_sysfs_mutex);
725
726 mem = find_memory_block(section);
727 if (mem) {
728 mem->section_count++;
729 kobject_put(&mem->sysdev.kobj);
730 } else
731 ret = init_memory_block(&mem, section, state);
732
Nathan Fontenote4619c82010-10-19 12:44:20 -0500733 if (!ret) {
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600734 if (context == HOTPLUG &&
735 mem->section_count == sections_per_block)
Nathan Fontenote4619c82010-10-19 12:44:20 -0500736 ret = register_mem_sect_under_node(mem, nid);
737 }
738
Nathan Fontenot2938ffb2010-10-19 12:45:24 -0500739 mutex_unlock(&mem_sysfs_mutex);
Nathan Fontenote4619c82010-10-19 12:44:20 -0500740 return ret;
741}
742
Dave Hansen3947be12005-10-29 18:16:54 -0700743int remove_memory_block(unsigned long node_id, struct mem_section *section,
744 int phys_device)
745{
746 struct memory_block *mem;
747
Nathan Fontenot2938ffb2010-10-19 12:45:24 -0500748 mutex_lock(&mem_sysfs_mutex);
Dave Hansen3947be12005-10-29 18:16:54 -0700749 mem = find_memory_block(section);
Nathan Fontenotd3360162011-01-20 10:44:29 -0600750 unregister_mem_sect_under_nodes(mem, __section_nr(section));
Nathan Fontenot07681212010-10-19 12:46:19 -0500751
752 mem->section_count--;
753 if (mem->section_count == 0) {
Nathan Fontenot07681212010-10-19 12:46:19 -0500754 mem_remove_simple_file(mem, phys_index);
Nathan Fontenotd3360162011-01-20 10:44:29 -0600755 mem_remove_simple_file(mem, end_phys_index);
Nathan Fontenot07681212010-10-19 12:46:19 -0500756 mem_remove_simple_file(mem, state);
757 mem_remove_simple_file(mem, phys_device);
758 mem_remove_simple_file(mem, removable);
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600759 unregister_memory(mem);
760 kfree(mem);
761 } else
762 kobject_put(&mem->sysdev.kobj);
Dave Hansen3947be12005-10-29 18:16:54 -0700763
Nathan Fontenot2938ffb2010-10-19 12:45:24 -0500764 mutex_unlock(&mem_sysfs_mutex);
Dave Hansen3947be12005-10-29 18:16:54 -0700765 return 0;
766}
767
768/*
769 * need an interface for the VM to add new memory regions,
770 * but without onlining it.
771 */
Gary Hadec04fc582009-01-06 14:39:14 -0800772int register_new_memory(int nid, struct mem_section *section)
Dave Hansen3947be12005-10-29 18:16:54 -0700773{
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600774 return add_memory_section(nid, section, MEM_OFFLINE, HOTPLUG);
Dave Hansen3947be12005-10-29 18:16:54 -0700775}
776
777int unregister_memory_section(struct mem_section *section)
778{
Andy Whitcroft540557b2007-10-16 01:24:11 -0700779 if (!present_section(section))
Dave Hansen3947be12005-10-29 18:16:54 -0700780 return -EINVAL;
781
782 return remove_memory_block(0, section, 0);
783}
784
785/*
786 * Initialize the sysfs support for memory devices...
787 */
788int __init memory_dev_init(void)
789{
790 unsigned int i;
791 int ret;
Andrew Morton28ec24e2006-12-06 20:37:29 -0800792 int err;
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600793 unsigned long block_sz;
Dave Hansen3947be12005-10-29 18:16:54 -0700794
Kay Sievers312c0042005-11-16 09:00:00 +0100795 memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops;
Dave Hansen3947be12005-10-29 18:16:54 -0700796 ret = sysdev_class_register(&memory_sysdev_class);
Andrew Morton28ec24e2006-12-06 20:37:29 -0800797 if (ret)
798 goto out;
Dave Hansen3947be12005-10-29 18:16:54 -0700799
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600800 block_sz = get_memory_block_size();
801 sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
802
Dave Hansen3947be12005-10-29 18:16:54 -0700803 /*
804 * Create entries for memory sections that were found
805 * during boot and have been initialized
806 */
807 for (i = 0; i < NR_MEM_SECTIONS; i++) {
Andy Whitcroft540557b2007-10-16 01:24:11 -0700808 if (!present_section_nr(i))
Dave Hansen3947be12005-10-29 18:16:54 -0700809 continue;
Nathan Fontenot0c2c99b2011-01-20 10:43:34 -0600810 err = add_memory_section(0, __nr_to_section(i), MEM_ONLINE,
811 BOOT);
Andrew Morton28ec24e2006-12-06 20:37:29 -0800812 if (!ret)
813 ret = err;
Dave Hansen3947be12005-10-29 18:16:54 -0700814 }
815
Andrew Morton28ec24e2006-12-06 20:37:29 -0800816 err = memory_probe_init();
817 if (!ret)
818 ret = err;
Andi Kleenfacb6012009-12-16 12:20:00 +0100819 err = memory_fail_init();
820 if (!ret)
821 ret = err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700822 err = memory_remove_init();
823 if (!ret)
824 ret = err;
825 err = memory_active_init();
826 if (!ret)
827 ret = err;
828 err = memory_low_power_init();
829 if (!ret)
830 ret = err;
Andrew Morton28ec24e2006-12-06 20:37:29 -0800831 err = block_size_init();
832 if (!ret)
833 ret = err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700834 err = movable_size_init();
835 if (!ret)
836 ret = err;
837 err = movable_start_init();
838 if (!ret)
839 ret = err;
840 err = low_power_memory_size_init();
841 if (!ret)
842 ret = err;
843 err = low_power_memory_start_init();
844 if (!ret)
845 ret = err;
Andrew Morton28ec24e2006-12-06 20:37:29 -0800846out:
847 if (ret)
Harvey Harrison2b3a3022008-03-04 16:41:05 -0800848 printk(KERN_ERR "%s() failed: %d\n", __func__, ret);
Dave Hansen3947be12005-10-29 18:16:54 -0700849 return ret;
850}