[RFC PATCH v1 15/22] PCI/eeepc: use PCI bus lock to avoid race conditions

From: Jiang Liu
Date: Tue Aug 07 2012 - 12:20:45 EST


This patch uses PCI bus lock mechanism to avoid race conditions when doing
PCI device hotplug through eeepc driver. It also fixes a PCI device reference
count leakage issue because acpi_get_pci_dev() holds a reference to the
device returned.

Signed-off-by: Jiang Liu <liuj97@xxxxxxxxx>
---
drivers/platform/x86/eeepc-laptop.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index dab91b4..25c4176 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -606,16 +606,16 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
goto out_unlock;
}

- bus = port->subordinate;
+ bus = pci_lock_subordinate(port, PCI_BUS_STATE_WORKING);

if (!bus) {
pr_warn("Unable to find PCI bus 1?\n");
- goto out_unlock;
+ goto out_put_dev;
}

if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
pr_err("Unable to read PCI config space?\n");
- goto out_unlock;
+ goto out_unlock_bus;
}

absent = (l == 0xffffffff);
@@ -627,7 +627,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
absent ? "absent" : "present");
pr_warn("skipped wireless hotplug as probably "
"inappropriate for this model\n");
- goto out_unlock;
+ goto out_unlock_bus;
}

if (!blocked) {
@@ -635,7 +635,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
if (dev) {
/* Device already present */
pci_dev_put(dev);
- goto out_unlock;
+ goto out_unlock_bus;
}
dev = pci_scan_single_device(bus, 0);
if (dev) {
@@ -650,6 +650,11 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
pci_dev_put(dev);
}
}
+
+out_unlock_bus:
+ pci_bus_unlock(bus);
+out_put_dev:
+ pci_dev_put(port);
}

out_unlock:
@@ -757,7 +762,7 @@ static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)
{
int ret = -ENOMEM;
- struct pci_bus *bus = pci_find_bus(0, 1);
+ struct pci_bus *bus = pci_get_bus(0, 1);

if (!bus) {
pr_err("Unable to find wifi PCI bus\n");
@@ -785,6 +790,8 @@ static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)
goto error_register;
}

+ pci_bus_put(bus);
+
return 0;

error_register:
@@ -793,6 +800,7 @@ error_info:
kfree(eeepc->hotplug_slot);
eeepc->hotplug_slot = NULL;
error_slot:
+ pci_bus_put(bus);
return ret;
}

--
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/