aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorAlex Chiang <achiang@hp.com>2009-03-20 16:56:31 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-03-20 17:57:58 -0400
commit705b1aaa823e800490f157cd9366ad8cff385f5f (patch)
tree634ea8ba227a305074938f49c110fea8e68e8bb3 /drivers/pci
parent3ed4fd96b3188406ac5357d9290bcffa08c65cf6 (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.c1
-rw-r--r--drivers/pci/pci-sysfs.c26
-rw-r--r--drivers/pci/pci.h6
-rw-r--r--drivers/pci/probe.c4
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
223static DEFINE_MUTEX(pci_remove_rescan_mutex);
224static 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
242struct bus_attribute pci_bus_attrs[] = {
243 __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store),
244 __ATTR_NULL
245};
246#endif
247
222struct device_attribute pci_dev_attrs[] = { 248struct 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;
138extern struct device_attribute pci_dev_attrs[]; 138extern struct device_attribute pci_dev_attrs[];
139extern struct device_attribute dev_attr_cpuaffinity; 139extern struct device_attribute dev_attr_cpuaffinity;
140extern struct device_attribute dev_attr_cpulistaffinity; 140extern struct device_attribute dev_attr_cpulistaffinity;
141#ifdef CONFIG_HOTPLUG
142extern 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);