From patchwork Sun Nov 4 15:23:58 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Liu X-Patchwork-Id: 1694571 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 6C2F83FD2B for ; Sun, 4 Nov 2012 15:26:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755484Ab2KDP02 (ORCPT ); Sun, 4 Nov 2012 10:26:28 -0500 Received: from mail-pb0-f46.google.com ([209.85.160.46]:42549 "EHLO mail-pb0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755012Ab2KDPYq (ORCPT ); Sun, 4 Nov 2012 10:24:46 -0500 Received: by mail-pb0-f46.google.com with SMTP id rr4so3377823pbb.19 for ; Sun, 04 Nov 2012 07:24:46 -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=ZNmBVqc6Z6BdK7BCATyAnldZZNeJSMOoo/mfgZCqrj8=; b=qeAmzFHcIBt33yze1Chv1Ajijg9H1fHha2GBeD+wOKeIf/c1zZ16RJQoZ2BXBb5jPT Cs1ed9IMFFtQ5KtbVVMHhUYX4aAd0gYSgECBkGGSmZD0UIXJe6x832iVvkKga0/NYu+s DBoR0a22kC/XWqBJnIs7+QnCrGPUmPDIs3k9kJA78WaoBvQs9JVdkp5g6uL5iqY56tmG NDamxUACzimRLsVsNaJ7DLoFLgV90iC46E4+HxRbhvycjFBp39mlSiRCyxtxmFID5U4u IRXRu8LpFa7u52+Fr13qx6LG9XfzMmgFy7v7K+bo8hOOsbt8fF464y1FyxG4aNYj+mcn V0DA== Received: by 10.68.228.36 with SMTP id sf4mr22970860pbc.20.1352042686174; Sun, 04 Nov 2012 07:24:46 -0800 (PST) Received: from localhost.localdomain ([120.196.98.117]) by mx.google.com with ESMTPS id nd6sm9020763pbc.68.2012.11.04.07.24.40 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 04 Nov 2012 07:24:45 -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 5/9] CPU: introduce busy flag to temporarily disable CPU online sysfs interface Date: Sun, 4 Nov 2012 23:23:58 +0800 Message-Id: <1352042642-7306-6-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-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 | 10 ++++++---- arch/x86/include/asm/cpu.h | 2 +- arch/x86/kernel/topology.c | 10 ++++++---- drivers/acpi/processor_driver.c | 3 ++- drivers/base/cpu.c | 22 ++++++++++++++++++++++ drivers/xen/cpu_hotplug.c | 2 +- include/linux/cpu.h | 2 ++ 8 files changed, 41 insertions(+), 12 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..11d47a4 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,7 +92,7 @@ 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))) + if((err = arch_register_cpu(i, 0))) goto out; } out: 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 b8c3684..53e364d 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -702,7 +702,8 @@ static int acpi_processor_pre_configure(struct acpi_device *device, if (result) return result; 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) { acpi_unmap_lsapic(pr->id); pr->id = -1; 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);