diff options
-rw-r--r-- | Documentation/ABI/testing/sysfs-bus-pci | 8 | ||||
-rw-r--r-- | Documentation/filesystems/sysfs-pci.txt | 10 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 36 |
3 files changed, 54 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci index e6ad047cb3c2..daa791a9e85e 100644 --- a/Documentation/ABI/testing/sysfs-bus-pci +++ b/Documentation/ABI/testing/sysfs-bus-pci | |||
@@ -66,6 +66,14 @@ Description: | |||
66 | re-discover previously removed devices. | 66 | re-discover previously removed devices. |
67 | Depends on CONFIG_HOTPLUG. | 67 | Depends on CONFIG_HOTPLUG. |
68 | 68 | ||
69 | What: /sys/bus/pci/devices/.../remove | ||
70 | Date: January 2009 | ||
71 | Contact: Linux PCI developers <linux-pci@vger.kernel.org> | ||
72 | Description: | ||
73 | Writing a non-zero value to this attribute will | ||
74 | hot-remove the PCI device and any of its children. | ||
75 | Depends on CONFIG_HOTPLUG. | ||
76 | |||
69 | What: /sys/bus/pci/devices/.../vpd | 77 | What: /sys/bus/pci/devices/.../vpd |
70 | Date: February 2008 | 78 | Date: February 2008 |
71 | Contact: Ben Hutchings <bhutchings@solarflare.com> | 79 | Contact: Ben Hutchings <bhutchings@solarflare.com> |
diff --git a/Documentation/filesystems/sysfs-pci.txt b/Documentation/filesystems/sysfs-pci.txt index 9f8740ca3f3b..26e4b8bc53ee 100644 --- a/Documentation/filesystems/sysfs-pci.txt +++ b/Documentation/filesystems/sysfs-pci.txt | |||
@@ -12,6 +12,7 @@ that support it. For example, a given bus might look like this: | |||
12 | | |-- enable | 12 | | |-- enable |
13 | | |-- irq | 13 | | |-- irq |
14 | | |-- local_cpus | 14 | | |-- local_cpus |
15 | | |-- remove | ||
15 | | |-- resource | 16 | | |-- resource |
16 | | |-- resource0 | 17 | | |-- resource0 |
17 | | |-- resource1 | 18 | | |-- resource1 |
@@ -36,6 +37,7 @@ files, each with their own function. | |||
36 | enable Whether the device is enabled (ascii, rw) | 37 | enable Whether the device is enabled (ascii, rw) |
37 | irq IRQ number (ascii, ro) | 38 | irq IRQ number (ascii, ro) |
38 | local_cpus nearby CPU mask (cpumask, ro) | 39 | local_cpus nearby CPU mask (cpumask, ro) |
40 | remove remove device from kernel's list (ascii, wo) | ||
39 | resource PCI resource host addresses (ascii, ro) | 41 | resource PCI resource host addresses (ascii, ro) |
40 | resource0..N PCI resource N, if present (binary, mmap) | 42 | resource0..N PCI resource N, if present (binary, mmap) |
41 | resource0_wc..N_wc PCI WC map resource N, if prefetchable (binary, mmap) | 43 | resource0_wc..N_wc PCI WC map resource N, if prefetchable (binary, mmap) |
@@ -46,6 +48,7 @@ files, each with their own function. | |||
46 | 48 | ||
47 | ro - read only file | 49 | ro - read only file |
48 | rw - file is readable and writable | 50 | rw - file is readable and writable |
51 | wo - write only file | ||
49 | mmap - file is mmapable | 52 | mmap - file is mmapable |
50 | ascii - file contains ascii text | 53 | ascii - file contains ascii text |
51 | binary - file contains binary data | 54 | binary - file contains binary data |
@@ -73,6 +76,13 @@ that the device must be enabled for a rom read to return data succesfully. | |||
73 | In the event a driver is not bound to the device, it can be enabled using the | 76 | In the event a driver is not bound to the device, it can be enabled using the |
74 | 'enable' file, documented above. | 77 | 'enable' file, documented above. |
75 | 78 | ||
79 | The 'remove' file is used to remove the PCI device, by writing a non-zero | ||
80 | integer to the file. This does not involve any kind of hot-plug functionality, | ||
81 | e.g. powering off the device. The device is removed from the kernel's list of | ||
82 | PCI devices, the sysfs directory for it is removed, and the device will be | ||
83 | removed from any drivers attached to it. Removal of PCI root buses is | ||
84 | disallowed. | ||
85 | |||
76 | Accessing legacy resources through sysfs | 86 | Accessing legacy resources through sysfs |
77 | ---------------------------------------- | 87 | ---------------------------------------- |
78 | 88 | ||
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 | ||