From patchwork Tue Feb 19 18:11:57 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vasilis Liaskovitis X-Patchwork-Id: 2163871 Return-Path: X-Original-To: patchwork-linux-acpi@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 1F60E3FDF1 for ; Tue, 19 Feb 2013 18:12:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758898Ab3BSSMF (ORCPT ); Tue, 19 Feb 2013 13:12:05 -0500 Received: from mail-bk0-f46.google.com ([209.85.214.46]:34356 "EHLO mail-bk0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758877Ab3BSSMD (ORCPT ); Tue, 19 Feb 2013 13:12:03 -0500 Received: by mail-bk0-f46.google.com with SMTP id j5so3251261bkw.19 for ; Tue, 19 Feb 2013 10:12:01 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:date:from:to:cc:subject:message-id:references :mime-version:content-type:content-disposition:in-reply-to :user-agent:x-gm-message-state; bh=BR9rNf2+JiBZ29LJrdnpgaOYxnjaedPQE+uQYmD5XVQ=; b=BqaD82iYTO99n1Bcq8LM0MJb+aCKLBZXR8fdlG76YtDbZ0o8eBk8j6gI5KSc3SIvZ7 5Ud+EPLcWTVr8lXx0q/2S1l/gmkcT2YY1LdlKld5P6YKgo6cdh1+nBZXkIu0W47BKk5/ /X1+uGHpXzbjqoPdpdENbIPmg/4//vW4l4mQsd0y+ID11IC+7JalRMxKp7DQ5uOESvuM YYgk/WoV1K8Ea6rpH5RV9IkSsSOdlkZ4Zt2WffQoISf7UfF6ogizPcXPwWPKdFa8GFhP WIRQtAYAieqGbIZ5K7nrg4or9Ylo6a0+1XG65Dr7zCSxn1SSkn7S643wXqcj0Pf1Yfma CgcA== X-Received: by 10.204.147.10 with SMTP id j10mr7006339bkv.7.1361297521142; Tue, 19 Feb 2013 10:12:01 -0800 (PST) Received: from dhcp-192-168-178-175.profitbricks.localdomain ([62.217.45.26]) by mx.google.com with ESMTPS id hc16sm22471095bkc.2.2013.02.19.10.11.59 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Tue, 19 Feb 2013 10:12:00 -0800 (PST) Date: Tue, 19 Feb 2013 19:11:57 +0100 From: Vasilis Liaskovitis To: "Rafael J. Wysocki" Cc: ACPI Devel Maling List , Bjorn Helgaas , LKML , Yinghai Lu , Toshi Kani , Yasuaki Ishimatsu , Jiang Liu Subject: Re: [PATCH 7/7] ACPI / scan: Make memory hotplug driver use struct acpi_scan_handler Message-ID: <20130219181157.GA4366@dhcp-192-168-178-175.profitbricks.localdomain> References: <3260206.bhaAobGhpZ@vostro.rjw.lan> <2200731.3okUfey51A@vostro.rjw.lan> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <2200731.3okUfey51A@vostro.rjw.lan> User-Agent: Mutt/1.5.21 (2010-09-15) X-Gm-Message-State: ALoCoQnL4mQii9p9IZ1QdALEsTIS4+3Ih2/oMfwUsHJ4bH2fop8N5HcYrxnsg58HywZ9ofyXtnsM Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Hi, On Sun, Feb 17, 2013 at 04:27:18PM +0100, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki > > Make the ACPI memory hotplug driver use struct acpi_scan_handler > for representing the object used to set up ACPI memory hotplug > functionality and to remove hotplug memory ranges and data > structures used by the driver before unregistering ACPI device > nodes representing memory. Register the new struct acpi_scan_handler > object with the help of acpi_scan_add_handler_with_hotplug() to allow > user space to manipulate the attributes of the memory hotplug > profile. Let's consider an example where we want acpi memory device ejection to be safely handled by userspace. We do the following: echo 0 > /sys/firmware/acpi/hotplug/memory/autoeject echo 1 > /sys/firmware/acpi/hotplug/memory/uevents We succesfully hotplug acpi device: /sys/devices/LNXSYSTM:00/LNXSYSBUS:00/PNP0C80:00 and its corresponding memblocks /sys/devices/system/memory/memoryXX are also successfully onlined. On an eject request, since uevents == 1, the kernel will emit KOBJ_OFFLINE for: /sys/devices/LNXSYSTM:00/LNXSYSBUS:00/PNP0C80:00 Can userspace know which memblocks in /sys/devices/system/memory/memoryXX/ correspond to the acpi device /sys/devices/LNXSYSTM:00/LNXSYSBUS:00/PNP0C80:00 ? This will be needed so that userspace tries to offline the memblocks (and only if successful, issue the eject operation on the acpi device). As far as I see, we don't create any sysfs links or files for this scenario - can userspace get this info somehow? /sys/devices/system/memory/memoryXX/phys_device needs to be properly implemented for this to work I think, see Documentation/ABI/testing/sysfs-memory The following test patch works toward that direction. Let me know if it's of interest or if there are better ideas /comments. From: Vasilis Liaskovitis Date: Tue, 19 Feb 2013 18:36:25 +0100 Subject: [RFC PATCH] acpi / memory-hotplug: implement phys_device In order for userspace to know which memblocks in: /sys/devices/system/memory/memoryXX correspond to which acpi memory devices in: /sys/devices/LNXSYSTM:00/LNXSYSBUS:00/PNP0C80:YY, /sys/devices/system/memory/memoryXX/phys_device should return a name (or index YY) of the memory device each memblock XX belongs to. WIth this patch, the acpi mem_hotplug driver keeps a global list of acpi memory devices (inserted in hotplug_order). The base memory driver checks against this list in arch_get_memory_phys_device to determine the zero-based index of the physical memory device each new memblock belongs to. For initial memory or for non-acpi/hotplug enabled systems, phys_device is always -1. Signed-off-by: Vasilis Liaskovitis --- Documentation/ABI/testing/sysfs-devices-memory | 8 ++++++- drivers/acpi/acpi_memhotplug.c | 27 ++++++++++++++++++++++++ drivers/base/memory.c | 7 +++++- include/linux/acpi.h | 2 + 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-devices-memory b/Documentation/ABI/testing/sysfs-devices-memory index 7405de2..290c62a 100644 --- a/Documentation/ABI/testing/sysfs-devices-memory +++ b/Documentation/ABI/testing/sysfs-devices-memory @@ -27,7 +27,13 @@ Contact: Badari Pulavarty Description: The file /sys/devices/system/memory/memoryX/phys_device is read-only and is designed to show the name of physical - memory device. Implementation is currently incomplete. + memory device. Implementation is currently incomplete. In a + system with CONFIG_ACPI_HOTPLUG_MEMORY=n, phys_device is always + -1. In a system with CONFIG_ACPI_HOTPLUG_MEMORY=y, phys_device + is -1 for all initial / non-hot-removable memory. For + memory that has been hot-plugged, phys_device will return the + zero-based index of the physical device that this memory block + belongs to. Indices are determined by hotplug order. What: /sys/devices/system/memory/memoryX/phys_index Date: September 2008 diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 3be9501..4154dc5 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -48,6 +48,7 @@ ACPI_MODULE_NAME("acpi_memhotplug"); #define MEMORY_POWER_ON_STATE 1 #define MEMORY_POWER_OFF_STATE 2 +static LIST_HEAD(acpi_mem_device_list); static int acpi_memory_device_add(struct acpi_device *device, const struct acpi_device_id *not_used); static void acpi_memory_device_remove(struct acpi_device *device); @@ -81,6 +82,7 @@ struct acpi_memory_device { struct acpi_device * device; unsigned int state; /* State of the memory device */ struct list_head res_list; + struct list_head mem_device_list; }; static acpi_status @@ -287,6 +289,7 @@ static int acpi_memory_device_add(struct acpi_device *device, return -ENOMEM; INIT_LIST_HEAD(&mem_device->res_list); + INIT_LIST_HEAD(&mem_device->mem_device_list); mem_device->device = device; sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME); sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS); @@ -308,9 +311,11 @@ static int acpi_memory_device_add(struct acpi_device *device, return 0; } + list_add_tail(&mem_device->mem_device_list, &acpi_mem_device_list); result = acpi_memory_enable_device(mem_device); if (result) { dev_err(&device->dev, "acpi_memory_enable_device() error\n"); + list_del(&mem_device->mem_device_list); acpi_memory_device_free(mem_device); return -ENODEV; } @@ -328,9 +333,31 @@ static void acpi_memory_device_remove(struct acpi_device *device) mem_device = acpi_driver_data(device); acpi_memory_remove_memory(mem_device); + list_del(&mem_device->mem_device_list); acpi_memory_device_free(mem_device); } +int acpi_memory_phys_device(unsigned long start_pfn) +{ + struct acpi_memory_device *mem_dev; + struct acpi_memory_info *info; + unsigned long start_addr = start_pfn << PAGE_SHIFT; + int id = 0; + + list_for_each_entry(mem_dev, &acpi_mem_device_list, mem_device_list) { + list_for_each_entry(info, &mem_dev->res_list, list) { + if ((info->start_addr <= start_addr) && + (info->start_addr + info->length > start_addr)) + return id; + } + id++; + } + + /* Memory not associated with a hot-pluggable device gets -1. For + * example, initial memory. */ + return -1; +} + void __init acpi_memory_hotplug_init(void) { acpi_scan_add_handler_with_hotplug(&memory_device_handler, "memory"); diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 8300a18..2cc98df 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -522,7 +523,11 @@ static inline int memory_fail_init(void) */ int __weak arch_get_memory_phys_device(unsigned long start_pfn) { - return 0; +#ifdef CONFIG_ACPI_HOTPLUG_MEMORY + return acpi_memory_phys_device(start_pfn); +#else + return -1; +#endif } /* diff --git a/include/linux/acpi.h b/include/linux/acpi.h index f46cfd7..00302fc 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -562,6 +562,8 @@ static inline __printf(3, 4) void acpi_handle_printk(const char *level, void *handle, const char *fmt, ...) {} #endif /* !CONFIG_ACPI */ +int acpi_memory_phys_device(unsigned long start_pfn); + /* * acpi_handle_: Print message with ACPI prefix and object path *