memory hotplug: allow setting of phys_device

/sys/devices/system/memory/memoryX/phys_device is supposed to contain the
number of the physical device that the corresponding piece of memory
belongs to.

In case a physical device should be replaced or taken offline for whatever
reason it is necessary to set all corresponding memory pieces offline.
The current implementation always sets phys_device to '0' and there is no
way or hook to change that. Seems like there was a plan to implement that
but it wasn't finished for whatever reason.

So add a weak function which architectures can override to actually set
the phys_device from within add_memory_block().

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Dave Hansen <haveblue@us.ibm.com>
Cc: Gerald Schaefer <gerald.schaefer@de.ibm.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Heiko Carstens and committed by
Linus Torvalds
bc32df00 e5d61511

+12 -5
+10 -5
drivers/base/memory.c
··· 429 429 * differentiation between which *physical* devices each 430 430 * section belongs to... 431 431 */ 432 + int __weak arch_get_memory_phys_device(unsigned long start_pfn) 433 + { 434 + return 0; 435 + } 432 436 433 437 static int add_memory_block(int nid, struct mem_section *section, 434 - unsigned long state, int phys_device, 435 - enum mem_add_context context) 438 + unsigned long state, enum mem_add_context context) 436 439 { 437 440 struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL); 441 + unsigned long start_pfn; 438 442 int ret = 0; 439 443 440 444 if (!mem) ··· 447 443 mem->phys_index = __section_nr(section); 448 444 mem->state = state; 449 445 mutex_init(&mem->state_mutex); 450 - mem->phys_device = phys_device; 446 + start_pfn = section_nr_to_pfn(mem->phys_index); 447 + mem->phys_device = arch_get_memory_phys_device(start_pfn); 451 448 452 449 ret = register_memory(mem, section); 453 450 if (!ret) ··· 520 515 */ 521 516 int register_new_memory(int nid, struct mem_section *section) 522 517 { 523 - return add_memory_block(nid, section, MEM_OFFLINE, 0, HOTPLUG); 518 + return add_memory_block(nid, section, MEM_OFFLINE, HOTPLUG); 524 519 } 525 520 526 521 int unregister_memory_section(struct mem_section *section) ··· 553 548 if (!present_section_nr(i)) 554 549 continue; 555 550 err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE, 556 - 0, BOOT); 551 + BOOT); 557 552 if (!ret) 558 553 ret = err; 559 554 }
+2
include/linux/memory.h
··· 36 36 struct sys_device sysdev; 37 37 }; 38 38 39 + int arch_get_memory_phys_device(unsigned long start_pfn); 40 + 39 41 /* These states are exposed to userspace as text strings in sysfs */ 40 42 #define MEM_ONLINE (1<<0) /* exposed to userspace */ 41 43 #define MEM_GOING_OFFLINE (1<<1) /* exposed to userspace */