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 | ||
