From patchwork Sat Oct 6 15:27:32 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Liu X-Patchwork-Id: 1558361 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 832CB3FCFC for ; Sat, 6 Oct 2012 15:35:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755007Ab2JFPfv (ORCPT ); Sat, 6 Oct 2012 11:35:51 -0400 Received: from mail-da0-f46.google.com ([209.85.210.46]:59359 "EHLO mail-da0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755014Ab2JFPfq (ORCPT ); Sat, 6 Oct 2012 11:35:46 -0400 Received: by mail-da0-f46.google.com with SMTP id n41so786899dak.19 for ; Sat, 06 Oct 2012 08:35:45 -0700 (PDT) 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=knsYvdE3c1DgcUOiFSnh2OoGBQhB+XUrlsLTQxt5/so=; b=jz0QD/WrXAdkXQmWs1/TcsUEjfVNuyk5FmfcAlA9ibFQGGb0vd9ukqm/msrQb4Ggal 56vnvEuY39fRFwaxevduiqRcKVW9gKPkY7wDWm8WhPbqrF68Oh8ArUXve6zqfyQKuYMd wkUxRSeq3o8Llj2CeB0P7KMp6gdnal8cCtjuTT0PSzUbVDUEabNDc1MSwu6ygoBwKt43 AEIQ1u5OfbrWufNxD6KbBnVt/ZgCccKyiCCOfoJb45EKOvnsByRMhLTT1LPnawvkRLuN EV99nSiVLdozf60kITMlbb92pLeDeQ9LVQcaes+5EgX/IPl/Pbz4dnF3D5uD7Qz3kVIl AMxg== Received: by 10.66.77.199 with SMTP id u7mr17678087paw.7.1349537745593; Sat, 06 Oct 2012 08:35:45 -0700 (PDT) Received: from localhost.localdomain ([221.221.24.247]) by mx.google.com with ESMTPS id vz8sm7785292pbc.63.2012.10.06.08.35.29 (version=TLSv1/SSLv3 cipher=OTHER); Sat, 06 Oct 2012 08:35:45 -0700 (PDT) From: Jiang Liu To: Yinghai Lu , Yasuaki Ishimatsu , Kenji Kaneshige , Wen Congyang , Tang Chen , Taku Izumi Cc: Hanjun Guo , Yijing Wang , Gong Chen , Jiang Liu , Tony Luck , Huang Ying , Bob Moore , Len Brown , "Srivatsa S . Bhat" , Bjorn Helgaas , linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org Subject: [RFC PATCH v3 24/28] CPU: introduce busy flag to temporarily disable CPU online sysfs interface Date: Sat, 6 Oct 2012 23:27:32 +0800 Message-Id: <1349537256-21670-25-git-send-email-jiang.liu@huawei.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1349537256-21670-1-git-send-email-jiang.liu@huawei.com> References: <1349537256-21670-1-git-send-email-jiang.liu@huawei.com> Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org When doing physical processor hotplug, all affected CPUs need to be handled in atomic and shouldn't be disturbed by online/offline requests from CPU device's online sysfs interface. So introduce a busy flag into struct cpu to temporariliy reject requests from online sysfs interface. Signed-off-by: Jiang Liu --- arch/ia64/include/asm/cpu.h | 2 +- arch/ia64/kernel/topology.c | 15 +++++++++------ arch/x86/include/asm/cpu.h | 2 +- arch/x86/kernel/topology.c | 10 ++++++---- drivers/acpi/processor_driver.c | 2 +- drivers/base/cpu.c | 22 ++++++++++++++++++++++ drivers/xen/cpu_hotplug.c | 2 +- include/linux/cpu.h | 2 ++ 8 files changed, 43 insertions(+), 14 deletions(-) diff --git a/arch/ia64/include/asm/cpu.h b/arch/ia64/include/asm/cpu.h index fcca30b..192fa2f 100644 --- a/arch/ia64/include/asm/cpu.h +++ b/arch/ia64/include/asm/cpu.h @@ -15,7 +15,7 @@ DECLARE_PER_CPU(struct ia64_cpu, cpu_devices); DECLARE_PER_CPU(int, cpu_state); #ifdef CONFIG_HOTPLUG_CPU -extern int arch_register_cpu(int num); +extern int arch_register_cpu(int num, int busy); extern void arch_unregister_cpu(int); #endif diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c index c64460b..54a6dfc 100644 --- a/arch/ia64/kernel/topology.c +++ b/arch/ia64/kernel/topology.c @@ -40,15 +40,17 @@ EXPORT_SYMBOL_GPL(arch_fix_phys_package_id); #ifdef CONFIG_HOTPLUG_CPU -int __ref arch_register_cpu(int num) +int __ref arch_register_cpu(int num, int busy) { #ifdef CONFIG_ACPI /* * If CPEI can be re-targeted or if this is not * CPEI target, then it is hotpluggable */ - if (can_cpei_retarget() || !is_cpu_cpei_target(num)) + if (can_cpei_retarget() || !is_cpu_cpei_target(num)) { sysfs_cpus[num].cpu.hotpluggable = 1; + sysfs_cpus[num].cpu.busy = busy; + } map_cpu_to_node(num, node_cpuid[num].nid); #endif return register_cpu(&sysfs_cpus[num].cpu, num); @@ -64,7 +66,7 @@ void __ref arch_unregister_cpu(int num) } EXPORT_SYMBOL(arch_unregister_cpu); #else -static int __init arch_register_cpu(int num) +static int __init arch_register_cpu(int num, int busy) { return register_cpu(&sysfs_cpus[num].cpu, num); } @@ -90,10 +92,11 @@ static int __init topology_init(void) panic("kzalloc in topology_init failed - NR_CPUS too big?"); for_each_present_cpu(i) { - if((err = arch_register_cpu(i))) - goto out; + err = arch_register_cpu(i, 0); + if (err) + break; } -out: + return err; } diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index 4564c8e..724c777 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -26,7 +26,7 @@ struct x86_cpu { }; #ifdef CONFIG_HOTPLUG_CPU -extern int arch_register_cpu(int num); +extern int arch_register_cpu(int num, int busy); extern void arch_unregister_cpu(int); #endif diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c index 76ee977..c66ef53 100644 --- a/arch/x86/kernel/topology.c +++ b/arch/x86/kernel/topology.c @@ -35,7 +35,7 @@ static DEFINE_PER_CPU(struct x86_cpu, cpu_devices); #ifdef CONFIG_HOTPLUG_CPU -int __ref arch_register_cpu(int num) +int __ref arch_register_cpu(int num, int busy) { /* * CPU0 cannot be offlined due to several @@ -46,8 +46,10 @@ int __ref arch_register_cpu(int num) * Also certain PCI quirks require not to enable hotplug control * for all CPU's. */ - if (num) + if (num) { per_cpu(cpu_devices, num).cpu.hotpluggable = 1; + per_cpu(cpu_devices, num).cpu.busy = busy; + } return register_cpu(&per_cpu(cpu_devices, num).cpu, num); } @@ -60,7 +62,7 @@ void arch_unregister_cpu(int num) EXPORT_SYMBOL(arch_unregister_cpu); #else /* CONFIG_HOTPLUG_CPU */ -static int __init arch_register_cpu(int num) +static int __init arch_register_cpu(int num, int busy) { return register_cpu(&per_cpu(cpu_devices, num).cpu, num); } @@ -76,7 +78,7 @@ static int __init topology_init(void) #endif for_each_present_cpu(i) - arch_register_cpu(i); + arch_register_cpu(i, 0); return 0; } diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 25079ca..447bd6d 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -702,7 +702,7 @@ static int acpi_processor_pre_configure(struct acpi_device *device, if (result) goto out_unlock; BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); - result = arch_register_cpu(pr->id); + result = arch_register_cpu(pr->id, 0); if (result) goto out_unmap; diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 6345294..dc6246c 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -42,6 +42,11 @@ static ssize_t __ref store_online(struct device *dev, ssize_t ret; cpu_hotplug_driver_lock(); + if (cpu->busy) { + ret = -EBUSY; + goto out; + } + switch (buf[0]) { case '0': ret = cpu_down(cpu->dev.id); @@ -56,6 +61,8 @@ static ssize_t __ref store_online(struct device *dev, default: ret = -EINVAL; } + +out: cpu_hotplug_driver_unlock(); if (ret >= 0) @@ -308,6 +315,21 @@ bool cpu_is_hotpluggable(unsigned cpu) } EXPORT_SYMBOL_GPL(cpu_is_hotpluggable); +int cpu_set_busy(unsigned int id, int busy) +{ + int old; + struct device *device = get_cpu_device(id); + struct cpu *cpu = container_of(device, struct cpu, dev); + + cpu_hotplug_driver_lock(); + old = cpu->busy; + cpu->busy = busy; + cpu_hotplug_driver_unlock(); + + return old; +} +EXPORT_SYMBOL_GPL(cpu_set_busy); + #ifdef CONFIG_GENERIC_CPU_DEVICES static DEFINE_PER_CPU(struct cpu, cpu_devices); #endif diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c index 4dcfced..95bde8a 100644 --- a/drivers/xen/cpu_hotplug.c +++ b/drivers/xen/cpu_hotplug.c @@ -9,7 +9,7 @@ static void enable_hotplug_cpu(int cpu) { if (!cpu_present(cpu)) - arch_register_cpu(cpu); + arch_register_cpu(cpu, 0); set_cpu_present(cpu, true); } diff --git a/include/linux/cpu.h b/include/linux/cpu.h index ce7a074..557501b 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -23,12 +23,14 @@ struct device; struct cpu { int node_id; /* The node which contains the CPU */ int hotpluggable; /* creates sysfs control file if hotpluggable */ + int busy; struct device dev; }; extern int register_cpu(struct cpu *cpu, int num); extern struct device *get_cpu_device(unsigned cpu); extern bool cpu_is_hotpluggable(unsigned cpu); +extern int cpu_set_busy(unsigned int cpu, int busy); extern int cpu_add_dev_attr(struct device_attribute *attr); extern void cpu_remove_dev_attr(struct device_attribute *attr);