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