diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/pci-sysfs.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index be7468a5eb72..e16990ecc024 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -243,6 +243,39 @@ struct bus_attribute pci_bus_attrs[] = { | |||
243 | __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store), | 243 | __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store), |
244 | __ATTR_NULL | 244 | __ATTR_NULL |
245 | }; | 245 | }; |
246 | |||
247 | static void remove_callback(struct device *dev) | ||
248 | { | ||
249 | struct pci_dev *pdev = to_pci_dev(dev); | ||
250 | |||
251 | mutex_lock(&pci_remove_rescan_mutex); | ||
252 | pci_remove_bus_device(pdev); | ||
253 | mutex_unlock(&pci_remove_rescan_mutex); | ||
254 | } | ||
255 | |||
256 | static ssize_t | ||
257 | remove_store(struct device *dev, struct device_attribute *dummy, | ||
258 | const char *buf, size_t count) | ||
259 | { | ||
260 | int ret = 0; | ||
261 | unsigned long val; | ||
262 | struct pci_dev *pdev = to_pci_dev(dev); | ||
263 | |||
264 | if (strict_strtoul(buf, 0, &val) < 0) | ||
265 | return -EINVAL; | ||
266 | |||
267 | if (pci_is_root_bus(pdev->bus)) | ||
268 | return -EBUSY; | ||
269 | |||
270 | /* An attribute cannot be unregistered by one of its own methods, | ||
271 | * so we have to use this roundabout approach. | ||
272 | */ | ||
273 | if (val) | ||
274 | ret = device_schedule_callback(dev, remove_callback); | ||
275 | if (ret) | ||
276 | count = ret; | ||
277 | return count; | ||
278 | } | ||
246 | #endif | 279 | #endif |
247 | 280 | ||
248 | struct device_attribute pci_dev_attrs[] = { | 281 | struct device_attribute pci_dev_attrs[] = { |
@@ -263,6 +296,9 @@ struct device_attribute pci_dev_attrs[] = { | |||
263 | __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR), | 296 | __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR), |
264 | broken_parity_status_show,broken_parity_status_store), | 297 | broken_parity_status_show,broken_parity_status_store), |
265 | __ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store), | 298 | __ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store), |
299 | #ifdef CONFIG_HOTPLUG | ||
300 | __ATTR(remove, (S_IWUSR|S_IWGRP), NULL, remove_store), | ||
301 | #endif | ||
266 | __ATTR_NULL, | 302 | __ATTR_NULL, |
267 | }; | 303 | }; |
268 | 304 | ||