linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] acpi, pci: hostbridge hotplug support
@ 2012-07-04  8:03 Taku Izumi
  2012-07-04  8:06 ` [PATCH 1/7] x86, PCI: Fix non acpi path pci_sysdata leaking with release_fn Taku Izumi
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Taku Izumi @ 2012-07-04  8:03 UTC (permalink / raw)
  To: linux-pci, Bjorn Helgaas; +Cc: Kenji Kaneshige, Yinghai Lu, Jiang Liu


 Hi all,

 I'd like to merge hostbridge hotplug feature.
 I looked at Yinghai's branch and found that this branch contains 
 many work and can be split into some parts. 
 I believe it is good to merge step by step.

 My idea is splitting into the following 4 parts:
   1. basic hostbirdge hotplug work
   2. acpiphp work
   3. /sysfs interface work (logical hotplug?)
   4. cleanup

 This patchset is 1st step based on the following Yinghai's branch:

git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git
for-pci-root-bus-hotplug

  * [PATCH 1/7] x86, PCI: Fix non acpi path pci_sysdata leaking with release_fn
  * [PATCH 2/7] PCI: Correctly clean up pci root buses in function pci_remove_bus()
  * [PATCH 3/7] ACPI, PCI: Use normal list for struct acpi_pci_driver
  * [PATCH 4/7] ACPI, PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges
  * [PATCH 5/7] ACPI, PCI: Protect global lists in drivers/acpi/pci_root.c
  * [PATCH 6/7] ACPI, PCI: add hostbridge removal function
  * [PATCH 7/7] ACPI, PCI: add resoruce-assign code for devices under hot-added hostbridge

-- 
Best regards,
Taku Izumi <izumi.taku@jp.fujitsu.com>


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/7] x86, PCI: Fix non acpi path pci_sysdata leaking with release_fn
  2012-07-04  8:03 [PATCH 0/7] acpi, pci: hostbridge hotplug support Taku Izumi
@ 2012-07-04  8:06 ` Taku Izumi
  2012-07-04  8:07 ` [PATCH 2/7] PCI: Correctly clean up pci root buses in function pci_remove_bus() Taku Izumi
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Taku Izumi @ 2012-07-04  8:06 UTC (permalink / raw)
  To: Taku Izumi
  Cc: linux-pci, Bjorn Helgaas, Kenji Kaneshige, Yinghai Lu, Jiang Liu

From: Yinghai Lu <yinghai@kernel.org>

    x86, PCI: Fix non acpi path pci_sysdata leaking with release_fn
    
    Non acpi path, or root is not probed from acpi, during root bus removal
    will get warning about leaking from pci_scan_bus_on_node.
    
    Fix it with setting pci_host_bridge release function.
    
    Signed-off-by: Yinghai Lu <yinghai@kernel.org>

---
 arch/x86/pci/common.c |   17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

Index: linux/arch/x86/pci/common.c
===================================================================
--- linux.orig/arch/x86/pci/common.c	2012-07-04 09:54:52.159485283 +0900
+++ linux/arch/x86/pci/common.c	2012-07-04 09:54:59.788389907 +0900
@@ -634,17 +634,19 @@ int pci_ext_cfg_avail(struct pci_dev *de
 		return 0;
 }
 
+static void release_pci_sysdata(struct pci_host_bridge *bridge)
+{
+	struct pci_sysdata *sd = bridge->release_data;
+
+	kfree(sd);
+}
+
 struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node)
 {
 	LIST_HEAD(resources);
 	struct pci_bus *bus = NULL;
 	struct pci_sysdata *sd;
 
-	/*
-	 * Allocate per-root-bus (not per bus) arch-specific data.
-	 * TODO: leak; this memory is never freed.
-	 * It's arguable whether it's worth the trouble to care.
-	 */
 	sd = kzalloc(sizeof(*sd), GFP_KERNEL);
 	if (!sd) {
 		printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busno);
@@ -654,7 +656,10 @@ struct pci_bus * __devinit pci_scan_bus_
 	x86_pci_root_bus_resources(busno, &resources);
 	printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busno);
 	bus = pci_scan_root_bus(NULL, busno, ops, sd, &resources);
-	if (!bus) {
+	if (bus)
+		pci_set_host_bridge_release(to_pci_host_bridge(bus->bridge),
+					release_pci_sysdata, sd);
+	else {
 		pci_free_resource_list(&resources);
 		kfree(sd);
 	}


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 2/7] PCI: Correctly clean up pci root buses in function pci_remove_bus()
  2012-07-04  8:03 [PATCH 0/7] acpi, pci: hostbridge hotplug support Taku Izumi
  2012-07-04  8:06 ` [PATCH 1/7] x86, PCI: Fix non acpi path pci_sysdata leaking with release_fn Taku Izumi
@ 2012-07-04  8:07 ` Taku Izumi
  2012-07-04  8:08 ` [PATCH 3/7] ACPI, PCI: Use normal list for struct acpi_pci_driver Taku Izumi
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Taku Izumi @ 2012-07-04  8:07 UTC (permalink / raw)
  To: Taku Izumi
  Cc: linux-pci, Bjorn Helgaas, Kenji Kaneshige, Yinghai Lu, Jiang Liu

From: Jiang Liu <jiang.liu@huawei.com>

    Correctly clean up pci root buses in function pci_remove_bus()
    
    The function pci_create_root_bus() allocates the pci bus structure,
    registers the bus device and creates the legacy files for a pci root
    bus, but returns without setting the is_added flag. The is_added flag
    for a pci root bus will be set by function pci_scan_child_bus().
    If a pci root bus is destroyed before calling pci_scan_child_bus(),
    the is_added flag will not be set.  So teach function pci_remove_bus()
    to detect such a case and correctly clean up pci root buses.
    
    Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
    Signed-off-by: Yinghai Lu <yinghai@kernel.org>

Index: linux/drivers/pci/remove.c
===================================================================
--- linux.orig/drivers/pci/remove.c	2012-07-04 09:54:52.126485695 +0900
+++ linux/drivers/pci/remove.c	2012-07-04 09:55:33.695965952 +0900
@@ -70,11 +70,10 @@ void pci_remove_bus(struct pci_bus *pci_
 	list_del(&pci_bus->node);
 	pci_bus_release_busn_res(pci_bus);
 	up_write(&pci_bus_sem);
-	if (!pci_bus->is_added)
-		return;
-
-	pci_remove_legacy_files(pci_bus);
-	device_unregister(&pci_bus->dev);
+	if (pci_bus->is_added || pci_is_root_bus(pci_bus)) {
+		pci_remove_legacy_files(pci_bus);
+		device_unregister(&pci_bus->dev);
+	}
 }
 EXPORT_SYMBOL(pci_remove_bus);
 


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 3/7] ACPI, PCI: Use normal list for struct acpi_pci_driver
  2012-07-04  8:03 [PATCH 0/7] acpi, pci: hostbridge hotplug support Taku Izumi
  2012-07-04  8:06 ` [PATCH 1/7] x86, PCI: Fix non acpi path pci_sysdata leaking with release_fn Taku Izumi
  2012-07-04  8:07 ` [PATCH 2/7] PCI: Correctly clean up pci root buses in function pci_remove_bus() Taku Izumi
@ 2012-07-04  8:08 ` Taku Izumi
  2012-07-04  8:08 ` [PATCH 4/7] ACPI, PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges Taku Izumi
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Taku Izumi @ 2012-07-04  8:08 UTC (permalink / raw)
  To: Taku Izumi
  Cc: linux-pci, Bjorn Helgaas, Kenji Kaneshige, Yinghai Lu, Jiang Liu

From: Jiang Liu <jiang.liu@huawei.com>

    ACPI, PCI: Use normal list for struct acpi_pci_driver
    
    Use normal list for struct acpi_pci_driver to simplify code.
    
    Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
    Signed-off-by: Yinghai Lu <yinghai@kernel.org>

Index: linux/drivers/acpi/pci_root.c
===================================================================
--- linux.orig/drivers/acpi/pci_root.c	2012-07-04 09:54:52.061486507 +0900
+++ linux/drivers/acpi/pci_root.c	2012-07-04 09:55:45.697815965 +0900
@@ -72,8 +72,8 @@ static struct acpi_driver acpi_pci_root_
 };
 
 static LIST_HEAD(acpi_pci_roots);
+static LIST_HEAD(acpi_pci_drivers);
 
-static struct acpi_pci_driver *sub_driver;
 static DEFINE_MUTEX(osc_lock);
 
 int acpi_pci_register_driver(struct acpi_pci_driver *driver)
@@ -81,10 +81,7 @@ int acpi_pci_register_driver(struct acpi
 	int n = 0;
 	struct acpi_pci_root *root;
 
-	struct acpi_pci_driver **pptr = &sub_driver;
-	while (*pptr)
-		pptr = &(*pptr)->next;
-	*pptr = driver;
+	list_add_tail(&driver->node, &acpi_pci_drivers);
 
 	if (!driver->add)
 		return 0;
@@ -103,14 +100,7 @@ void acpi_pci_unregister_driver(struct a
 {
 	struct acpi_pci_root *root;
 
-	struct acpi_pci_driver **pptr = &sub_driver;
-	while (*pptr) {
-		if (*pptr == driver)
-			break;
-		pptr = &(*pptr)->next;
-	}
-	BUG_ON(!*pptr);
-	*pptr = (*pptr)->next;
+	list_del(&driver->node);
 
 	if (!driver->remove)
 		return;
Index: linux/include/linux/acpi.h
===================================================================
--- linux.orig/include/linux/acpi.h	2012-07-04 09:54:52.061486507 +0900
+++ linux/include/linux/acpi.h	2012-07-04 09:55:45.697815965 +0900
@@ -138,7 +138,7 @@ void acpi_penalize_isa_irq(int irq, int 
 void acpi_pci_irq_disable (struct pci_dev *dev);
 
 struct acpi_pci_driver {
-	struct acpi_pci_driver *next;
+	struct list_head node;
 	int (*add)(acpi_handle handle);
 	void (*remove)(acpi_handle handle);
 };


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 4/7] ACPI, PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges
  2012-07-04  8:03 [PATCH 0/7] acpi, pci: hostbridge hotplug support Taku Izumi
                   ` (2 preceding siblings ...)
  2012-07-04  8:08 ` [PATCH 3/7] ACPI, PCI: Use normal list for struct acpi_pci_driver Taku Izumi
@ 2012-07-04  8:08 ` Taku Izumi
  2012-07-04  8:09 ` [PATCH 5/7] ACPI, PCI: Protect global lists in drivers/acpi/pci_root.c Taku Izumi
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Taku Izumi @ 2012-07-04  8:08 UTC (permalink / raw)
  To: Taku Izumi
  Cc: linux-pci, Bjorn Helgaas, Kenji Kaneshige, Yinghai Lu, Jiang Liu

From: Jiang Liu <jiang.liu@huawei.com>

    ACPI, PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges
    
    When hot-plugging PCI root bridge, acpi_pci_drivers' add()/remove()
    methods should be invoked to notify registered drivers.
    
    -v2: Move add calling to acpi_pci_root_start by Yinghai
    
    Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
    Signed-off-by: Yinghai Lu <yinghai@kernel.org>

---
 drivers/acpi/pci_root.c |   11 +++++++++++
 1 file changed, 11 insertions(+)

Index: linux/drivers/acpi/pci_root.c
===================================================================
--- linux.orig/drivers/acpi/pci_root.c	2012-07-04 09:55:45.697815965 +0900
+++ linux/drivers/acpi/pci_root.c	2012-07-04 09:55:49.169772504 +0900
@@ -626,14 +626,25 @@ end:
 static int acpi_pci_root_start(struct acpi_device *device)
 {
 	struct acpi_pci_root *root = acpi_driver_data(device);
+	struct acpi_pci_driver *driver;
+
+	list_for_each_entry(driver, &acpi_pci_drivers, node)
+		if (driver->add)
+			driver->add(device->handle);
 
 	pci_bus_add_devices(root->bus);
+
 	return 0;
 }
 
 static int acpi_pci_root_remove(struct acpi_device *device, int type)
 {
 	struct acpi_pci_root *root = acpi_driver_data(device);
+	struct acpi_pci_driver *driver;
+
+	list_for_each_entry(driver, &acpi_pci_drivers, node)
+		if (driver->remove)
+			driver->remove(root->device->handle);
 
 	device_set_run_wake(root->bus->bridge, false);
 	pci_acpi_remove_bus_pm_notifier(device);


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 5/7] ACPI, PCI: Protect global lists in drivers/acpi/pci_root.c
  2012-07-04  8:03 [PATCH 0/7] acpi, pci: hostbridge hotplug support Taku Izumi
                   ` (3 preceding siblings ...)
  2012-07-04  8:08 ` [PATCH 4/7] ACPI, PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges Taku Izumi
@ 2012-07-04  8:09 ` Taku Izumi
  2012-07-04  8:10 ` [PATCH 6/7] ACPI, PCI: add hostbridge removal function Taku Izumi
  2012-07-04  8:11 ` [PATCH 7/7] ACPI, PCI: add resoruce-assign code for devices under hot-added hostbridge Taku Izumi
  6 siblings, 0 replies; 8+ messages in thread
From: Taku Izumi @ 2012-07-04  8:09 UTC (permalink / raw)
  To: Taku Izumi
  Cc: linux-pci, Bjorn Helgaas, Kenji Kaneshige, Yinghai Lu, Jiang Liu

From: Jiang Liu <jiang.liu@huawei.com>

    ACPI, PCI: Protect global lists in drivers/acpi/pci_root.c
    
    There are two global lists inf file drivers/acpi/pci_root.c.
    One is for registered acpi_pci_drivers, the other is for
    enumerated ACPI PCI root bridge objects. These two global
    lists may change dynamically when registering/deregistering
    acpi_pci_drivers or adding/removing ACPI PCI root bridge
    objects. So protect them by mutex lock and RCU list.
    
    Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
    Signed-off-by: Yinghai Lu <yinghai@kernel.org>
    [izumi.taku@jp.fujitsu.com: a bit change at acpi_pci_root_remove()]
    Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>

---
 drivers/acpi/pci_root.c |   86 +++++++++++++++++++++++++++++-------------------
 1 file changed, 53 insertions(+), 33 deletions(-)

Index: linux/drivers/acpi/pci_root.c
===================================================================
--- linux.orig/drivers/acpi/pci_root.c	2012-07-04 09:55:49.169772504 +0900
+++ linux/drivers/acpi/pci_root.c	2012-07-04 09:55:54.435706670 +0900
@@ -27,7 +27,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/rculist.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/pci.h>
@@ -71,6 +72,8 @@ static struct acpi_driver acpi_pci_root_
 		},
 };
 
+/* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */
+static DEFINE_MUTEX(acpi_pci_root_lock);
 static LIST_HEAD(acpi_pci_roots);
 static LIST_HEAD(acpi_pci_drivers);
 
@@ -81,47 +84,48 @@ int acpi_pci_register_driver(struct acpi
 	int n = 0;
 	struct acpi_pci_root *root;
 
+	mutex_lock(&acpi_pci_root_lock);
 	list_add_tail(&driver->node, &acpi_pci_drivers);
-
-	if (!driver->add)
-		return 0;
-
-	list_for_each_entry(root, &acpi_pci_roots, node) {
-		driver->add(root->device->handle);
-		n++;
-	}
+	if (driver->add)
+		list_for_each_entry_rcu(root, &acpi_pci_roots, node) {
+			driver->add(root->device->handle);
+			n++;
+		}
+	mutex_unlock(&acpi_pci_root_lock);
 
 	return n;
 }
-
 EXPORT_SYMBOL(acpi_pci_register_driver);
 
 void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
 {
 	struct acpi_pci_root *root;
 
+	mutex_lock(&acpi_pci_root_lock);
 	list_del(&driver->node);
-
-	if (!driver->remove)
-		return;
-
-	list_for_each_entry(root, &acpi_pci_roots, node)
-		driver->remove(root->device->handle);
+	if (driver->remove)
+		list_for_each_entry_rcu(root, &acpi_pci_roots, node)
+			driver->remove(root->device->handle);
+	mutex_unlock(&acpi_pci_root_lock);
 }
-
 EXPORT_SYMBOL(acpi_pci_unregister_driver);
 
 acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus)
 {
 	struct acpi_pci_root *root;
+	struct acpi_handle *handle = NULL;
 	
-	list_for_each_entry(root, &acpi_pci_roots, node)
+	rcu_read_lock();
+	list_for_each_entry_rcu(root, &acpi_pci_roots, node)
 		if ((root->segment == (u16) seg) &&
-		    (root->secondary.start == (u16) bus))
-			return root->device->handle;
-	return NULL;		
-}
+		    (root->secondary.start == (u16) bus)) {
+			handle = root->device->handle;
+			break;
+		}
+	rcu_read_unlock();
 
+	return handle;
+}
 EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle);
 
 /**
@@ -268,10 +272,15 @@ struct acpi_pci_root *acpi_pci_find_root
 {
 	struct acpi_pci_root *root;
 
-	list_for_each_entry(root, &acpi_pci_roots, node) {
-		if (root->device->handle == handle)
+	rcu_read_lock();
+	list_for_each_entry_rcu(root, &acpi_pci_roots, node) {
+		if (root->device->handle == handle) {
+			rcu_read_unlock();
 			return root;
+		}
 	}
+	rcu_read_unlock();
+
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(acpi_pci_find_root);
@@ -459,7 +468,7 @@ static int __devinit acpi_pci_root_add(s
 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
 		printk(KERN_ERR PREFIX "can't evaluate _SEG\n");
 		result = -ENODEV;
-		goto end;
+		goto out_free;
 	}
 
 	/* Check _CRS first, then _BBN.  If no _BBN, default to zero. */
@@ -484,7 +493,7 @@ static int __devinit acpi_pci_root_add(s
 		else {
 			printk(KERN_ERR PREFIX "can't evaluate _BBN\n");
 			result = -ENODEV;
-			goto end;
+			goto out_free;
 		}
 	}
 
@@ -508,8 +517,8 @@ static int __devinit acpi_pci_root_add(s
 	 * TBD: Need PCI interface for enumeration/configuration of roots.
 	 */
 
-	/* TBD: Locking */
-	list_add_tail(&root->node, &acpi_pci_roots);
+	mutex_lock(&acpi_pci_root_lock);
+	list_add_tail_rcu(&root->node, &acpi_pci_roots);
 
 	printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
 	       acpi_device_name(device), acpi_device_bid(device),
@@ -528,7 +537,7 @@ static int __devinit acpi_pci_root_add(s
 			    "Bus %04x:%02x not present in PCI namespace\n",
 			    root->segment, (unsigned int)root->secondary.start);
 		result = -ENODEV;
-		goto end;
+		goto out_del_root;
 	}
 
 	/*
@@ -538,7 +547,7 @@ static int __devinit acpi_pci_root_add(s
 	 */
 	result = acpi_pci_bind_root(device);
 	if (result)
-		goto end;
+		goto out_del_root;
 
 	/*
 	 * PCI Routing Table
@@ -614,11 +623,15 @@ static int __devinit acpi_pci_root_add(s
 	if (device->wakeup.flags.run_wake)
 		device_set_run_wake(root->bus->bridge, true);
 
+	mutex_unlock(&acpi_pci_root_lock);
+
 	return 0;
 
-end:
-	if (!list_empty(&root->node))
-		list_del(&root->node);
+out_del_root:
+	list_del_rcu(&root->node);
+	mutex_unlock(&acpi_pci_root_lock);
+	synchronize_rcu();
+out_free:
 	kfree(root);
 	return result;
 }
@@ -628,11 +641,13 @@ static int acpi_pci_root_start(struct ac
 	struct acpi_pci_root *root = acpi_driver_data(device);
 	struct acpi_pci_driver *driver;
 
+	mutex_lock(&acpi_pci_root_lock);
 	list_for_each_entry(driver, &acpi_pci_drivers, node)
 		if (driver->add)
 			driver->add(device->handle);
 
 	pci_bus_add_devices(root->bus);
+	mutex_unlock(&acpi_pci_root_lock);
 
 	return 0;
 }
@@ -642,6 +657,8 @@ static int acpi_pci_root_remove(struct a
 	struct acpi_pci_root *root = acpi_driver_data(device);
 	struct acpi_pci_driver *driver;
 
+	mutex_lock(&acpi_pci_root_lock);
+
 	list_for_each_entry(driver, &acpi_pci_drivers, node)
 		if (driver->remove)
 			driver->remove(root->device->handle);
@@ -649,6 +666,9 @@ static int acpi_pci_root_remove(struct a
 	device_set_run_wake(root->bus->bridge, false);
 	pci_acpi_remove_bus_pm_notifier(device);
 
+	list_del_rcu(&root->node);
+	mutex_unlock(&acpi_pci_root_lock);
+	synchronize_rcu();
 	kfree(root);
 	return 0;
 }


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 6/7] ACPI, PCI: add hostbridge removal function
  2012-07-04  8:03 [PATCH 0/7] acpi, pci: hostbridge hotplug support Taku Izumi
                   ` (4 preceding siblings ...)
  2012-07-04  8:09 ` [PATCH 5/7] ACPI, PCI: Protect global lists in drivers/acpi/pci_root.c Taku Izumi
@ 2012-07-04  8:10 ` Taku Izumi
  2012-07-04  8:11 ` [PATCH 7/7] ACPI, PCI: add resoruce-assign code for devices under hot-added hostbridge Taku Izumi
  6 siblings, 0 replies; 8+ messages in thread
From: Taku Izumi @ 2012-07-04  8:10 UTC (permalink / raw)
  To: Taku Izumi
  Cc: linux-pci, Bjorn Helgaas, Kenji Kaneshige, Yinghai Lu, Jiang Liu


Currently there's no PCI-related clean-up code
in acpi_pci_root_remove() function.
This patch introduces function for hostbridge removal.

Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
---
 drivers/acpi/pci_bind.c     |    7 +++++++
 drivers/acpi/pci_root.c     |    8 ++++++++
 drivers/pci/remove.c        |   18 +++++++++++++++++-
 include/acpi/acpi_drivers.h |    1 +
 include/linux/pci.h         |    2 ++
 5 files changed, 35 insertions(+), 1 deletion(-)

Index: linux/drivers/pci/remove.c
===================================================================
--- linux.orig/drivers/pci/remove.c	2012-07-04 09:55:33.695965952 +0900
+++ linux/drivers/pci/remove.c	2012-07-04 09:55:57.374674896 +0900
@@ -143,7 +143,7 @@ void pci_stop_and_remove_behind_bridge(s
 	__pci_remove_behind_bridge(dev);
 }
 
-static void pci_stop_bus_devices(struct pci_bus *bus)
+void pci_stop_bus_devices(struct pci_bus *bus)
 {
 	struct list_head *l, *n;
 
@@ -179,4 +179,20 @@ void pci_stop_bus_device(struct pci_dev 
 
 EXPORT_SYMBOL(pci_stop_and_remove_bus_device);
 EXPORT_SYMBOL(pci_stop_and_remove_behind_bridge);
+EXPORT_SYMBOL(pci_stop_bus_devices);
 EXPORT_SYMBOL_GPL(pci_stop_bus_device);
+
+void pci_remove_host_bridge(struct pci_host_bridge *bridge)
+{
+	struct list_head *l, *n;
+	struct pci_bus *root = bridge->bus;
+
+	list_for_each_safe(l, n, &root->devices)
+		__pci_remove_bus_device(pci_dev_b(l));
+
+	pci_remove_bus(root);
+
+	device_unregister(&bridge->dev);
+}
+EXPORT_SYMBOL(pci_remove_host_bridge);
+
Index: linux/drivers/acpi/pci_root.c
===================================================================
--- linux.orig/drivers/acpi/pci_root.c	2012-07-04 09:55:54.435706670 +0900
+++ linux/drivers/acpi/pci_root.c	2012-07-04 09:55:57.375674818 +0900
@@ -656,9 +656,12 @@ static int acpi_pci_root_remove(struct a
 {
 	struct acpi_pci_root *root = acpi_driver_data(device);
 	struct acpi_pci_driver *driver;
+	struct pci_host_bridge *bridge = to_pci_host_bridge(root->bus->bridge);
 
 	mutex_lock(&acpi_pci_root_lock);
 
+	pci_stop_bus_devices(root->bus);
+
 	list_for_each_entry(driver, &acpi_pci_drivers, node)
 		if (driver->remove)
 			driver->remove(root->device->handle);
@@ -666,6 +669,11 @@ static int acpi_pci_root_remove(struct a
 	device_set_run_wake(root->bus->bridge, false);
 	pci_acpi_remove_bus_pm_notifier(device);
 
+	acpi_pci_irq_del_prt(root->bus);
+	acpi_pci_unbind_root(device);
+
+	pci_remove_host_bridge(bridge);
+
 	list_del_rcu(&root->node);
 	mutex_unlock(&acpi_pci_root_lock);
 	synchronize_rcu();
Index: linux/include/linux/pci.h
===================================================================
--- linux.orig/include/linux/pci.h	2012-07-04 09:54:51.863488983 +0900
+++ linux/include/linux/pci.h	2012-07-04 09:55:57.380674441 +0900
@@ -734,7 +734,9 @@ extern void pci_dev_put(struct pci_dev *
 extern void pci_remove_bus(struct pci_bus *b);
 extern void __pci_remove_bus_device(struct pci_dev *dev);
 extern void pci_stop_and_remove_bus_device(struct pci_dev *dev);
+extern void pci_stop_bus_devices(struct pci_bus *bus);
 extern void pci_stop_bus_device(struct pci_dev *dev);
+extern void pci_remove_host_bridge(struct pci_host_bridge *bridge);
 void pci_setup_cardbus(struct pci_bus *bus);
 extern void pci_sort_breadthfirst(void);
 #define dev_is_pci(d) ((d)->bus == &pci_bus_type)
Index: linux/drivers/acpi/pci_bind.c
===================================================================
--- linux.orig/drivers/acpi/pci_bind.c	2012-07-04 09:54:51.863488983 +0900
+++ linux/drivers/acpi/pci_bind.c	2012-07-04 09:55:57.382674297 +0900
@@ -118,3 +118,10 @@ int acpi_pci_bind_root(struct acpi_devic
 
 	return 0;
 }
+
+void  acpi_pci_unbind_root(struct acpi_device *device)
+{
+	device->ops.bind = NULL;
+	device->ops.unbind = NULL;
+}
+
Index: linux/include/acpi/acpi_drivers.h
===================================================================
--- linux.orig/include/acpi/acpi_drivers.h	2012-07-04 09:54:51.863488983 +0900
+++ linux/include/acpi/acpi_drivers.h	2012-07-04 09:55:57.386674021 +0900
@@ -101,6 +101,7 @@ struct pci_bus;
 
 struct pci_dev *acpi_get_pci_dev(acpi_handle);
 int acpi_pci_bind_root(struct acpi_device *device);
+void acpi_pci_unbind_root(struct acpi_device *device);
 
 /* Arch-defined function to add a bus to the system */
 


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 7/7] ACPI, PCI: add resoruce-assign code for devices under hot-added hostbridge
  2012-07-04  8:03 [PATCH 0/7] acpi, pci: hostbridge hotplug support Taku Izumi
                   ` (5 preceding siblings ...)
  2012-07-04  8:10 ` [PATCH 6/7] ACPI, PCI: add hostbridge removal function Taku Izumi
@ 2012-07-04  8:11 ` Taku Izumi
  6 siblings, 0 replies; 8+ messages in thread
From: Taku Izumi @ 2012-07-04  8:11 UTC (permalink / raw)
  To: Taku Izumi
  Cc: linux-pci, Bjorn Helgaas, Kenji Kaneshige, Yinghai Lu, Jiang Liu


Devices under hot-added hostbridge have no chance to assign resources
and to configure them, so this patch adds such code for hot-added 
hostbridges at acpi_pci_root_start().

Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
---
 drivers/acpi/pci_root.c |   18 ++++++++++++++++++
 include/acpi/acpi_bus.h |    1 +
 2 files changed, 19 insertions(+)

Index: linux/drivers/acpi/pci_root.c
===================================================================
--- linux.orig/drivers/acpi/pci_root.c	2012-07-04 09:55:57.375674818 +0900
+++ linux/drivers/acpi/pci_root.c	2012-07-04 09:56:00.771627515 +0900
@@ -39,6 +39,7 @@
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/apei.h>
+#include <linux/pci_hotplug.h>
 
 #define PREFIX "ACPI: "
 
@@ -462,6 +463,10 @@ static int __devinit acpi_pci_root_add(s
 	if (!root)
 		return -ENOMEM;
 
+	if (system_state != SYSTEM_BOOTING) {
+		root->hot_added = true;
+	}
+
 	segment = 0;
 	status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL,
 				       &segment);
@@ -640,12 +645,25 @@ static int acpi_pci_root_start(struct ac
 {
 	struct acpi_pci_root *root = acpi_driver_data(device);
 	struct acpi_pci_driver *driver;
+	struct pci_dev *pdev;
 
 	mutex_lock(&acpi_pci_root_lock);
 	list_for_each_entry(driver, &acpi_pci_drivers, node)
 		if (driver->add)
 			driver->add(device->handle);
 
+	/*
+ 	 * Devices under hot-added hostbridge have no chance to assign
+ 	 * resources and to configure them, so do that here
+ 	 */
+	if (root->hot_added) {
+		pci_bus_size_bridges(root->bus);
+		pci_bus_assign_resources(root->bus);
+		list_for_each_entry(pdev, &root->bus->devices, bus_list)
+			pci_configure_slot(pdev);
+		pci_enable_bridges(root->bus);
+	}
+
 	pci_bus_add_devices(root->bus);
 	mutex_unlock(&acpi_pci_root_lock);
 
Index: linux/include/acpi/acpi_bus.h
===================================================================
--- linux.orig/include/acpi/acpi_bus.h	2012-07-04 09:54:51.754490344 +0900
+++ linux/include/acpi/acpi_bus.h	2012-07-04 09:56:00.772627502 +0900
@@ -402,6 +402,7 @@ struct acpi_pci_root {
 	u32 osc_support_set;	/* _OSC state of support bits */
 	u32 osc_control_set;	/* _OSC state of control bits */
 	phys_addr_t mcfg_addr;
+	bool hot_added;
 };
 
 /* helper */


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2012-07-04  8:11 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-04  8:03 [PATCH 0/7] acpi, pci: hostbridge hotplug support Taku Izumi
2012-07-04  8:06 ` [PATCH 1/7] x86, PCI: Fix non acpi path pci_sysdata leaking with release_fn Taku Izumi
2012-07-04  8:07 ` [PATCH 2/7] PCI: Correctly clean up pci root buses in function pci_remove_bus() Taku Izumi
2012-07-04  8:08 ` [PATCH 3/7] ACPI, PCI: Use normal list for struct acpi_pci_driver Taku Izumi
2012-07-04  8:08 ` [PATCH 4/7] ACPI, PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges Taku Izumi
2012-07-04  8:09 ` [PATCH 5/7] ACPI, PCI: Protect global lists in drivers/acpi/pci_root.c Taku Izumi
2012-07-04  8:10 ` [PATCH 6/7] ACPI, PCI: add hostbridge removal function Taku Izumi
2012-07-04  8:11 ` [PATCH 7/7] ACPI, PCI: add resoruce-assign code for devices under hot-added hostbridge Taku Izumi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).