* [PATCH 0/3] Enhance pci_root.c to better support PCI root bus hotplug
@ 2012-03-21 16:22 Jiang Liu
2012-03-21 16:22 ` [PATCH 1/3] ACPI,PCI: Use normal list for struct acpi_pci_driver Jiang Liu
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Jiang Liu @ 2012-03-21 16:22 UTC (permalink / raw)
To: Yinghai Lu, Len Brown
Cc: Jiang Liu, Jesse Barnes, Bjorn Helgaas, Ashok Raj, linux-pci,
linux-acpi, chenkeping
This series of patches is based on Yinghai's work on PCI root bus hotplug,
which enhance the pci_root.c to better support PCI root bus hotplug.
It applies to
93c6c6b PCI: Add /sys/bus/pci/rescan_root
at
git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci-root-bus-hotplug
Jiang Liu (3):
ACPI,PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges
ACPI,PCI: protect global lists in drivers/acpi/pci_root.c
ACPI,PCI: Use normal list for struct acpi_pci_driver
drivers/acpi/pci_root.c | 111 +++++++++++++++++++++++++++--------------------
include/linux/acpi.h | 2 +-
2 files changed, 65 insertions(+), 48 deletions(-)
--
1.7.5.4
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/3] ACPI,PCI: Use normal list for struct acpi_pci_driver
2012-03-21 16:22 [PATCH 0/3] Enhance pci_root.c to better support PCI root bus hotplug Jiang Liu
@ 2012-03-21 16:22 ` Jiang Liu
2012-03-21 16:22 ` [PATCH 2/3] ACPI,PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges Jiang Liu
2012-03-21 16:22 ` [PATCH 3/3] ACPI,PCI: protect global lists in drivers/acpi/pci_root.c Jiang Liu
2 siblings, 0 replies; 7+ messages in thread
From: Jiang Liu @ 2012-03-21 16:22 UTC (permalink / raw)
To: Yinghai Lu, Len Brown
Cc: Liu Jiang, Jesse Barnes, Bjorn Helgaas, Ashok Raj, linux-pci,
linux-acpi, chenkeping
From: Liu Jiang <jiang.liu@huawei.com>
Use normal list for struct acpi_pci_driver to simplify code.
Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
---
drivers/acpi/pci_root.c | 16 +++-------------
include/linux/acpi.h | 2 +-
2 files changed, 4 insertions(+), 14 deletions(-)
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index b38e347..c2d2b7b 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -72,8 +72,8 @@ static struct acpi_driver acpi_pci_root_driver = {
};
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_pci_driver *driver)
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 acpi_pci_driver *driver)
{
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;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 3f96866..efcc6c4 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -138,7 +138,7 @@ void acpi_penalize_isa_irq(int irq, int active);
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);
};
--
1.7.5.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/3] ACPI,PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges
2012-03-21 16:22 [PATCH 0/3] Enhance pci_root.c to better support PCI root bus hotplug Jiang Liu
2012-03-21 16:22 ` [PATCH 1/3] ACPI,PCI: Use normal list for struct acpi_pci_driver Jiang Liu
@ 2012-03-21 16:22 ` Jiang Liu
2012-03-21 17:04 ` Yinghai Lu
2012-03-21 16:22 ` [PATCH 3/3] ACPI,PCI: protect global lists in drivers/acpi/pci_root.c Jiang Liu
2 siblings, 1 reply; 7+ messages in thread
From: Jiang Liu @ 2012-03-21 16:22 UTC (permalink / raw)
To: Yinghai Lu, Len Brown
Cc: Jiang Liu, Jesse Barnes, Bjorn Helgaas, Ashok Raj, linux-pci,
linux-acpi, chenkeping, Jiang Liu
From: Jiang Liu <liuj97@gmail.com>
When hot-plugging PCI root bridge, acpi_pci_drivers' add()/remove()
methods should be invoked to notify registered drivers.
Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
---
drivers/acpi/pci_root.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index c2d2b7b..ff73357 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -445,6 +445,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
acpi_status status;
int result;
struct acpi_pci_root *root;
+ struct acpi_pci_driver *driver;
acpi_handle handle;
struct acpi_device *child;
u32 flags, base_flags;
@@ -612,6 +613,10 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
if (device->wakeup.flags.run_wake)
device_set_run_wake(root->bus->bridge, true);
+ list_for_each_entry(driver, &acpi_pci_drivers, node)
+ if (driver->add)
+ driver->add(device->handle);
+
return 0;
end:
@@ -632,6 +637,11 @@ static int acpi_pci_root_start(struct acpi_device *device)
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);
/* that root bus could be removed already */
if (!pci_find_bus(root->segment, root->secondary.start)) {
--
1.7.5.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/3] ACPI,PCI: protect global lists in drivers/acpi/pci_root.c
2012-03-21 16:22 [PATCH 0/3] Enhance pci_root.c to better support PCI root bus hotplug Jiang Liu
2012-03-21 16:22 ` [PATCH 1/3] ACPI,PCI: Use normal list for struct acpi_pci_driver Jiang Liu
2012-03-21 16:22 ` [PATCH 2/3] ACPI,PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges Jiang Liu
@ 2012-03-21 16:22 ` Jiang Liu
2 siblings, 0 replies; 7+ messages in thread
From: Jiang Liu @ 2012-03-21 16:22 UTC (permalink / raw)
To: Yinghai Lu, Len Brown
Cc: Jiang Liu, Jesse Barnes, Bjorn Helgaas, Ashok Raj, linux-pci,
linux-acpi, chenkeping, Jiang Liu
From: Jiang Liu <liuj97@gmail.com>
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>
---
drivers/acpi/pci_root.c | 85 ++++++++++++++++++++++++++++-------------------
1 files changed, 51 insertions(+), 34 deletions(-)
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index ff73357..24afd66 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -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_driver = {
},
};
+/* 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_pci_driver *driver)
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(acpi_handle handle)
{
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);
@@ -460,7 +469,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
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. */
@@ -485,7 +494,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
else {
printk(KERN_ERR PREFIX "can't evaluate _BBN\n");
result = -ENODEV;
- goto end;
+ goto out_free;
}
}
@@ -507,8 +516,8 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
* 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),
@@ -527,7 +536,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
"Bus %04x:%02x not present in PCI namespace\n",
root->segment, (unsigned int)root->secondary.start);
result = -ENODEV;
- goto end;
+ goto out_del_root;
}
/*
@@ -537,7 +546,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
*/
result = acpi_pci_bind_root(device);
if (result)
- goto end;
+ goto out_del_root;
/*
* PCI Routing Table
@@ -617,11 +626,15 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
if (driver->add)
driver->add(device->handle);
+ 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;
}
@@ -639,6 +652,8 @@ 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;
+ mutex_lock(&acpi_pci_root_lock);
+
list_for_each_entry(driver, &acpi_pci_drivers, node)
if (driver->remove)
driver->remove(root->device->handle);
@@ -658,7 +673,9 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
pci_stop_and_remove_bus(root->bus);
out:
- list_del(&root->node);
+ list_del_rcu(&root->node);
+ mutex_unlock(&acpi_pci_root_lock);
+ synchronize_rcu();
kfree(root);
return 0;
--
1.7.5.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 2/3] ACPI,PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges
2012-03-21 16:22 ` [PATCH 2/3] ACPI,PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges Jiang Liu
@ 2012-03-21 17:04 ` Yinghai Lu
2012-03-22 1:12 ` Yinghai Lu
2012-03-22 3:01 ` Jiang Liu
0 siblings, 2 replies; 7+ messages in thread
From: Yinghai Lu @ 2012-03-21 17:04 UTC (permalink / raw)
To: Jiang Liu
Cc: Len Brown, Jesse Barnes, Bjorn Helgaas, Ashok Raj, linux-pci,
linux-acpi, chenkeping, Jiang Liu
On Wed, Mar 21, 2012 at 9:22 AM, Jiang Liu <liuj97@gmail.com> wrote:
> From: Jiang Liu <liuj97@gmail.com>
>
> When hot-plugging PCI root bridge, acpi_pci_drivers' add()/remove()
> methods should be invoked to notify registered drivers.
>
> Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
> ---
> drivers/acpi/pci_root.c | 10 ++++++++++
> 1 files changed, 10 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index c2d2b7b..ff73357 100644
> --- a/drivers/acpi/pci_root.c
> +++ b/drivers/acpi/pci_root.c
> @@ -445,6 +445,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
> acpi_status status;
> int result;
> struct acpi_pci_root *root;
> + struct acpi_pci_driver *driver;
> acpi_handle handle;
> struct acpi_device *child;
> u32 flags, base_flags;
> @@ -612,6 +613,10 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
> if (device->wakeup.flags.run_wake)
> device_set_run_wake(root->bus->bridge, true);
>
> + list_for_each_entry(driver, &acpi_pci_drivers, node)
> + if (driver->add)
> + driver->add(device->handle);
> +
> return 0;
if those calling is with acpi_pci_root_start() instead of acpi_pci_root_add()
Do you still need patches 3?
Yinghai
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/3] ACPI,PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges
2012-03-21 17:04 ` Yinghai Lu
@ 2012-03-22 1:12 ` Yinghai Lu
2012-03-22 3:01 ` Jiang Liu
1 sibling, 0 replies; 7+ messages in thread
From: Yinghai Lu @ 2012-03-22 1:12 UTC (permalink / raw)
To: Jiang Liu
Cc: Len Brown, Jesse Barnes, Bjorn Helgaas, Ashok Raj, linux-pci,
linux-acpi, chenkeping, Jiang Liu
On Wed, Mar 21, 2012 at 10:04 AM, Yinghai Lu <yinghai@kernel.org> wrote:
> On Wed, Mar 21, 2012 at 9:22 AM, Jiang Liu <liuj97@gmail.com> wrote:
>> From: Jiang Liu <liuj97@gmail.com>
>>
>> When hot-plugging PCI root bridge, acpi_pci_drivers' add()/remove()
>> methods should be invoked to notify registered drivers.
>>
>> Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
>> ---
>> drivers/acpi/pci_root.c | 10 ++++++++++
>> 1 files changed, 10 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
>> index c2d2b7b..ff73357 100644
>> --- a/drivers/acpi/pci_root.c
>> +++ b/drivers/acpi/pci_root.c
>> @@ -445,6 +445,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
>> acpi_status status;
>> int result;
>> struct acpi_pci_root *root;
>> + struct acpi_pci_driver *driver;
>> acpi_handle handle;
>> struct acpi_device *child;
>> u32 flags, base_flags;
>> @@ -612,6 +613,10 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
>> if (device->wakeup.flags.run_wake)
>> device_set_run_wake(root->bus->bridge, true);
>>
>> + list_for_each_entry(driver, &acpi_pci_drivers, node)
>> + if (driver->add)
>> + driver->add(device->handle);
>> +
>> return 0;
>
> if those calling is with acpi_pci_root_start() instead of acpi_pci_root_add()
>
ok, i put those three in my patcheset.
only change is moving that ->add calling to acpi_pci_root_start.
Yinghai
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/3] ACPI,PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges
2012-03-21 17:04 ` Yinghai Lu
2012-03-22 1:12 ` Yinghai Lu
@ 2012-03-22 3:01 ` Jiang Liu
1 sibling, 0 replies; 7+ messages in thread
From: Jiang Liu @ 2012-03-22 3:01 UTC (permalink / raw)
To: Yinghai Lu
Cc: Jiang Liu, Len Brown, Jesse Barnes, Bjorn Helgaas, Ashok Raj,
linux-pci, linux-acpi, chenkeping
On 2012-3-22 1:04, Yinghai Lu wrote:
> On Wed, Mar 21, 2012 at 9:22 AM, Jiang Liu<liuj97@gmail.com> wrote:
>> From: Jiang Liu<liuj97@gmail.com>
>>
>> When hot-plugging PCI root bridge, acpi_pci_drivers' add()/remove()
>> methods should be invoked to notify registered drivers.
>>
>> Signed-off-by: Jiang Liu<jiang.liu@huawei.com>
>> ---
>> drivers/acpi/pci_root.c | 10 ++++++++++
>> 1 files changed, 10 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
>> index c2d2b7b..ff73357 100644
>> --- a/drivers/acpi/pci_root.c
>> +++ b/drivers/acpi/pci_root.c
>> @@ -445,6 +445,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
>> acpi_status status;
>> int result;
>> struct acpi_pci_root *root;
>> + struct acpi_pci_driver *driver;
>> acpi_handle handle;
>> struct acpi_device *child;
>> u32 flags, base_flags;
>> @@ -612,6 +613,10 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
>> if (device->wakeup.flags.run_wake)
>> device_set_run_wake(root->bus->bridge, true);
>>
>> + list_for_each_entry(driver,&acpi_pci_drivers, node)
>> + if (driver->add)
>> + driver->add(device->handle);
>> +
>> return 0;
>
> if those calling is with acpi_pci_root_start() instead of acpi_pci_root_add()
>
> Do you still need patches 3?
I think it's still needed. If driver->add is called by
acpi_pci_root_add(), then acpi_pci_root_add() needs to
acquire the lock too.
>
> Yinghai
>
> .
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2012-03-22 3:02 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-21 16:22 [PATCH 0/3] Enhance pci_root.c to better support PCI root bus hotplug Jiang Liu
2012-03-21 16:22 ` [PATCH 1/3] ACPI,PCI: Use normal list for struct acpi_pci_driver Jiang Liu
2012-03-21 16:22 ` [PATCH 2/3] ACPI,PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges Jiang Liu
2012-03-21 17:04 ` Yinghai Lu
2012-03-22 1:12 ` Yinghai Lu
2012-03-22 3:01 ` Jiang Liu
2012-03-21 16:22 ` [PATCH 3/3] ACPI,PCI: protect global lists in drivers/acpi/pci_root.c Jiang Liu
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).