^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2004, 2013 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author: Naveen B S <naveen.b.s@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * ACPI based HotPlug driver that supports Memory Hotplug
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * This driver fields notifications from firmware for memory add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * and remove operations and alerts the VM of the affected memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * ranges.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/memory.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/memory_hotplug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define ACPI_MEMORY_DEVICE_CLASS "memory"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define ACPI_MEMORY_DEVICE_HID "PNP0C80"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define ACPI_MEMORY_DEVICE_NAME "Hotplug Mem Device"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static const struct acpi_device_id memory_device_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {ACPI_MEMORY_DEVICE_HID, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {"", 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #ifdef CONFIG_ACPI_HOTPLUG_MEMORY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static int acpi_memory_device_add(struct acpi_device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) const struct acpi_device_id *not_used);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static void acpi_memory_device_remove(struct acpi_device *device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static struct acpi_scan_handler memory_device_handler = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) .ids = memory_device_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) .attach = acpi_memory_device_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .detach = acpi_memory_device_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .hotplug = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .enabled = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct acpi_memory_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) u64 start_addr; /* Memory Range start physical addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) u64 length; /* Memory Range length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) unsigned short caching; /* memory cache attribute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) unsigned short write_protect; /* memory read/write attribute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned int enabled:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct acpi_memory_device {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct acpi_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct list_head res_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static acpi_status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) acpi_memory_get_resource(struct acpi_resource *resource, void *context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct acpi_memory_device *mem_device = context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct acpi_resource_address64 address64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct acpi_memory_info *info, *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) status = acpi_resource_to_address64(resource, &address64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (ACPI_FAILURE(status) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) (address64.resource_type != ACPI_MEMORY_RANGE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) list_for_each_entry(info, &mem_device->res_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* Can we combine the resource range information? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if ((info->caching == address64.info.mem.caching) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) (info->write_protect == address64.info.mem.write_protect) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) (info->start_addr + info->length == address64.address.minimum)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) info->length += address64.address.address_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) new = kzalloc(sizeof(struct acpi_memory_info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (!new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return AE_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) INIT_LIST_HEAD(&new->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) new->caching = address64.info.mem.caching;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) new->write_protect = address64.info.mem.write_protect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) new->start_addr = address64.address.minimum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) new->length = address64.address.address_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) list_add_tail(&new->list, &mem_device->res_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) acpi_memory_free_device_resources(struct acpi_memory_device *mem_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct acpi_memory_info *info, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) list_for_each_entry_safe(info, n, &mem_device->res_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) kfree(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) INIT_LIST_HEAD(&mem_device->res_list);
^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) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (!list_empty(&mem_device->res_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) acpi_memory_get_resource, mem_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) acpi_memory_free_device_resources(mem_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) unsigned long long current_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* Get device present/absent information from the _STA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) METHOD_NAME__STA, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ¤t_status)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * Check for device status. Device should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * present/enabled/functioning.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (!((current_status & ACPI_STA_DEVICE_PRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) && (current_status & ACPI_STA_DEVICE_ENABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) && (current_status & ACPI_STA_DEVICE_FUNCTIONING)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static int acpi_bind_memblk(struct memory_block *mem, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return acpi_bind_one(&mem->dev, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static int acpi_bind_memory_blocks(struct acpi_memory_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct acpi_device *adev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return walk_memory_blocks(info->start_addr, info->length, adev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) acpi_bind_memblk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static int acpi_unbind_memblk(struct memory_block *mem, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) acpi_unbind_one(&mem->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static void acpi_unbind_memory_blocks(struct acpi_memory_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) walk_memory_blocks(info->start_addr, info->length, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) acpi_unbind_memblk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) acpi_handle handle = mem_device->device->handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int result, num_enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct acpi_memory_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) int node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) node = acpi_get_node(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * Tell the VM there is more memory here...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * Note: Assume that this function returns zero on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * We don't have memory-hot-add rollback function,now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * (i.e. memory-hot-remove function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) list_for_each_entry(info, &mem_device->res_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (info->enabled) { /* just sanity check...*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) num_enabled++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * If the memory block size is zero, please ignore it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * Don't try to do the following memory hotplug flowchart.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (!info->length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (node < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) node = memory_add_physaddr_to_nid(info->start_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) result = __add_memory(node, info->start_addr, info->length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) MHP_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * If the memory block has been used by the kernel, add_memory()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * returns -EEXIST. If add_memory() returns the other error, it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * means that this memory block is not used by the kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (result && result != -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) result = acpi_bind_memory_blocks(info, mem_device->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) acpi_unbind_memory_blocks(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) info->enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * Add num_enable even if add_memory() returns -EEXIST, so the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * device is bound to this driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) num_enabled++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (!num_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) dev_err(&mem_device->device->dev, "add_memory failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * Sometimes the memory device will contain several memory blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * When one memory block is hot-added to the system memory, it will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * be regarded as a success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * Otherwise if the last memory block can't be hot-added to the system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * memory, it will be failure and the memory device can't be bound with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static void acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) acpi_handle handle = mem_device->device->handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct acpi_memory_info *info, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int nid = acpi_get_node(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (!info->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (nid == NUMA_NO_NODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) nid = memory_add_physaddr_to_nid(info->start_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) acpi_unbind_memory_blocks(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) __remove_memory(nid, info->start_addr, info->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) list_del(&info->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) kfree(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static void acpi_memory_device_free(struct acpi_memory_device *mem_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (!mem_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) acpi_memory_free_device_resources(mem_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) mem_device->device->driver_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) kfree(mem_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static int acpi_memory_device_add(struct acpi_device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) const struct acpi_device_id *not_used)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct acpi_memory_device *mem_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (!device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) mem_device = kzalloc(sizeof(struct acpi_memory_device), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (!mem_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) INIT_LIST_HEAD(&mem_device->res_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) mem_device->device = device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) device->driver_data = mem_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /* Get the range from the _CRS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) result = acpi_memory_get_device_resources(mem_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) device->driver_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) kfree(mem_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) result = acpi_memory_check_device(mem_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) acpi_memory_device_free(mem_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) result = acpi_memory_enable_device(mem_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) dev_err(&device->dev, "acpi_memory_enable_device() error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) acpi_memory_device_free(mem_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) dev_dbg(&device->dev, "Memory device configured by ACPI\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static void acpi_memory_device_remove(struct acpi_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct acpi_memory_device *mem_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (!device || !acpi_driver_data(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) mem_device = acpi_driver_data(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) acpi_memory_remove_memory(mem_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) acpi_memory_device_free(mem_device);
^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 bool __initdata acpi_no_memhotplug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) void __init acpi_memory_hotplug_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (acpi_no_memhotplug) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) memory_device_handler.attach = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) acpi_scan_add_handler(&memory_device_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) acpi_scan_add_handler_with_hotplug(&memory_device_handler, "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static int __init disable_acpi_memory_hotplug(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) acpi_no_memhotplug = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) __setup("acpi_no_memhotplug", disable_acpi_memory_hotplug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static struct acpi_scan_handler memory_device_handler = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) .ids = memory_device_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) void __init acpi_memory_hotplug_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) acpi_scan_add_handler(&memory_device_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) #endif /* CONFIG_ACPI_HOTPLUG_MEMORY */