Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2004, 2013 Intel Corporation
0004  * Author: Naveen B S <naveen.b.s@intel.com>
0005  * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
0006  *
0007  * All rights reserved.
0008  *
0009  * ACPI based HotPlug driver that supports Memory Hotplug
0010  * This driver fields notifications from firmware for memory add
0011  * and remove operations and alerts the VM of the affected memory
0012  * ranges.
0013  */
0014 
0015 #include <linux/acpi.h>
0016 #include <linux/memory.h>
0017 #include <linux/memory_hotplug.h>
0018 
0019 #include "internal.h"
0020 
0021 #define ACPI_MEMORY_DEVICE_CLASS        "memory"
0022 #define ACPI_MEMORY_DEVICE_HID          "PNP0C80"
0023 #define ACPI_MEMORY_DEVICE_NAME         "Hotplug Mem Device"
0024 
0025 static const struct acpi_device_id memory_device_ids[] = {
0026     {ACPI_MEMORY_DEVICE_HID, 0},
0027     {"", 0},
0028 };
0029 
0030 #ifdef CONFIG_ACPI_HOTPLUG_MEMORY
0031 
0032 static int acpi_memory_device_add(struct acpi_device *device,
0033                   const struct acpi_device_id *not_used);
0034 static void acpi_memory_device_remove(struct acpi_device *device);
0035 
0036 static struct acpi_scan_handler memory_device_handler = {
0037     .ids = memory_device_ids,
0038     .attach = acpi_memory_device_add,
0039     .detach = acpi_memory_device_remove,
0040     .hotplug = {
0041         .enabled = true,
0042     },
0043 };
0044 
0045 struct acpi_memory_info {
0046     struct list_head list;
0047     u64 start_addr;     /* Memory Range start physical addr */
0048     u64 length;     /* Memory Range length */
0049     unsigned short caching; /* memory cache attribute */
0050     unsigned short write_protect;   /* memory read/write attribute */
0051     unsigned int enabled:1;
0052 };
0053 
0054 struct acpi_memory_device {
0055     struct acpi_device *device;
0056     struct list_head res_list;
0057     int mgid;
0058 };
0059 
0060 static acpi_status
0061 acpi_memory_get_resource(struct acpi_resource *resource, void *context)
0062 {
0063     struct acpi_memory_device *mem_device = context;
0064     struct acpi_resource_address64 address64;
0065     struct acpi_memory_info *info, *new;
0066     acpi_status status;
0067 
0068     status = acpi_resource_to_address64(resource, &address64);
0069     if (ACPI_FAILURE(status) ||
0070         (address64.resource_type != ACPI_MEMORY_RANGE))
0071         return AE_OK;
0072 
0073     list_for_each_entry(info, &mem_device->res_list, list) {
0074         /* Can we combine the resource range information? */
0075         if ((info->caching == address64.info.mem.caching) &&
0076             (info->write_protect == address64.info.mem.write_protect) &&
0077             (info->start_addr + info->length == address64.address.minimum)) {
0078             info->length += address64.address.address_length;
0079             return AE_OK;
0080         }
0081     }
0082 
0083     new = kzalloc(sizeof(struct acpi_memory_info), GFP_KERNEL);
0084     if (!new)
0085         return AE_ERROR;
0086 
0087     INIT_LIST_HEAD(&new->list);
0088     new->caching = address64.info.mem.caching;
0089     new->write_protect = address64.info.mem.write_protect;
0090     new->start_addr = address64.address.minimum;
0091     new->length = address64.address.address_length;
0092     list_add_tail(&new->list, &mem_device->res_list);
0093 
0094     return AE_OK;
0095 }
0096 
0097 static void
0098 acpi_memory_free_device_resources(struct acpi_memory_device *mem_device)
0099 {
0100     struct acpi_memory_info *info, *n;
0101 
0102     list_for_each_entry_safe(info, n, &mem_device->res_list, list)
0103         kfree(info);
0104     INIT_LIST_HEAD(&mem_device->res_list);
0105 }
0106 
0107 static int
0108 acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
0109 {
0110     acpi_status status;
0111 
0112     if (!list_empty(&mem_device->res_list))
0113         return 0;
0114 
0115     status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS,
0116                      acpi_memory_get_resource, mem_device);
0117     if (ACPI_FAILURE(status)) {
0118         acpi_memory_free_device_resources(mem_device);
0119         return -EINVAL;
0120     }
0121 
0122     return 0;
0123 }
0124 
0125 static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
0126 {
0127     unsigned long long current_status;
0128 
0129     /* Get device present/absent information from the _STA */
0130     if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle,
0131                            METHOD_NAME__STA, NULL,
0132                            &current_status)))
0133         return -ENODEV;
0134     /*
0135      * Check for device status. Device should be
0136      * present/enabled/functioning.
0137      */
0138     if (!((current_status & ACPI_STA_DEVICE_PRESENT)
0139           && (current_status & ACPI_STA_DEVICE_ENABLED)
0140           && (current_status & ACPI_STA_DEVICE_FUNCTIONING)))
0141         return -ENODEV;
0142 
0143     return 0;
0144 }
0145 
0146 static int acpi_bind_memblk(struct memory_block *mem, void *arg)
0147 {
0148     return acpi_bind_one(&mem->dev, arg);
0149 }
0150 
0151 static int acpi_bind_memory_blocks(struct acpi_memory_info *info,
0152                    struct acpi_device *adev)
0153 {
0154     return walk_memory_blocks(info->start_addr, info->length, adev,
0155                   acpi_bind_memblk);
0156 }
0157 
0158 static int acpi_unbind_memblk(struct memory_block *mem, void *arg)
0159 {
0160     acpi_unbind_one(&mem->dev);
0161     return 0;
0162 }
0163 
0164 static void acpi_unbind_memory_blocks(struct acpi_memory_info *info)
0165 {
0166     walk_memory_blocks(info->start_addr, info->length, NULL,
0167                acpi_unbind_memblk);
0168 }
0169 
0170 static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
0171 {
0172     acpi_handle handle = mem_device->device->handle;
0173     mhp_t mhp_flags = MHP_NID_IS_MGID;
0174     int result, num_enabled = 0;
0175     struct acpi_memory_info *info;
0176     u64 total_length = 0;
0177     int node, mgid;
0178 
0179     node = acpi_get_node(handle);
0180 
0181     list_for_each_entry(info, &mem_device->res_list, list) {
0182         if (!info->length)
0183             continue;
0184         /* We want a single node for the whole memory group */
0185         if (node < 0)
0186             node = memory_add_physaddr_to_nid(info->start_addr);
0187         total_length += info->length;
0188     }
0189 
0190     if (!total_length) {
0191         dev_err(&mem_device->device->dev, "device is empty\n");
0192         return -EINVAL;
0193     }
0194 
0195     mgid = memory_group_register_static(node, PFN_UP(total_length));
0196     if (mgid < 0)
0197         return mgid;
0198     mem_device->mgid = mgid;
0199 
0200     /*
0201      * Tell the VM there is more memory here...
0202      * Note: Assume that this function returns zero on success
0203      * We don't have memory-hot-add rollback function,now.
0204      * (i.e. memory-hot-remove function)
0205      */
0206     list_for_each_entry(info, &mem_device->res_list, list) {
0207         /*
0208          * If the memory block size is zero, please ignore it.
0209          * Don't try to do the following memory hotplug flowchart.
0210          */
0211         if (!info->length)
0212             continue;
0213 
0214         if (mhp_supports_memmap_on_memory(info->length))
0215             mhp_flags |= MHP_MEMMAP_ON_MEMORY;
0216         result = __add_memory(mgid, info->start_addr, info->length,
0217                       mhp_flags);
0218 
0219         /*
0220          * If the memory block has been used by the kernel, add_memory()
0221          * returns -EEXIST. If add_memory() returns the other error, it
0222          * means that this memory block is not used by the kernel.
0223          */
0224         if (result && result != -EEXIST)
0225             continue;
0226 
0227         result = acpi_bind_memory_blocks(info, mem_device->device);
0228         if (result) {
0229             acpi_unbind_memory_blocks(info);
0230             return -ENODEV;
0231         }
0232 
0233         info->enabled = 1;
0234 
0235         /*
0236          * Add num_enable even if add_memory() returns -EEXIST, so the
0237          * device is bound to this driver.
0238          */
0239         num_enabled++;
0240     }
0241     if (!num_enabled) {
0242         dev_err(&mem_device->device->dev, "add_memory failed\n");
0243         return -EINVAL;
0244     }
0245     /*
0246      * Sometimes the memory device will contain several memory blocks.
0247      * When one memory block is hot-added to the system memory, it will
0248      * be regarded as a success.
0249      * Otherwise if the last memory block can't be hot-added to the system
0250      * memory, it will be failure and the memory device can't be bound with
0251      * driver.
0252      */
0253     return 0;
0254 }
0255 
0256 static void acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
0257 {
0258     struct acpi_memory_info *info, *n;
0259 
0260     list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
0261         if (!info->enabled)
0262             continue;
0263 
0264         acpi_unbind_memory_blocks(info);
0265         __remove_memory(info->start_addr, info->length);
0266         list_del(&info->list);
0267         kfree(info);
0268     }
0269 }
0270 
0271 static void acpi_memory_device_free(struct acpi_memory_device *mem_device)
0272 {
0273     if (!mem_device)
0274         return;
0275 
0276     /* In case we succeeded adding *some* memory, unregistering fails. */
0277     if (mem_device->mgid >= 0)
0278         memory_group_unregister(mem_device->mgid);
0279 
0280     acpi_memory_free_device_resources(mem_device);
0281     mem_device->device->driver_data = NULL;
0282     kfree(mem_device);
0283 }
0284 
0285 static int acpi_memory_device_add(struct acpi_device *device,
0286                   const struct acpi_device_id *not_used)
0287 {
0288     struct acpi_memory_device *mem_device;
0289     int result;
0290 
0291     if (!device)
0292         return -EINVAL;
0293 
0294     mem_device = kzalloc(sizeof(struct acpi_memory_device), GFP_KERNEL);
0295     if (!mem_device)
0296         return -ENOMEM;
0297 
0298     INIT_LIST_HEAD(&mem_device->res_list);
0299     mem_device->device = device;
0300     mem_device->mgid = -1;
0301     sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME);
0302     sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS);
0303     device->driver_data = mem_device;
0304 
0305     /* Get the range from the _CRS */
0306     result = acpi_memory_get_device_resources(mem_device);
0307     if (result) {
0308         device->driver_data = NULL;
0309         kfree(mem_device);
0310         return result;
0311     }
0312 
0313     result = acpi_memory_check_device(mem_device);
0314     if (result) {
0315         acpi_memory_device_free(mem_device);
0316         return 0;
0317     }
0318 
0319     result = acpi_memory_enable_device(mem_device);
0320     if (result) {
0321         dev_err(&device->dev, "acpi_memory_enable_device() error\n");
0322         acpi_memory_device_free(mem_device);
0323         return result;
0324     }
0325 
0326     dev_dbg(&device->dev, "Memory device configured by ACPI\n");
0327     return 1;
0328 }
0329 
0330 static void acpi_memory_device_remove(struct acpi_device *device)
0331 {
0332     struct acpi_memory_device *mem_device;
0333 
0334     if (!device || !acpi_driver_data(device))
0335         return;
0336 
0337     mem_device = acpi_driver_data(device);
0338     acpi_memory_remove_memory(mem_device);
0339     acpi_memory_device_free(mem_device);
0340 }
0341 
0342 static bool __initdata acpi_no_memhotplug;
0343 
0344 void __init acpi_memory_hotplug_init(void)
0345 {
0346     if (acpi_no_memhotplug) {
0347         memory_device_handler.attach = NULL;
0348         acpi_scan_add_handler(&memory_device_handler);
0349         return;
0350     }
0351     acpi_scan_add_handler_with_hotplug(&memory_device_handler, "memory");
0352 }
0353 
0354 static int __init disable_acpi_memory_hotplug(char *str)
0355 {
0356     acpi_no_memhotplug = true;
0357     return 1;
0358 }
0359 __setup("acpi_no_memhotplug", disable_acpi_memory_hotplug);
0360 
0361 #else
0362 
0363 static struct acpi_scan_handler memory_device_handler = {
0364     .ids = memory_device_ids,
0365 };
0366 
0367 void __init acpi_memory_hotplug_init(void)
0368 {
0369     acpi_scan_add_handler(&memory_device_handler);
0370 }
0371 
0372 #endif /* CONFIG_ACPI_HOTPLUG_MEMORY */