diff options
Diffstat (limited to 'drivers/base/memory.c')
-rw-r--r-- | drivers/base/memory.c | 197 |
1 files changed, 143 insertions, 54 deletions
diff --git a/drivers/base/memory.c b/drivers/base/memory.c index cafeaaf0428f..3da6a43b7756 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c | |||
@@ -30,6 +30,14 @@ | |||
30 | static DEFINE_MUTEX(mem_sysfs_mutex); | 30 | static DEFINE_MUTEX(mem_sysfs_mutex); |
31 | 31 | ||
32 | #define MEMORY_CLASS_NAME "memory" | 32 | #define MEMORY_CLASS_NAME "memory" |
33 | #define MIN_MEMORY_BLOCK_SIZE (1 << SECTION_SIZE_BITS) | ||
34 | |||
35 | static int sections_per_block; | ||
36 | |||
37 | static inline int base_memory_block_id(int section_nr) | ||
38 | { | ||
39 | return section_nr / sections_per_block; | ||
40 | } | ||
33 | 41 | ||
34 | static struct sysdev_class memory_sysdev_class = { | 42 | static struct sysdev_class memory_sysdev_class = { |
35 | .name = MEMORY_CLASS_NAME, | 43 | .name = MEMORY_CLASS_NAME, |
@@ -84,39 +92,72 @@ EXPORT_SYMBOL(unregister_memory_isolate_notifier); | |||
84 | * register_memory - Setup a sysfs device for a memory block | 92 | * register_memory - Setup a sysfs device for a memory block |
85 | */ | 93 | */ |
86 | static | 94 | static |
87 | int register_memory(struct memory_block *memory, struct mem_section *section) | 95 | int register_memory(struct memory_block *memory) |
88 | { | 96 | { |
89 | int error; | 97 | int error; |
90 | 98 | ||
91 | memory->sysdev.cls = &memory_sysdev_class; | 99 | memory->sysdev.cls = &memory_sysdev_class; |
92 | memory->sysdev.id = __section_nr(section); | 100 | memory->sysdev.id = memory->start_section_nr / sections_per_block; |
93 | 101 | ||
94 | error = sysdev_register(&memory->sysdev); | 102 | error = sysdev_register(&memory->sysdev); |
95 | return error; | 103 | return error; |
96 | } | 104 | } |
97 | 105 | ||
98 | static void | 106 | static void |
99 | unregister_memory(struct memory_block *memory, struct mem_section *section) | 107 | unregister_memory(struct memory_block *memory) |
100 | { | 108 | { |
101 | BUG_ON(memory->sysdev.cls != &memory_sysdev_class); | 109 | BUG_ON(memory->sysdev.cls != &memory_sysdev_class); |
102 | BUG_ON(memory->sysdev.id != __section_nr(section)); | ||
103 | 110 | ||
104 | /* drop the ref. we got in remove_memory_block() */ | 111 | /* drop the ref. we got in remove_memory_block() */ |
105 | kobject_put(&memory->sysdev.kobj); | 112 | kobject_put(&memory->sysdev.kobj); |
106 | sysdev_unregister(&memory->sysdev); | 113 | sysdev_unregister(&memory->sysdev); |
107 | } | 114 | } |
108 | 115 | ||
116 | unsigned long __weak memory_block_size_bytes(void) | ||
117 | { | ||
118 | return MIN_MEMORY_BLOCK_SIZE; | ||
119 | } | ||
120 | |||
121 | static unsigned long get_memory_block_size(void) | ||
122 | { | ||
123 | unsigned long block_sz; | ||
124 | |||
125 | block_sz = memory_block_size_bytes(); | ||
126 | |||
127 | /* Validate blk_sz is a power of 2 and not less than section size */ | ||
128 | if ((block_sz & (block_sz - 1)) || (block_sz < MIN_MEMORY_BLOCK_SIZE)) { | ||
129 | WARN_ON(1); | ||
130 | block_sz = MIN_MEMORY_BLOCK_SIZE; | ||
131 | } | ||
132 | |||
133 | return block_sz; | ||
134 | } | ||
135 | |||
109 | /* | 136 | /* |
110 | * use this as the physical section index that this memsection | 137 | * use this as the physical section index that this memsection |
111 | * uses. | 138 | * uses. |
112 | */ | 139 | */ |
113 | 140 | ||
114 | static ssize_t show_mem_phys_index(struct sys_device *dev, | 141 | static ssize_t show_mem_start_phys_index(struct sys_device *dev, |
115 | struct sysdev_attribute *attr, char *buf) | 142 | struct sysdev_attribute *attr, char *buf) |
116 | { | 143 | { |
117 | struct memory_block *mem = | 144 | struct memory_block *mem = |
118 | container_of(dev, struct memory_block, sysdev); | 145 | container_of(dev, struct memory_block, sysdev); |
119 | return sprintf(buf, "%08lx\n", mem->phys_index); | 146 | unsigned long phys_index; |
147 | |||
148 | phys_index = mem->start_section_nr / sections_per_block; | ||
149 | return sprintf(buf, "%08lx\n", phys_index); | ||
150 | } | ||
151 | |||
152 | static ssize_t show_mem_end_phys_index(struct sys_device *dev, | ||
153 | struct sysdev_attribute *attr, char *buf) | ||
154 | { | ||
155 | struct memory_block *mem = | ||
156 | container_of(dev, struct memory_block, sysdev); | ||
157 | unsigned long phys_index; | ||
158 | |||
159 | phys_index = mem->end_section_nr / sections_per_block; | ||
160 | return sprintf(buf, "%08lx\n", phys_index); | ||
120 | } | 161 | } |
121 | 162 | ||
122 | /* | 163 | /* |
@@ -125,13 +166,16 @@ static ssize_t show_mem_phys_index(struct sys_device *dev, | |||
125 | static ssize_t show_mem_removable(struct sys_device *dev, | 166 | static ssize_t show_mem_removable(struct sys_device *dev, |
126 | struct sysdev_attribute *attr, char *buf) | 167 | struct sysdev_attribute *attr, char *buf) |
127 | { | 168 | { |
128 | unsigned long start_pfn; | 169 | unsigned long i, pfn; |
129 | int ret; | 170 | int ret = 1; |
130 | struct memory_block *mem = | 171 | struct memory_block *mem = |
131 | container_of(dev, struct memory_block, sysdev); | 172 | container_of(dev, struct memory_block, sysdev); |
132 | 173 | ||
133 | start_pfn = section_nr_to_pfn(mem->phys_index); | 174 | for (i = 0; i < sections_per_block; i++) { |
134 | ret = is_mem_section_removable(start_pfn, PAGES_PER_SECTION); | 175 | pfn = section_nr_to_pfn(mem->start_section_nr + i); |
176 | ret &= is_mem_section_removable(pfn, PAGES_PER_SECTION); | ||
177 | } | ||
178 | |||
135 | return sprintf(buf, "%d\n", ret); | 179 | return sprintf(buf, "%d\n", ret); |
136 | } | 180 | } |
137 | 181 | ||
@@ -184,17 +228,14 @@ int memory_isolate_notify(unsigned long val, void *v) | |||
184 | * OK to have direct references to sparsemem variables in here. | 228 | * OK to have direct references to sparsemem variables in here. |
185 | */ | 229 | */ |
186 | static int | 230 | static int |
187 | memory_block_action(struct memory_block *mem, unsigned long action) | 231 | memory_section_action(unsigned long phys_index, unsigned long action) |
188 | { | 232 | { |
189 | int i; | 233 | int i; |
190 | unsigned long psection; | ||
191 | unsigned long start_pfn, start_paddr; | 234 | unsigned long start_pfn, start_paddr; |
192 | struct page *first_page; | 235 | struct page *first_page; |
193 | int ret; | 236 | int ret; |
194 | int old_state = mem->state; | ||
195 | 237 | ||
196 | psection = mem->phys_index; | 238 | first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT); |
197 | first_page = pfn_to_page(psection << PFN_SECTION_SHIFT); | ||
198 | 239 | ||
199 | /* | 240 | /* |
200 | * The probe routines leave the pages reserved, just | 241 | * The probe routines leave the pages reserved, just |
@@ -207,8 +248,8 @@ memory_block_action(struct memory_block *mem, unsigned long action) | |||
207 | continue; | 248 | continue; |
208 | 249 | ||
209 | printk(KERN_WARNING "section number %ld page number %d " | 250 | printk(KERN_WARNING "section number %ld page number %d " |
210 | "not reserved, was it already online? \n", | 251 | "not reserved, was it already online?\n", |
211 | psection, i); | 252 | phys_index, i); |
212 | return -EBUSY; | 253 | return -EBUSY; |
213 | } | 254 | } |
214 | } | 255 | } |
@@ -219,18 +260,13 @@ memory_block_action(struct memory_block *mem, unsigned long action) | |||
219 | ret = online_pages(start_pfn, PAGES_PER_SECTION); | 260 | ret = online_pages(start_pfn, PAGES_PER_SECTION); |
220 | break; | 261 | break; |
221 | case MEM_OFFLINE: | 262 | case MEM_OFFLINE: |
222 | mem->state = MEM_GOING_OFFLINE; | ||
223 | start_paddr = page_to_pfn(first_page) << PAGE_SHIFT; | 263 | start_paddr = page_to_pfn(first_page) << PAGE_SHIFT; |
224 | ret = remove_memory(start_paddr, | 264 | ret = remove_memory(start_paddr, |
225 | PAGES_PER_SECTION << PAGE_SHIFT); | 265 | PAGES_PER_SECTION << PAGE_SHIFT); |
226 | if (ret) { | ||
227 | mem->state = old_state; | ||
228 | break; | ||
229 | } | ||
230 | break; | 266 | break; |
231 | default: | 267 | default: |
232 | WARN(1, KERN_WARNING "%s(%p, %ld) unknown action: %ld\n", | 268 | WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: " |
233 | __func__, mem, action, action); | 269 | "%ld\n", __func__, phys_index, action, action); |
234 | ret = -EINVAL; | 270 | ret = -EINVAL; |
235 | } | 271 | } |
236 | 272 | ||
@@ -240,7 +276,8 @@ memory_block_action(struct memory_block *mem, unsigned long action) | |||
240 | static int memory_block_change_state(struct memory_block *mem, | 276 | static int memory_block_change_state(struct memory_block *mem, |
241 | unsigned long to_state, unsigned long from_state_req) | 277 | unsigned long to_state, unsigned long from_state_req) |
242 | { | 278 | { |
243 | int ret = 0; | 279 | int i, ret = 0; |
280 | |||
244 | mutex_lock(&mem->state_mutex); | 281 | mutex_lock(&mem->state_mutex); |
245 | 282 | ||
246 | if (mem->state != from_state_req) { | 283 | if (mem->state != from_state_req) { |
@@ -248,8 +285,23 @@ static int memory_block_change_state(struct memory_block *mem, | |||
248 | goto out; | 285 | goto out; |
249 | } | 286 | } |
250 | 287 | ||
251 | ret = memory_block_action(mem, to_state); | 288 | if (to_state == MEM_OFFLINE) |
252 | if (!ret) | 289 | mem->state = MEM_GOING_OFFLINE; |
290 | |||
291 | for (i = 0; i < sections_per_block; i++) { | ||
292 | ret = memory_section_action(mem->start_section_nr + i, | ||
293 | to_state); | ||
294 | if (ret) | ||
295 | break; | ||
296 | } | ||
297 | |||
298 | if (ret) { | ||
299 | for (i = 0; i < sections_per_block; i++) | ||
300 | memory_section_action(mem->start_section_nr + i, | ||
301 | from_state_req); | ||
302 | |||
303 | mem->state = from_state_req; | ||
304 | } else | ||
253 | mem->state = to_state; | 305 | mem->state = to_state; |
254 | 306 | ||
255 | out: | 307 | out: |
@@ -262,20 +314,15 @@ store_mem_state(struct sys_device *dev, | |||
262 | struct sysdev_attribute *attr, const char *buf, size_t count) | 314 | struct sysdev_attribute *attr, const char *buf, size_t count) |
263 | { | 315 | { |
264 | struct memory_block *mem; | 316 | struct memory_block *mem; |
265 | unsigned int phys_section_nr; | ||
266 | int ret = -EINVAL; | 317 | int ret = -EINVAL; |
267 | 318 | ||
268 | mem = container_of(dev, struct memory_block, sysdev); | 319 | mem = container_of(dev, struct memory_block, sysdev); |
269 | phys_section_nr = mem->phys_index; | ||
270 | |||
271 | if (!present_section_nr(phys_section_nr)) | ||
272 | goto out; | ||
273 | 320 | ||
274 | if (!strncmp(buf, "online", min((int)count, 6))) | 321 | if (!strncmp(buf, "online", min((int)count, 6))) |
275 | ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE); | 322 | ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE); |
276 | else if(!strncmp(buf, "offline", min((int)count, 7))) | 323 | else if(!strncmp(buf, "offline", min((int)count, 7))) |
277 | ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE); | 324 | ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE); |
278 | out: | 325 | |
279 | if (ret) | 326 | if (ret) |
280 | return ret; | 327 | return ret; |
281 | return count; | 328 | return count; |
@@ -298,7 +345,8 @@ static ssize_t show_phys_device(struct sys_device *dev, | |||
298 | return sprintf(buf, "%d\n", mem->phys_device); | 345 | return sprintf(buf, "%d\n", mem->phys_device); |
299 | } | 346 | } |
300 | 347 | ||
301 | static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL); | 348 | static SYSDEV_ATTR(phys_index, 0444, show_mem_start_phys_index, NULL); |
349 | static SYSDEV_ATTR(end_phys_index, 0444, show_mem_end_phys_index, NULL); | ||
302 | static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state); | 350 | static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state); |
303 | static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL); | 351 | static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL); |
304 | static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL); | 352 | static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL); |
@@ -315,7 +363,7 @@ static ssize_t | |||
315 | print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr, | 363 | print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr, |
316 | char *buf) | 364 | char *buf) |
317 | { | 365 | { |
318 | return sprintf(buf, "%lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE); | 366 | return sprintf(buf, "%lx\n", get_memory_block_size()); |
319 | } | 367 | } |
320 | 368 | ||
321 | static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); | 369 | static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); |
@@ -339,12 +387,19 @@ memory_probe_store(struct class *class, struct class_attribute *attr, | |||
339 | { | 387 | { |
340 | u64 phys_addr; | 388 | u64 phys_addr; |
341 | int nid; | 389 | int nid; |
342 | int ret; | 390 | int i, ret; |
343 | 391 | ||
344 | phys_addr = simple_strtoull(buf, NULL, 0); | 392 | phys_addr = simple_strtoull(buf, NULL, 0); |
345 | 393 | ||
346 | nid = memory_add_physaddr_to_nid(phys_addr); | 394 | for (i = 0; i < sections_per_block; i++) { |
347 | ret = add_memory(nid, phys_addr, PAGES_PER_SECTION << PAGE_SHIFT); | 395 | nid = memory_add_physaddr_to_nid(phys_addr); |
396 | ret = add_memory(nid, phys_addr, | ||
397 | PAGES_PER_SECTION << PAGE_SHIFT); | ||
398 | if (ret) | ||
399 | break; | ||
400 | |||
401 | phys_addr += MIN_MEMORY_BLOCK_SIZE; | ||
402 | } | ||
348 | 403 | ||
349 | if (ret) | 404 | if (ret) |
350 | count = ret; | 405 | count = ret; |
@@ -444,6 +499,7 @@ struct memory_block *find_memory_block_hinted(struct mem_section *section, | |||
444 | struct sys_device *sysdev; | 499 | struct sys_device *sysdev; |
445 | struct memory_block *mem; | 500 | struct memory_block *mem; |
446 | char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1]; | 501 | char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1]; |
502 | int block_id = base_memory_block_id(__section_nr(section)); | ||
447 | 503 | ||
448 | kobj = hint ? &hint->sysdev.kobj : NULL; | 504 | kobj = hint ? &hint->sysdev.kobj : NULL; |
449 | 505 | ||
@@ -451,7 +507,7 @@ struct memory_block *find_memory_block_hinted(struct mem_section *section, | |||
451 | * This only works because we know that section == sysdev->id | 507 | * This only works because we know that section == sysdev->id |
452 | * slightly redundant with sysdev_register() | 508 | * slightly redundant with sysdev_register() |
453 | */ | 509 | */ |
454 | sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section)); | 510 | sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, block_id); |
455 | 511 | ||
456 | kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj); | 512 | kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj); |
457 | if (!kobj) | 513 | if (!kobj) |
@@ -476,36 +532,62 @@ struct memory_block *find_memory_block(struct mem_section *section) | |||
476 | return find_memory_block_hinted(section, NULL); | 532 | return find_memory_block_hinted(section, NULL); |
477 | } | 533 | } |
478 | 534 | ||
479 | static int add_memory_block(int nid, struct mem_section *section, | 535 | static int init_memory_block(struct memory_block **memory, |
480 | unsigned long state, enum mem_add_context context) | 536 | struct mem_section *section, unsigned long state) |
481 | { | 537 | { |
482 | struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL); | 538 | struct memory_block *mem; |
483 | unsigned long start_pfn; | 539 | unsigned long start_pfn; |
540 | int scn_nr; | ||
484 | int ret = 0; | 541 | int ret = 0; |
485 | 542 | ||
543 | mem = kzalloc(sizeof(*mem), GFP_KERNEL); | ||
486 | if (!mem) | 544 | if (!mem) |
487 | return -ENOMEM; | 545 | return -ENOMEM; |
488 | 546 | ||
489 | mutex_lock(&mem_sysfs_mutex); | 547 | scn_nr = __section_nr(section); |
490 | 548 | mem->start_section_nr = | |
491 | mem->phys_index = __section_nr(section); | 549 | base_memory_block_id(scn_nr) * sections_per_block; |
550 | mem->end_section_nr = mem->start_section_nr + sections_per_block - 1; | ||
492 | mem->state = state; | 551 | mem->state = state; |
493 | mem->section_count++; | 552 | mem->section_count++; |
494 | mutex_init(&mem->state_mutex); | 553 | mutex_init(&mem->state_mutex); |
495 | start_pfn = section_nr_to_pfn(mem->phys_index); | 554 | start_pfn = section_nr_to_pfn(mem->start_section_nr); |
496 | mem->phys_device = arch_get_memory_phys_device(start_pfn); | 555 | mem->phys_device = arch_get_memory_phys_device(start_pfn); |
497 | 556 | ||
498 | ret = register_memory(mem, section); | 557 | ret = register_memory(mem); |
499 | if (!ret) | 558 | if (!ret) |
500 | ret = mem_create_simple_file(mem, phys_index); | 559 | ret = mem_create_simple_file(mem, phys_index); |
501 | if (!ret) | 560 | if (!ret) |
561 | ret = mem_create_simple_file(mem, end_phys_index); | ||
562 | if (!ret) | ||
502 | ret = mem_create_simple_file(mem, state); | 563 | ret = mem_create_simple_file(mem, state); |
503 | if (!ret) | 564 | if (!ret) |
504 | ret = mem_create_simple_file(mem, phys_device); | 565 | ret = mem_create_simple_file(mem, phys_device); |
505 | if (!ret) | 566 | if (!ret) |
506 | ret = mem_create_simple_file(mem, removable); | 567 | ret = mem_create_simple_file(mem, removable); |
568 | |||
569 | *memory = mem; | ||
570 | return ret; | ||
571 | } | ||
572 | |||
573 | static int add_memory_section(int nid, struct mem_section *section, | ||
574 | unsigned long state, enum mem_add_context context) | ||
575 | { | ||
576 | struct memory_block *mem; | ||
577 | int ret = 0; | ||
578 | |||
579 | mutex_lock(&mem_sysfs_mutex); | ||
580 | |||
581 | mem = find_memory_block(section); | ||
582 | if (mem) { | ||
583 | mem->section_count++; | ||
584 | kobject_put(&mem->sysdev.kobj); | ||
585 | } else | ||
586 | ret = init_memory_block(&mem, section, state); | ||
587 | |||
507 | if (!ret) { | 588 | if (!ret) { |
508 | if (context == HOTPLUG) | 589 | if (context == HOTPLUG && |
590 | mem->section_count == sections_per_block) | ||
509 | ret = register_mem_sect_under_node(mem, nid); | 591 | ret = register_mem_sect_under_node(mem, nid); |
510 | } | 592 | } |
511 | 593 | ||
@@ -520,16 +602,19 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section, | |||
520 | 602 | ||
521 | mutex_lock(&mem_sysfs_mutex); | 603 | mutex_lock(&mem_sysfs_mutex); |
522 | mem = find_memory_block(section); | 604 | mem = find_memory_block(section); |
605 | unregister_mem_sect_under_nodes(mem, __section_nr(section)); | ||
523 | 606 | ||
524 | mem->section_count--; | 607 | mem->section_count--; |
525 | if (mem->section_count == 0) { | 608 | if (mem->section_count == 0) { |
526 | unregister_mem_sect_under_nodes(mem); | ||
527 | mem_remove_simple_file(mem, phys_index); | 609 | mem_remove_simple_file(mem, phys_index); |
610 | mem_remove_simple_file(mem, end_phys_index); | ||
528 | mem_remove_simple_file(mem, state); | 611 | mem_remove_simple_file(mem, state); |
529 | mem_remove_simple_file(mem, phys_device); | 612 | mem_remove_simple_file(mem, phys_device); |
530 | mem_remove_simple_file(mem, removable); | 613 | mem_remove_simple_file(mem, removable); |
531 | unregister_memory(mem, section); | 614 | unregister_memory(mem); |
532 | } | 615 | kfree(mem); |
616 | } else | ||
617 | kobject_put(&mem->sysdev.kobj); | ||
533 | 618 | ||
534 | mutex_unlock(&mem_sysfs_mutex); | 619 | mutex_unlock(&mem_sysfs_mutex); |
535 | return 0; | 620 | return 0; |
@@ -541,7 +626,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section, | |||
541 | */ | 626 | */ |
542 | int register_new_memory(int nid, struct mem_section *section) | 627 | int register_new_memory(int nid, struct mem_section *section) |
543 | { | 628 | { |
544 | return add_memory_block(nid, section, MEM_OFFLINE, HOTPLUG); | 629 | return add_memory_section(nid, section, MEM_OFFLINE, HOTPLUG); |
545 | } | 630 | } |
546 | 631 | ||
547 | int unregister_memory_section(struct mem_section *section) | 632 | int unregister_memory_section(struct mem_section *section) |
@@ -560,12 +645,16 @@ int __init memory_dev_init(void) | |||
560 | unsigned int i; | 645 | unsigned int i; |
561 | int ret; | 646 | int ret; |
562 | int err; | 647 | int err; |
648 | unsigned long block_sz; | ||
563 | 649 | ||
564 | memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops; | 650 | memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops; |
565 | ret = sysdev_class_register(&memory_sysdev_class); | 651 | ret = sysdev_class_register(&memory_sysdev_class); |
566 | if (ret) | 652 | if (ret) |
567 | goto out; | 653 | goto out; |
568 | 654 | ||
655 | block_sz = get_memory_block_size(); | ||
656 | sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE; | ||
657 | |||
569 | /* | 658 | /* |
570 | * Create entries for memory sections that were found | 659 | * Create entries for memory sections that were found |
571 | * during boot and have been initialized | 660 | * during boot and have been initialized |
@@ -573,8 +662,8 @@ int __init memory_dev_init(void) | |||
573 | for (i = 0; i < NR_MEM_SECTIONS; i++) { | 662 | for (i = 0; i < NR_MEM_SECTIONS; i++) { |
574 | if (!present_section_nr(i)) | 663 | if (!present_section_nr(i)) |
575 | continue; | 664 | continue; |
576 | err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE, | 665 | err = add_memory_section(0, __nr_to_section(i), MEM_ONLINE, |
577 | BOOT); | 666 | BOOT); |
578 | if (!ret) | 667 | if (!ret) |
579 | ret = err; | 668 | ret = err; |
580 | } | 669 | } |