From patchwork Sun Nov 4 15:23:55 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Liu X-Patchwork-Id: 1694651 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id DE70FDF230 for ; Sun, 4 Nov 2012 15:27:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755201Ab2KDP1Q (ORCPT ); Sun, 4 Nov 2012 10:27:16 -0500 Received: from mail-pa0-f46.google.com ([209.85.220.46]:52244 "EHLO mail-pa0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755054Ab2KDPY3 (ORCPT ); Sun, 4 Nov 2012 10:24:29 -0500 Received: by mail-pa0-f46.google.com with SMTP id hz1so3385889pad.19 for ; Sun, 04 Nov 2012 07:24:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=hdkcRdBy7S2/rhnyu+vwdYAfX7YQZOsPwPLfFdX69Fw=; b=WTX6l7wB5OKHfJ+JKu0GwZfYKDKBVsof6bu36guVjeQcAlgH7sT0a7XvXAp/1Vn4Bu XijK/N6zJWhdP5Ee5irew3WOdmFNNMtDKOLCRkRJZws1QP0jACPT01Bln/nPDEByIAZD 8It8G4ZiGEIhClSqm7h77GcsRX4blurVI25vC5dijxeuuGi+FhFlVAzrkEKXiSFJkGKm 9XNrmzgcu53YNUSsssXuwxSmBv8HJNS2jNHxlK2Vj+8Nbf+xEBAlIhVOyjD8X+tUkqs7 xGjI3N2XdNoRJT8c1r+2KT65thuuqoBhDeuW6utqTymuzHAlA625Hv6k5cld77U7HYR5 N4XQ== Received: by 10.66.88.133 with SMTP id bg5mr21139258pab.80.1352042668833; Sun, 04 Nov 2012 07:24:28 -0800 (PST) Received: from localhost.localdomain ([120.196.98.117]) by mx.google.com with ESMTPS id nd6sm9020763pbc.68.2012.11.04.07.24.23 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 04 Nov 2012 07:24:28 -0800 (PST) From: Jiang Liu To: "Rafael J . Wysocki" , Yinghai Lu , Tony Luck , Yasuaki Ishimatsu , Wen Congyang , Tang Chen , Taku Izumi , Bjorn Helgaas Cc: Jiang Liu , Kenji Kaneshige , Huang Ying , Bob Moore , Len Brown , "Srivatsa S . Bhat" , Yijing Wang , Hanjun Guo , Jiang Liu , linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org, linux-mm@kvack.org Subject: [ACPIHP PATCH part4 2/9] ACPIHP/processor: reorganize ACPI processor driver for new hotplug framework Date: Sun, 4 Nov 2012 23:23:55 +0800 Message-Id: <1352042642-7306-3-git-send-email-jiang.liu@huawei.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1352042642-7306-1-git-send-email-jiang.liu@huawei.com> References: <1352042642-7306-1-git-send-email-jiang.liu@huawei.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org This patch reorganizes code in processor_driver.c to parepare for integration with the new hotplug framework. Common code could be shared among acpi_processor_add(), acpi_processor_remove() and hotplug has been reorganized as: acpi_processor_start() acpi_processor_stop() acpi_processor_link() acpi_processor_unlink() Signed-off-by: Jiang Liu --- drivers/acpi/processor_driver.c | 179 +++++++++++++++++++++++---------------- include/acpi/processor.h | 2 + 2 files changed, 108 insertions(+), 73 deletions(-) diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index aa9c43a..28add34 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -105,6 +105,8 @@ static struct acpi_driver acpi_processor_driver = { #define INSTALL_NOTIFY_HANDLER 1 #define UNINSTALL_NOTIFY_HANDLER 2 +static DEFINE_PER_CPU(void *, processor_device_array); + DEFINE_PER_CPU(struct acpi_processor *, processors); EXPORT_PER_CPU_SYMBOL(processors); @@ -327,11 +329,11 @@ static int acpi_processor_get_info(struct acpi_device *device) * \_SB.SCK1.CPU0 * Rename the processor device bus id. And the new bus id will be * generated as the following format: - * CPU+CPU ID. + * CPU+ACPI ID. */ - sprintf(acpi_device_bid(device), "CPU%X", pr->id); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, - pr->acpi_id)); + sprintf(acpi_device_bid(device), "CPU%X", pr->acpi_id); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->acpi_id, + pr->id)); if (!object.processor.pblk_address) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n")); @@ -355,19 +357,67 @@ static int acpi_processor_get_info(struct acpi_device *device) request_region(pr->throttling.address, 6, "ACPI CPU throttle"); } + return 0; +} + +static int acpi_processor_link(struct acpi_device *device, + struct acpi_processor *pr) +{ + struct device *dev; + acpi_status status; + unsigned long long value; + + if (pr->flags.device_linked) + return 0; + /* * If ACPI describes a slot number for this CPU, we can use it * ensure we get the right value in the "physical id" field * of /proc/cpuinfo */ - status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer); + status = acpi_evaluate_integer(pr->handle, "_SUN", NULL, &value); if (ACPI_SUCCESS(status)) - arch_fix_phys_package_id(pr->id, object.integer.value); + arch_fix_phys_package_id(pr->id, value); + + /* + * Buggy BIOS check + * ACPI id of processors can be reported wrongly by the BIOS. + * Don't trust it blindly + */ + if (per_cpu(processor_device_array, pr->id) != NULL && + per_cpu(processor_device_array, pr->id) != device) { + dev_warn(&device->dev, + "BIOS reported wrong ACPI id for the processor\n"); + return -ENODEV; + } + per_cpu(processor_device_array, pr->id) = device; + per_cpu(processors, pr->id) = pr; + + dev = get_cpu_device(pr->id); + if (sysfs_create_link(&device->dev.kobj, &dev->kobj, "sysdev")) { + /* + * processor_device_array is not cleared to allow checks + * for buggy BIOS + */ + per_cpu(processors, pr->id) = NULL; + return -EFAULT; + } + + pr->flags.device_linked = 1; return 0; } -static DEFINE_PER_CPU(void *, processor_device_array); +static void acpi_processor_unlink(struct acpi_device *device, + struct acpi_processor *pr) +{ + if (pr->flags.device_linked) { + sysfs_remove_link(&device->dev.kobj, "sysdev"); + per_cpu(processor_device_array, pr->id) = NULL; + per_cpu(processors, pr->id) = NULL; + pr->flags.device_linked = 0; + } +} static void acpi_processor_notify(struct acpi_device *device, u32 event) { @@ -422,11 +472,11 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb, if (pr->flags.need_hotplug_init) { printk(KERN_INFO "Will online and init hotplugged " "CPU: %d\n", pr->id); - WARN(acpi_processor_start(pr), "Failed to start CPU:" - " %d\n", pr->id); + WARN(acpi_processor_start(pr), + "Failed to start CPU: %d\n", pr->id); pr->flags.need_hotplug_init = 0; /* Normal CPU soft online event */ - } else { + } else if (pr->flags.device_started) { acpi_processor_ppc_has_changed(pr, 0); acpi_processor_hotplug(pr); acpi_processor_reevaluate_tstate(pr, action); @@ -458,6 +508,9 @@ static __ref int acpi_processor_start(struct acpi_processor *pr) struct acpi_device *device = per_cpu(processor_device_array, pr->id); int result = 0; + if (pr->flags.device_started) + return 0; + #ifdef CONFIG_CPU_FREQ acpi_processor_ppc_has_changed(pr, 0); acpi_processor_load_module(pr); @@ -493,6 +546,8 @@ static __ref int acpi_processor_start(struct acpi_processor *pr) goto err_remove_sysfs_thermal; } + pr->flags.device_started = 1; + return 0; err_remove_sysfs_thermal: @@ -505,6 +560,21 @@ err_power_exit: return result; } +static void acpi_processor_stop(struct acpi_device *device, + struct acpi_processor *pr) +{ + if (pr->flags.device_started) { + acpi_processor_power_exit(pr); + if (pr->cdev) { + sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); + sysfs_remove_link(&pr->cdev->device.kobj, "device"); + thermal_cooling_device_unregister(pr->cdev); + pr->cdev = NULL; + } + pr->flags.device_started = 0; + } +} + /* * Do not put anything in here which needs the core to be online. * For example MSR access or setting up things which check for cpuinfo_x86 @@ -513,9 +583,8 @@ err_power_exit: */ static int __cpuinit acpi_processor_add(struct acpi_device *device) { - struct acpi_processor *pr = NULL; - int result = 0; - struct device *dev; + struct acpi_processor *pr; + int result; pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL); if (!pr) @@ -532,60 +601,36 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) device->driver_data = pr; result = acpi_processor_get_info(device); - if (result) { - /* Processor is physically not present */ - return 0; - } - -#ifdef CONFIG_SMP - if (pr->id >= setup_max_cpus && pr->id != 0) - return 0; -#endif - - BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); - - /* - * Buggy BIOS check - * ACPI id of processors can be reported wrongly by the BIOS. - * Don't trust it blindly - */ - if (per_cpu(processor_device_array, pr->id) != NULL && - per_cpu(processor_device_array, pr->id) != device) { - printk(KERN_WARNING "BIOS reported wrong ACPI id " - "for the processor\n"); - result = -ENODEV; + if (result) goto err_free_cpumask; - } - per_cpu(processor_device_array, pr->id) = device; - - per_cpu(processors, pr->id) = pr; - - dev = get_cpu_device(pr->id); - if (sysfs_create_link(&device->dev.kobj, &dev->kobj, "sysdev")) { - result = -EFAULT; - goto err_clear_processor; - } /* - * Do not start hotplugged CPUs now, but when they - * are onlined the first time + * Delay linking with logical CPU device if: + * 1) no CPUID assigned yet + * 2) processor won't be boot if CPUID is bigger than setup_max_cpus + * They will be handled by CPU hotplug logical later. */ - if (pr->flags.need_hotplug_init) + if (pr->id == -1) return 0; + if (IS_BUILTIN(CONFIG_SMP) && pr->id >= setup_max_cpus && pr->id != 0) + return 0; + BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); - result = acpi_processor_start(pr); + result = acpi_processor_link(device, pr); if (result) - goto err_remove_sysfs; + goto err_unlock; + if (cpu_online(pr->id)) { + result = acpi_processor_start(pr); + if (result) + goto err_unlink; + } return 0; -err_remove_sysfs: - sysfs_remove_link(&device->dev.kobj, "sysdev"); -err_clear_processor: - /* - * processor_device_array is not cleared to allow checks for buggy BIOS - */ - per_cpu(processors, pr->id) = NULL; +err_unlink: + acpi_processor_unlink(device, pr); +err_unlock: + put_online_cpus(); err_free_cpumask: free_cpumask_var(pr->throttling.shared_cpu_map); err_free_pr: @@ -595,14 +640,12 @@ err_free_pr: static int acpi_processor_remove(struct acpi_device *device, int type) { - struct acpi_processor *pr = NULL; - + struct acpi_processor *pr; if (!device || !acpi_driver_data(device)) return -EINVAL; pr = acpi_driver_data(device); - if (pr->id >= nr_cpu_ids) goto free; @@ -611,21 +654,11 @@ static int acpi_processor_remove(struct acpi_device *device, int type) return -EINVAL; } - acpi_processor_power_exit(pr); - - sysfs_remove_link(&device->dev.kobj, "sysdev"); - - if (pr->cdev) { - sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); - sysfs_remove_link(&pr->cdev->device.kobj, "device"); - thermal_cooling_device_unregister(pr->cdev); - pr->cdev = NULL; - } - - per_cpu(processors, pr->id) = NULL; - per_cpu(processor_device_array, pr->id) = NULL; + acpi_processor_stop(device, pr); + acpi_processor_unlink(device, pr); free: + device->driver_data = NULL; free_cpumask_var(pr->throttling.shared_cpu_map); kfree(pr); diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 555d033..9e1c980 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -190,6 +190,8 @@ struct acpi_processor_flags { u8 power_setup_done:1; u8 bm_rld_set:1; u8 need_hotplug_init:1; + u8 device_linked:1; + u8 device_started:1; }; struct acpi_processor {