diff options
author | Alex Chiang <achiang@hp.com> | 2009-03-20 16:56:31 -0400 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-03-20 17:57:58 -0400 |
commit | 705b1aaa823e800490f157cd9366ad8cff385f5f (patch) | |
tree | 634ea8ba227a305074938f49c110fea8e68e8bb3 /drivers/pci | |
parent | 3ed4fd96b3188406ac5357d9290bcffa08c65cf6 (diff) |
PCI: Introduce /sys/bus/pci/rescan
This interface allows the user to force a rescan of all PCI buses
in system, and rediscover devices that have been removed earlier.
pci_bus_attrs implementation from Trent Piepho.
Thanks to Vegard Nossum for discovering locking issues with the
sysfs interface.
Cc: Trent Piepho <xyzzy@speakeasy.org>
Signed-off-by: Alex Chiang <achiang@hp.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/pci-driver.c | 1 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 26 | ||||
-rw-r--r-- | drivers/pci/pci.h | 6 | ||||
-rw-r--r-- | drivers/pci/probe.c | 4 |
4 files changed, 35 insertions, 2 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 87a5ddbb324f..95d198570290 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -1049,6 +1049,7 @@ struct bus_type pci_bus_type = { | |||
1049 | .remove = pci_device_remove, | 1049 | .remove = pci_device_remove, |
1050 | .shutdown = pci_device_shutdown, | 1050 | .shutdown = pci_device_shutdown, |
1051 | .dev_attrs = pci_dev_attrs, | 1051 | .dev_attrs = pci_dev_attrs, |
1052 | .bus_attrs = pci_bus_attrs, | ||
1052 | .pm = PCI_PM_OPS_PTR, | 1053 | .pm = PCI_PM_OPS_PTR, |
1053 | }; | 1054 | }; |
1054 | 1055 | ||
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index ec7a175dcbaf..be7468a5eb72 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -219,6 +219,32 @@ msi_bus_store(struct device *dev, struct device_attribute *attr, | |||
219 | return count; | 219 | return count; |
220 | } | 220 | } |
221 | 221 | ||
222 | #ifdef CONFIG_HOTPLUG | ||
223 | static DEFINE_MUTEX(pci_remove_rescan_mutex); | ||
224 | static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf, | ||
225 | size_t count) | ||
226 | { | ||
227 | unsigned long val; | ||
228 | struct pci_bus *b = NULL; | ||
229 | |||
230 | if (strict_strtoul(buf, 0, &val) < 0) | ||
231 | return -EINVAL; | ||
232 | |||
233 | if (val) { | ||
234 | mutex_lock(&pci_remove_rescan_mutex); | ||
235 | while ((b = pci_find_next_bus(b)) != NULL) | ||
236 | pci_rescan_bus(b); | ||
237 | mutex_unlock(&pci_remove_rescan_mutex); | ||
238 | } | ||
239 | return count; | ||
240 | } | ||
241 | |||
242 | struct bus_attribute pci_bus_attrs[] = { | ||
243 | __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store), | ||
244 | __ATTR_NULL | ||
245 | }; | ||
246 | #endif | ||
247 | |||
222 | struct device_attribute pci_dev_attrs[] = { | 248 | struct device_attribute pci_dev_attrs[] = { |
223 | __ATTR_RO(resource), | 249 | __ATTR_RO(resource), |
224 | __ATTR_RO(vendor), | 250 | __ATTR_RO(vendor), |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 22dcfdb75d91..45833a5bca61 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -138,6 +138,12 @@ extern int pcie_mch_quirk; | |||
138 | extern struct device_attribute pci_dev_attrs[]; | 138 | extern struct device_attribute pci_dev_attrs[]; |
139 | extern struct device_attribute dev_attr_cpuaffinity; | 139 | extern struct device_attribute dev_attr_cpuaffinity; |
140 | extern struct device_attribute dev_attr_cpulistaffinity; | 140 | extern struct device_attribute dev_attr_cpulistaffinity; |
141 | #ifdef CONFIG_HOTPLUG | ||
142 | extern struct bus_attribute pci_bus_attrs[]; | ||
143 | #else | ||
144 | #define pci_bus_attrs NULL | ||
145 | #endif | ||
146 | |||
141 | 147 | ||
142 | /** | 148 | /** |
143 | * pci_match_one_device - Tell if a PCI device structure has a matching | 149 | * pci_match_one_device - Tell if a PCI device structure has a matching |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 60a8e5fec6c5..56c71e585f3d 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -1228,13 +1228,13 @@ unsigned int __devinit pci_rescan_bus(struct pci_bus *bus) | |||
1228 | 1228 | ||
1229 | max = pci_scan_child_bus(bus); | 1229 | max = pci_scan_child_bus(bus); |
1230 | 1230 | ||
1231 | up_read(&pci_bus_sem); | 1231 | down_read(&pci_bus_sem); |
1232 | list_for_each_entry(dev, &bus->devices, bus_list) | 1232 | list_for_each_entry(dev, &bus->devices, bus_list) |
1233 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | 1233 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || |
1234 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) | 1234 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) |
1235 | if (dev->subordinate) | 1235 | if (dev->subordinate) |
1236 | pci_bus_size_bridges(dev->subordinate); | 1236 | pci_bus_size_bridges(dev->subordinate); |
1237 | down_read(&pci_bus_sem); | 1237 | up_read(&pci_bus_sem); |
1238 | 1238 | ||
1239 | pci_bus_assign_resources(bus); | 1239 | pci_bus_assign_resources(bus); |
1240 | pci_enable_bridges(bus); | 1240 | pci_enable_bridges(bus); |