Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Memory subsystem support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Written by Matt Tolentino <matthew.e.tolentino@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *            Dave Hansen <haveblue@us.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * This file provides the necessary infrastructure to represent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * a SPARSEMEM-memory-model system's physical memory in /sysfs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * All arch-independent code that assumes MEMORY_HOTPLUG requires
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * SPARSEMEM should be contained here, or in mm/memory_hotplug.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/topology.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/capability.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/memory.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/memory_hotplug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/xarray.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define MEMORY_CLASS_NAME	"memory"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) static const char *const online_type_to_str[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	[MMOP_OFFLINE] = "offline",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	[MMOP_ONLINE] = "online",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	[MMOP_ONLINE_KERNEL] = "online_kernel",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	[MMOP_ONLINE_MOVABLE] = "online_movable",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) int memhp_online_type_from_str(const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	for (i = 0; i < ARRAY_SIZE(online_type_to_str); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		if (sysfs_streq(str, online_type_to_str[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 			return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) #define to_memory_block(dev) container_of(dev, struct memory_block, dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) static int sections_per_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) static inline unsigned long memory_block_id(unsigned long section_nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	return section_nr / sections_per_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) static inline unsigned long pfn_to_block_id(unsigned long pfn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	return memory_block_id(pfn_to_section_nr(pfn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) static inline unsigned long phys_to_block_id(unsigned long phys)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	return pfn_to_block_id(PFN_DOWN(phys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) static int memory_subsys_online(struct device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) static int memory_subsys_offline(struct device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) static struct bus_type memory_subsys = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	.name = MEMORY_CLASS_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	.dev_name = MEMORY_CLASS_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	.online = memory_subsys_online,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	.offline = memory_subsys_offline,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)  * Memory blocks are cached in a local radix tree to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  * a costly linear search for the corresponding device on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  * the subsystem bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) static DEFINE_XARRAY(memory_blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) static BLOCKING_NOTIFIER_HEAD(memory_chain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) int register_memory_notifier(struct notifier_block *nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	return blocking_notifier_chain_register(&memory_chain, nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) EXPORT_SYMBOL(register_memory_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) void unregister_memory_notifier(struct notifier_block *nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	blocking_notifier_chain_unregister(&memory_chain, nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) EXPORT_SYMBOL(unregister_memory_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) static void memory_block_release(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	struct memory_block *mem = to_memory_block(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	kfree(mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) unsigned long __weak memory_block_size_bytes(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	return MIN_MEMORY_BLOCK_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) EXPORT_SYMBOL_GPL(memory_block_size_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  * Show the first physical section index (number) of this memory block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static ssize_t phys_index_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 			       struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	struct memory_block *mem = to_memory_block(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	unsigned long phys_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	phys_index = mem->start_section_nr / sections_per_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	return sysfs_emit(buf, "%08lx\n", phys_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)  * Legacy interface that we cannot remove. Always indicate "removable"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)  * with CONFIG_MEMORY_HOTREMOVE - bad heuristic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static ssize_t removable_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 			      char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	return sysfs_emit(buf, "%d\n", (int)IS_ENABLED(CONFIG_MEMORY_HOTREMOVE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)  * online, offline, going offline, etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static ssize_t state_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 			  char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	struct memory_block *mem = to_memory_block(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	const char *output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	 * We can probably put these states in a nice little array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	 * so that they're not open-coded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	switch (mem->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	case MEM_ONLINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		output = "online";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	case MEM_OFFLINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		output = "offline";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	case MEM_GOING_OFFLINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		output = "going-offline";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		return sysfs_emit(buf, "ERROR-UNKNOWN-%ld\n", mem->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	return sysfs_emit(buf, "%s\n", output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) int memory_notify(unsigned long val, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	return blocking_notifier_call_chain(&memory_chain, val, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)  * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)  * OK to have direct references to sparsemem variables in here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) memory_block_action(unsigned long start_section_nr, unsigned long action,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		    int online_type, int nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	unsigned long start_pfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	start_pfn = section_nr_to_pfn(start_section_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	switch (action) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	case MEM_ONLINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		ret = online_pages(start_pfn, nr_pages, online_type, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	case MEM_OFFLINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		ret = offline_pages(start_pfn, nr_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		     "%ld\n", __func__, start_section_nr, action, action);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static int memory_block_change_state(struct memory_block *mem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		unsigned long to_state, unsigned long from_state_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	if (mem->state != from_state_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	if (to_state == MEM_OFFLINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		mem->state = MEM_GOING_OFFLINE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	ret = memory_block_action(mem->start_section_nr, to_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 				  mem->online_type, mem->nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	mem->state = ret ? from_state_req : to_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /* The device lock serializes operations on memory_subsys_[online|offline] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static int memory_subsys_online(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	struct memory_block *mem = to_memory_block(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	if (mem->state == MEM_ONLINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	 * When called via device_online() without configuring the online_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	 * we want to default to MMOP_ONLINE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	if (mem->online_type == MMOP_OFFLINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		mem->online_type = MMOP_ONLINE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	mem->online_type = MMOP_OFFLINE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static int memory_subsys_offline(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	struct memory_block *mem = to_memory_block(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	if (mem->state == MEM_OFFLINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	return memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static ssize_t state_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 			   const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	const int online_type = memhp_online_type_from_str(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	struct memory_block *mem = to_memory_block(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	if (online_type < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	ret = lock_device_hotplug_sysfs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	switch (online_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	case MMOP_ONLINE_KERNEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	case MMOP_ONLINE_MOVABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	case MMOP_ONLINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		/* mem->online_type is protected by device_hotplug_lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		mem->online_type = online_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		ret = device_online(&mem->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	case MMOP_OFFLINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		ret = device_offline(&mem->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		ret = -EINVAL; /* should never happen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	unlock_device_hotplug();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)  * Legacy interface that we cannot remove: s390x exposes the storage increment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)  * covered by a memory block, allowing for identifying which memory blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)  * comprise a storage increment. Since a memory block spans complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)  * storage increments nowadays, this interface is basically unused. Other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)  * archs never exposed != 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static ssize_t phys_device_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 				struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	struct memory_block *mem = to_memory_block(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	unsigned long start_pfn = section_nr_to_pfn(mem->start_section_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	return sysfs_emit(buf, "%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 			  arch_get_memory_phys_device(start_pfn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) #ifdef CONFIG_MEMORY_HOTREMOVE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static int print_allowed_zone(char *buf, int len, int nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 			      unsigned long start_pfn, unsigned long nr_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 			      int online_type, struct zone *default_zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	struct zone *zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	zone = zone_for_pfn_range(online_type, nid, start_pfn, nr_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	if (zone == default_zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	return sysfs_emit_at(buf, len, " %s", zone->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static ssize_t valid_zones_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 				struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	struct memory_block *mem = to_memory_block(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	unsigned long start_pfn = section_nr_to_pfn(mem->start_section_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	struct zone *default_zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	int nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	 * Check the existing zone. Make sure that we do that only on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	 * online nodes otherwise the page_zone is not reliable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	if (mem->state == MEM_ONLINE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		 * The block contains more than one zone can not be offlined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		 * This can happen e.g. for ZONE_DMA and ZONE_DMA32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		default_zone = test_pages_in_a_zone(start_pfn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 						    start_pfn + nr_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		if (!default_zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 			return sysfs_emit(buf, "%s\n", "none");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		len += sysfs_emit_at(buf, len, "%s", default_zone->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	nid = mem->nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	default_zone = zone_for_pfn_range(MMOP_ONLINE, nid, start_pfn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 					  nr_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	len += sysfs_emit_at(buf, len, "%s", default_zone->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	len += print_allowed_zone(buf, len, nid, start_pfn, nr_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 				  MMOP_ONLINE_KERNEL, default_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	len += print_allowed_zone(buf, len, nid, start_pfn, nr_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 				  MMOP_ONLINE_MOVABLE, default_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	len += sysfs_emit_at(buf, len, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static DEVICE_ATTR_RO(valid_zones);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) static DEVICE_ATTR_RO(phys_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static DEVICE_ATTR_RW(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static DEVICE_ATTR_RO(phys_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static DEVICE_ATTR_RO(removable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)  * Show the memory block size (shared by all memory blocks).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static ssize_t block_size_bytes_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 				     struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	return sysfs_emit(buf, "%lx\n", memory_block_size_bytes());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static DEVICE_ATTR_RO(block_size_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)  * Memory auto online policy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) static ssize_t auto_online_blocks_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 				       struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	return sysfs_emit(buf, "%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 			  online_type_to_str[memhp_default_online_type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static ssize_t auto_online_blocks_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 					struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 					const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	const int online_type = memhp_online_type_from_str(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	if (online_type < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	memhp_default_online_type = online_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) static DEVICE_ATTR_RW(auto_online_blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)  * Some architectures will have custom drivers to do this, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)  * will not need to do it from userspace.  The fake hot-add code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)  * as well as ppc64 will do all of their discovery in userspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)  * and will require this interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) #ifdef CONFIG_ARCH_MEMORY_PROBE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static ssize_t probe_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 			   const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	u64 phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	int nid, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	unsigned long pages_per_block = PAGES_PER_SECTION * sections_per_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	ret = kstrtoull(buf, 0, &phys_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	if (phys_addr & ((pages_per_block << PAGE_SHIFT) - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	ret = lock_device_hotplug_sysfs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	nid = memory_add_physaddr_to_nid(phys_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	ret = __add_memory(nid, phys_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 			   MIN_MEMORY_BLOCK_SIZE * sections_per_block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 			   MHP_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	ret = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	unlock_device_hotplug();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) static DEVICE_ATTR_WO(probe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) #ifdef CONFIG_MEMORY_FAILURE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)  * Support for offlining pages of memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /* Soft offline a page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static ssize_t soft_offline_page_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 				       struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 				       const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	u64 pfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	if (kstrtoull(buf, 0, &pfn) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	pfn >>= PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	ret = soft_offline_page(pfn, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	return ret == 0 ? count : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) /* Forcibly offline a page, including killing processes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) static ssize_t hard_offline_page_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 				       struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 				       const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	u64 pfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	if (kstrtoull(buf, 0, &pfn) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	pfn >>= PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	ret = memory_failure(pfn, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	return ret ? ret : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) static DEVICE_ATTR_WO(soft_offline_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static DEVICE_ATTR_WO(hard_offline_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /* See phys_device_show(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) int __weak arch_get_memory_phys_device(unsigned long start_pfn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)  * A reference for the returned memory block device is acquired.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)  * Called under device_hotplug_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) static struct memory_block *find_memory_block_by_id(unsigned long block_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	struct memory_block *mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	mem = xa_load(&memory_blocks, block_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	if (mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 		get_device(&mem->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	return mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)  * Called under device_hotplug_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) struct memory_block *find_memory_block(struct mem_section *section)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	unsigned long block_id = memory_block_id(__section_nr(section));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	return find_memory_block_by_id(block_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) static struct attribute *memory_memblk_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	&dev_attr_phys_index.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	&dev_attr_state.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	&dev_attr_phys_device.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	&dev_attr_removable.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) #ifdef CONFIG_MEMORY_HOTREMOVE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	&dev_attr_valid_zones.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) static struct attribute_group memory_memblk_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	.attrs = memory_memblk_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) static const struct attribute_group *memory_memblk_attr_groups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	&memory_memblk_attr_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)  * register_memory - Setup a sysfs device for a memory block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) int register_memory(struct memory_block *memory)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	memory->dev.bus = &memory_subsys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	memory->dev.id = memory->start_section_nr / sections_per_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	memory->dev.release = memory_block_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	memory->dev.groups = memory_memblk_attr_groups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	memory->dev.offline = memory->state == MEM_OFFLINE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	ret = device_register(&memory->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 		put_device(&memory->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	ret = xa_err(xa_store(&memory_blocks, memory->dev.id, memory,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 			      GFP_KERNEL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 		put_device(&memory->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 		device_unregister(&memory->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) static int init_memory_block(unsigned long block_id, unsigned long state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	struct memory_block *mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	mem = find_memory_block_by_id(block_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	if (mem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 		put_device(&mem->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 		return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 	if (!mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	mem->start_section_nr = block_id * sections_per_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	mem->state = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	mem->nid = NUMA_NO_NODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	ret = register_memory(mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) static int add_memory_block(unsigned long base_section_nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	int section_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	unsigned long nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	for (nr = base_section_nr; nr < base_section_nr + sections_per_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 	     nr++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 		if (present_section_nr(nr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 			section_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	if (section_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	return init_memory_block(memory_block_id(base_section_nr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 				 MEM_ONLINE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static void unregister_memory(struct memory_block *memory)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	if (WARN_ON_ONCE(memory->dev.bus != &memory_subsys))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	WARN_ON(xa_erase(&memory_blocks, memory->dev.id) == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 	/* drop the ref. we got via find_memory_block() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	put_device(&memory->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 	device_unregister(&memory->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)  * Create memory block devices for the given memory area. Start and size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)  * have to be aligned to memory block granularity. Memory block devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)  * will be initialized as offline.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)  * Called under device_hotplug_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) int create_memory_block_devices(unsigned long start, unsigned long size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	const unsigned long start_block_id = pfn_to_block_id(PFN_DOWN(start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	unsigned long end_block_id = pfn_to_block_id(PFN_DOWN(start + size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	struct memory_block *mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	unsigned long block_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	if (WARN_ON_ONCE(!IS_ALIGNED(start, memory_block_size_bytes()) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 			 !IS_ALIGNED(size, memory_block_size_bytes())))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	for (block_id = start_block_id; block_id != end_block_id; block_id++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 		ret = init_memory_block(block_id, MEM_OFFLINE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 		end_block_id = block_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 		for (block_id = start_block_id; block_id != end_block_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 		     block_id++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 			mem = find_memory_block_by_id(block_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 			if (WARN_ON_ONCE(!mem))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 			unregister_memory(mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)  * Remove memory block devices for the given memory area. Start and size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)  * have to be aligned to memory block granularity. Memory block devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)  * have to be offline.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)  * Called under device_hotplug_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) void remove_memory_block_devices(unsigned long start, unsigned long size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	const unsigned long start_block_id = pfn_to_block_id(PFN_DOWN(start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 	const unsigned long end_block_id = pfn_to_block_id(PFN_DOWN(start + size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 	struct memory_block *mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 	unsigned long block_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 	if (WARN_ON_ONCE(!IS_ALIGNED(start, memory_block_size_bytes()) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 			 !IS_ALIGNED(size, memory_block_size_bytes())))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	for (block_id = start_block_id; block_id != end_block_id; block_id++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 		mem = find_memory_block_by_id(block_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 		if (WARN_ON_ONCE(!mem))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 		unregister_memory_block_under_nodes(mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 		unregister_memory(mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) /* return true if the memory block is offlined, otherwise, return false */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) bool is_memblock_offlined(struct memory_block *mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 	return mem->state == MEM_OFFLINE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) static struct attribute *memory_root_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) #ifdef CONFIG_ARCH_MEMORY_PROBE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 	&dev_attr_probe.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) #ifdef CONFIG_MEMORY_FAILURE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 	&dev_attr_soft_offline_page.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 	&dev_attr_hard_offline_page.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 	&dev_attr_block_size_bytes.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 	&dev_attr_auto_online_blocks.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 	NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) static struct attribute_group memory_root_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 	.attrs = memory_root_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) static const struct attribute_group *memory_root_attr_groups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 	&memory_root_attr_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)  * Initialize the sysfs support for memory devices. At the time this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)  * is called, we cannot have concurrent creation/deletion of memory block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)  * devices, the device_hotplug_lock is not needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) void __init memory_dev_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 	unsigned long block_sz, nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	/* Validate the configured memory block size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 	block_sz = memory_block_size_bytes();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 	if (!is_power_of_2(block_sz) || block_sz < MIN_MEMORY_BLOCK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 		panic("Memory block size not suitable: 0x%lx\n", block_sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 	sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 	ret = subsys_system_register(&memory_subsys, memory_root_attr_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 		panic("%s() failed to register subsystem: %d\n", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 	 * Create entries for memory sections that were found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 	 * during boot and have been initialized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 	for (nr = 0; nr <= __highest_present_section_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 	     nr += sections_per_block) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 		ret = add_memory_block(nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 			panic("%s() failed to add memory block: %d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 			      ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)  * walk_memory_blocks - walk through all present memory blocks overlapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)  *			by the range [start, start + size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)  * @start: start address of the memory range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)  * @size: size of the memory range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)  * @arg: argument passed to func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)  * @func: callback for each memory section walked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)  * This function walks through all present memory blocks overlapped by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)  * range [start, start + size), calling func on each memory block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)  * In case func() returns an error, walking is aborted and the error is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)  * returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)  * Called under device_hotplug_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) int walk_memory_blocks(unsigned long start, unsigned long size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 		       void *arg, walk_memory_blocks_func_t func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 	const unsigned long start_block_id = phys_to_block_id(start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 	const unsigned long end_block_id = phys_to_block_id(start + size - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 	struct memory_block *mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 	unsigned long block_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 	if (!size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 	for (block_id = start_block_id; block_id <= end_block_id; block_id++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 		mem = find_memory_block_by_id(block_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 		if (!mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 		ret = func(mem, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 		put_device(&mem->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) struct for_each_memory_block_cb_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 	walk_memory_blocks_func_t func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 	void *arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) static int for_each_memory_block_cb(struct device *dev, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 	struct memory_block *mem = to_memory_block(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 	struct for_each_memory_block_cb_data *cb_data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) 	return cb_data->func(mem, cb_data->arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)  * for_each_memory_block - walk through all present memory blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)  * @arg: argument passed to func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)  * @func: callback for each memory block walked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)  * This function walks through all present memory blocks, calling func on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)  * each memory block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)  * In case func() returns an error, walking is aborted and the error is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)  * returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) int for_each_memory_block(void *arg, walk_memory_blocks_func_t func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 	struct for_each_memory_block_cb_data cb_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 		.func = func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) 		.arg = arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 	return bus_for_each_dev(&memory_subsys, NULL, &cb_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 				for_each_memory_block_cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }