diff options
Diffstat (limited to 'drivers/base/memory.c')
-rw-r--r-- | drivers/base/memory.c | 94 |
1 files changed, 57 insertions, 37 deletions
diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 933442f40321..cafeaaf0428f 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <asm/atomic.h> | 27 | #include <asm/atomic.h> |
28 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
29 | 29 | ||
30 | static DEFINE_MUTEX(mem_sysfs_mutex); | ||
31 | |||
30 | #define MEMORY_CLASS_NAME "memory" | 32 | #define MEMORY_CLASS_NAME "memory" |
31 | 33 | ||
32 | static struct sysdev_class memory_sysdev_class = { | 34 | static struct sysdev_class memory_sysdev_class = { |
@@ -435,6 +437,45 @@ int __weak arch_get_memory_phys_device(unsigned long start_pfn) | |||
435 | return 0; | 437 | return 0; |
436 | } | 438 | } |
437 | 439 | ||
440 | struct memory_block *find_memory_block_hinted(struct mem_section *section, | ||
441 | struct memory_block *hint) | ||
442 | { | ||
443 | struct kobject *kobj; | ||
444 | struct sys_device *sysdev; | ||
445 | struct memory_block *mem; | ||
446 | char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1]; | ||
447 | |||
448 | kobj = hint ? &hint->sysdev.kobj : NULL; | ||
449 | |||
450 | /* | ||
451 | * This only works because we know that section == sysdev->id | ||
452 | * slightly redundant with sysdev_register() | ||
453 | */ | ||
454 | sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section)); | ||
455 | |||
456 | kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj); | ||
457 | if (!kobj) | ||
458 | return NULL; | ||
459 | |||
460 | sysdev = container_of(kobj, struct sys_device, kobj); | ||
461 | mem = container_of(sysdev, struct memory_block, sysdev); | ||
462 | |||
463 | return mem; | ||
464 | } | ||
465 | |||
466 | /* | ||
467 | * For now, we have a linear search to go find the appropriate | ||
468 | * memory_block corresponding to a particular phys_index. If | ||
469 | * this gets to be a real problem, we can always use a radix | ||
470 | * tree or something here. | ||
471 | * | ||
472 | * This could be made generic for all sysdev classes. | ||
473 | */ | ||
474 | struct memory_block *find_memory_block(struct mem_section *section) | ||
475 | { | ||
476 | return find_memory_block_hinted(section, NULL); | ||
477 | } | ||
478 | |||
438 | static int add_memory_block(int nid, struct mem_section *section, | 479 | static int add_memory_block(int nid, struct mem_section *section, |
439 | unsigned long state, enum mem_add_context context) | 480 | unsigned long state, enum mem_add_context context) |
440 | { | 481 | { |
@@ -445,8 +486,11 @@ static int add_memory_block(int nid, struct mem_section *section, | |||
445 | if (!mem) | 486 | if (!mem) |
446 | return -ENOMEM; | 487 | return -ENOMEM; |
447 | 488 | ||
489 | mutex_lock(&mem_sysfs_mutex); | ||
490 | |||
448 | mem->phys_index = __section_nr(section); | 491 | mem->phys_index = __section_nr(section); |
449 | mem->state = state; | 492 | mem->state = state; |
493 | mem->section_count++; | ||
450 | mutex_init(&mem->state_mutex); | 494 | mutex_init(&mem->state_mutex); |
451 | start_pfn = section_nr_to_pfn(mem->phys_index); | 495 | start_pfn = section_nr_to_pfn(mem->phys_index); |
452 | mem->phys_device = arch_get_memory_phys_device(start_pfn); | 496 | mem->phys_device = arch_get_memory_phys_device(start_pfn); |
@@ -465,53 +509,29 @@ static int add_memory_block(int nid, struct mem_section *section, | |||
465 | ret = register_mem_sect_under_node(mem, nid); | 509 | ret = register_mem_sect_under_node(mem, nid); |
466 | } | 510 | } |
467 | 511 | ||
512 | mutex_unlock(&mem_sysfs_mutex); | ||
468 | return ret; | 513 | return ret; |
469 | } | 514 | } |
470 | 515 | ||
471 | /* | ||
472 | * For now, we have a linear search to go find the appropriate | ||
473 | * memory_block corresponding to a particular phys_index. If | ||
474 | * this gets to be a real problem, we can always use a radix | ||
475 | * tree or something here. | ||
476 | * | ||
477 | * This could be made generic for all sysdev classes. | ||
478 | */ | ||
479 | struct memory_block *find_memory_block(struct mem_section *section) | ||
480 | { | ||
481 | struct kobject *kobj; | ||
482 | struct sys_device *sysdev; | ||
483 | struct memory_block *mem; | ||
484 | char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1]; | ||
485 | |||
486 | /* | ||
487 | * This only works because we know that section == sysdev->id | ||
488 | * slightly redundant with sysdev_register() | ||
489 | */ | ||
490 | sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section)); | ||
491 | |||
492 | kobj = kset_find_obj(&memory_sysdev_class.kset, name); | ||
493 | if (!kobj) | ||
494 | return NULL; | ||
495 | |||
496 | sysdev = container_of(kobj, struct sys_device, kobj); | ||
497 | mem = container_of(sysdev, struct memory_block, sysdev); | ||
498 | |||
499 | return mem; | ||
500 | } | ||
501 | |||
502 | int remove_memory_block(unsigned long node_id, struct mem_section *section, | 516 | int remove_memory_block(unsigned long node_id, struct mem_section *section, |
503 | int phys_device) | 517 | int phys_device) |
504 | { | 518 | { |
505 | struct memory_block *mem; | 519 | struct memory_block *mem; |
506 | 520 | ||
521 | mutex_lock(&mem_sysfs_mutex); | ||
507 | mem = find_memory_block(section); | 522 | mem = find_memory_block(section); |
508 | unregister_mem_sect_under_nodes(mem); | ||
509 | mem_remove_simple_file(mem, phys_index); | ||
510 | mem_remove_simple_file(mem, state); | ||
511 | mem_remove_simple_file(mem, phys_device); | ||
512 | mem_remove_simple_file(mem, removable); | ||
513 | unregister_memory(mem, section); | ||
514 | 523 | ||
524 | mem->section_count--; | ||
525 | if (mem->section_count == 0) { | ||
526 | unregister_mem_sect_under_nodes(mem); | ||
527 | mem_remove_simple_file(mem, phys_index); | ||
528 | mem_remove_simple_file(mem, state); | ||
529 | mem_remove_simple_file(mem, phys_device); | ||
530 | mem_remove_simple_file(mem, removable); | ||
531 | unregister_memory(mem, section); | ||
532 | } | ||
533 | |||
534 | mutex_unlock(&mem_sysfs_mutex); | ||
515 | return 0; | 535 | return 0; |
516 | } | 536 | } |
517 | 537 | ||