^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) }