* [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).