aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/bus.c22
-rw-r--r--drivers/pci/hotplug/fakephp.c18
-rw-r--r--drivers/pci/pci-driver.c5
-rw-r--r--drivers/pci/pci-sysfs.c112
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c3
-rw-r--r--drivers/pci/pcie/portdrv_core.c6
-rw-r--r--drivers/pci/pcie/portdrv_pci.c16
-rw-r--r--drivers/pci/probe.c16
8 files changed, 137 insertions, 61 deletions
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 5f7db9d2436e..aadaa3c8096b 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -77,9 +77,12 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
77 * This adds a single pci device to the global 77 * This adds a single pci device to the global
78 * device list and adds sysfs and procfs entries 78 * device list and adds sysfs and procfs entries
79 */ 79 */
80void __devinit pci_bus_add_device(struct pci_dev *dev) 80int __devinit pci_bus_add_device(struct pci_dev *dev)
81{ 81{
82 device_add(&dev->dev); 82 int retval;
83 retval = device_add(&dev->dev);
84 if (retval)
85 return retval;
83 86
84 down_write(&pci_bus_sem); 87 down_write(&pci_bus_sem);
85 list_add_tail(&dev->global_list, &pci_devices); 88 list_add_tail(&dev->global_list, &pci_devices);
@@ -87,6 +90,7 @@ void __devinit pci_bus_add_device(struct pci_dev *dev)
87 90
88 pci_proc_attach_device(dev); 91 pci_proc_attach_device(dev);
89 pci_create_sysfs_dev_files(dev); 92 pci_create_sysfs_dev_files(dev);
93 return 0;
90} 94}
91 95
92/** 96/**
@@ -104,6 +108,7 @@ void __devinit pci_bus_add_device(struct pci_dev *dev)
104void __devinit pci_bus_add_devices(struct pci_bus *bus) 108void __devinit pci_bus_add_devices(struct pci_bus *bus)
105{ 109{
106 struct pci_dev *dev; 110 struct pci_dev *dev;
111 int retval;
107 112
108 list_for_each_entry(dev, &bus->devices, bus_list) { 113 list_for_each_entry(dev, &bus->devices, bus_list) {
109 /* 114 /*
@@ -112,7 +117,9 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
112 */ 117 */
113 if (!list_empty(&dev->global_list)) 118 if (!list_empty(&dev->global_list))
114 continue; 119 continue;
115 pci_bus_add_device(dev); 120 retval = pci_bus_add_device(dev);
121 if (retval)
122 dev_err(&dev->dev, "Error adding device, continuing\n");
116 } 123 }
117 124
118 list_for_each_entry(dev, &bus->devices, bus_list) { 125 list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -129,10 +136,13 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
129 list_add_tail(&dev->subordinate->node, 136 list_add_tail(&dev->subordinate->node,
130 &dev->bus->children); 137 &dev->bus->children);
131 up_write(&pci_bus_sem); 138 up_write(&pci_bus_sem);
132 } 139 }
133 pci_bus_add_devices(dev->subordinate); 140 pci_bus_add_devices(dev->subordinate);
134 141 retval = sysfs_create_link(&dev->subordinate->class_dev.kobj,
135 sysfs_create_link(&dev->subordinate->class_dev.kobj, &dev->dev.kobj, "bridge"); 142 &dev->dev.kobj, "bridge");
143 if (retval)
144 dev_err(&dev->dev, "Error creating sysfs "
145 "bridge symlink, continuing...\n");
136 } 146 }
137 } 147 }
138} 148}
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index dd2b762777c4..05a4f0f90186 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -176,7 +176,9 @@ static void pci_rescan_slot(struct pci_dev *temp)
176 struct pci_bus *bus = temp->bus; 176 struct pci_bus *bus = temp->bus;
177 struct pci_dev *dev; 177 struct pci_dev *dev;
178 int func; 178 int func;
179 int retval;
179 u8 hdr_type; 180 u8 hdr_type;
181
180 if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) { 182 if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) {
181 temp->hdr_type = hdr_type & 0x7f; 183 temp->hdr_type = hdr_type & 0x7f;
182 if (!pci_find_slot(bus->number, temp->devfn)) { 184 if (!pci_find_slot(bus->number, temp->devfn)) {
@@ -185,8 +187,12 @@ static void pci_rescan_slot(struct pci_dev *temp)
185 dbg("New device on %s function %x:%x\n", 187 dbg("New device on %s function %x:%x\n",
186 bus->name, temp->devfn >> 3, 188 bus->name, temp->devfn >> 3,
187 temp->devfn & 7); 189 temp->devfn & 7);
188 pci_bus_add_device(dev); 190 retval = pci_bus_add_device(dev);
189 add_slot(dev); 191 if (retval)
192 dev_err(&dev->dev, "error adding "
193 "device, continuing.\n");
194 else
195 add_slot(dev);
190 } 196 }
191 } 197 }
192 /* multifunction device? */ 198 /* multifunction device? */
@@ -205,8 +211,12 @@ static void pci_rescan_slot(struct pci_dev *temp)
205 dbg("New device on %s function %x:%x\n", 211 dbg("New device on %s function %x:%x\n",
206 bus->name, temp->devfn >> 3, 212 bus->name, temp->devfn >> 3,
207 temp->devfn & 7); 213 temp->devfn & 7);
208 pci_bus_add_device(dev); 214 retval = pci_bus_add_device(dev);
209 add_slot(dev); 215 if (retval)
216 dev_err(&dev->dev, "error adding "
217 "device, continuing.\n");
218 else
219 add_slot(dev);
210 } 220 }
211 } 221 }
212 } 222 }
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index d8ace1f90dd2..309629e03bae 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -56,6 +56,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
56 subdevice=PCI_ANY_ID, class=0, class_mask=0; 56 subdevice=PCI_ANY_ID, class=0, class_mask=0;
57 unsigned long driver_data=0; 57 unsigned long driver_data=0;
58 int fields=0; 58 int fields=0;
59 int retval = 0;
59 60
60 fields = sscanf(buf, "%x %x %x %x %x %x %lux", 61 fields = sscanf(buf, "%x %x %x %x %x %x %lux",
61 &vendor, &device, &subvendor, &subdevice, 62 &vendor, &device, &subvendor, &subdevice,
@@ -82,10 +83,12 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
82 spin_unlock(&pdrv->dynids.lock); 83 spin_unlock(&pdrv->dynids.lock);
83 84
84 if (get_driver(&pdrv->driver)) { 85 if (get_driver(&pdrv->driver)) {
85 driver_attach(&pdrv->driver); 86 retval = driver_attach(&pdrv->driver);
86 put_driver(&pdrv->driver); 87 put_driver(&pdrv->driver);
87 } 88 }
88 89
90 if (retval)
91 return retval;
89 return count; 92 return count;
90} 93}
91static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); 94static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 010e01c4bd43..a1d2e979b17f 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -117,6 +117,7 @@ is_enabled_store(struct device *dev, struct device_attribute *attr,
117 const char *buf, size_t count) 117 const char *buf, size_t count)
118{ 118{
119 struct pci_dev *pdev = to_pci_dev(dev); 119 struct pci_dev *pdev = to_pci_dev(dev);
120 int retval = 0;
120 121
121 /* this can crash the machine when done on the "wrong" device */ 122 /* this can crash the machine when done on the "wrong" device */
122 if (!capable(CAP_SYS_ADMIN)) 123 if (!capable(CAP_SYS_ADMIN))
@@ -126,8 +127,10 @@ is_enabled_store(struct device *dev, struct device_attribute *attr,
126 pci_disable_device(pdev); 127 pci_disable_device(pdev);
127 128
128 if (*buf == '1') 129 if (*buf == '1')
129 pci_enable_device(pdev); 130 retval = pci_enable_device(pdev);
130 131
132 if (retval)
133 return retval;
131 return count; 134 return count;
132} 135}
133 136
@@ -426,15 +429,38 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
426} 429}
427 430
428/** 431/**
432 * pci_remove_resource_files - cleanup resource files
433 * @dev: dev to cleanup
434 *
435 * If we created resource files for @dev, remove them from sysfs and
436 * free their resources.
437 */
438static void
439pci_remove_resource_files(struct pci_dev *pdev)
440{
441 int i;
442
443 for (i = 0; i < PCI_ROM_RESOURCE; i++) {
444 struct bin_attribute *res_attr;
445
446 res_attr = pdev->res_attr[i];
447 if (res_attr) {
448 sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
449 kfree(res_attr);
450 }
451 }
452}
453
454/**
429 * pci_create_resource_files - create resource files in sysfs for @dev 455 * pci_create_resource_files - create resource files in sysfs for @dev
430 * @dev: dev in question 456 * @dev: dev in question
431 * 457 *
432 * Walk the resources in @dev creating files for each resource available. 458 * Walk the resources in @dev creating files for each resource available.
433 */ 459 */
434static void 460static int pci_create_resource_files(struct pci_dev *pdev)
435pci_create_resource_files(struct pci_dev *pdev)
436{ 461{
437 int i; 462 int i;
463 int retval;
438 464
439 /* Expose the PCI resources from this device as files */ 465 /* Expose the PCI resources from this device as files */
440 for (i = 0; i < PCI_ROM_RESOURCE; i++) { 466 for (i = 0; i < PCI_ROM_RESOURCE; i++) {
@@ -457,35 +483,19 @@ pci_create_resource_files(struct pci_dev *pdev)
457 res_attr->size = pci_resource_len(pdev, i); 483 res_attr->size = pci_resource_len(pdev, i);
458 res_attr->mmap = pci_mmap_resource; 484 res_attr->mmap = pci_mmap_resource;
459 res_attr->private = &pdev->resource[i]; 485 res_attr->private = &pdev->resource[i];
460 sysfs_create_bin_file(&pdev->dev.kobj, res_attr); 486 retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
461 } 487 if (retval) {
462 } 488 pci_remove_resource_files(pdev);
463} 489 return retval;
464 490 }
465/** 491 } else {
466 * pci_remove_resource_files - cleanup resource files 492 return -ENOMEM;
467 * @dev: dev to cleanup
468 *
469 * If we created resource files for @dev, remove them from sysfs and
470 * free their resources.
471 */
472static void
473pci_remove_resource_files(struct pci_dev *pdev)
474{
475 int i;
476
477 for (i = 0; i < PCI_ROM_RESOURCE; i++) {
478 struct bin_attribute *res_attr;
479
480 res_attr = pdev->res_attr[i];
481 if (res_attr) {
482 sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
483 kfree(res_attr);
484 } 493 }
485 } 494 }
495 return 0;
486} 496}
487#else /* !HAVE_PCI_MMAP */ 497#else /* !HAVE_PCI_MMAP */
488static inline void pci_create_resource_files(struct pci_dev *dev) { return; } 498static inline int pci_create_resource_files(struct pci_dev *dev) { return 0; }
489static inline void pci_remove_resource_files(struct pci_dev *dev) { return; } 499static inline void pci_remove_resource_files(struct pci_dev *dev) { return; }
490#endif /* HAVE_PCI_MMAP */ 500#endif /* HAVE_PCI_MMAP */
491 501
@@ -570,22 +580,27 @@ static struct bin_attribute pcie_config_attr = {
570 .write = pci_write_config, 580 .write = pci_write_config,
571}; 581};
572 582
573int pci_create_sysfs_dev_files (struct pci_dev *pdev) 583int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
574{ 584{
585 struct bin_attribute *rom_attr = NULL;
586 int retval;
587
575 if (!sysfs_initialized) 588 if (!sysfs_initialized)
576 return -EACCES; 589 return -EACCES;
577 590
578 if (pdev->cfg_size < 4096) 591 if (pdev->cfg_size < 4096)
579 sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr); 592 retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
580 else 593 else
581 sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr); 594 retval = sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
595 if (retval)
596 goto err;
582 597
583 pci_create_resource_files(pdev); 598 retval = pci_create_resource_files(pdev);
599 if (retval)
600 goto err_bin_file;
584 601
585 /* If the device has a ROM, try to expose it in sysfs. */ 602 /* If the device has a ROM, try to expose it in sysfs. */
586 if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) { 603 if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
587 struct bin_attribute *rom_attr;
588
589 rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC); 604 rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC);
590 if (rom_attr) { 605 if (rom_attr) {
591 pdev->rom_attr = rom_attr; 606 pdev->rom_attr = rom_attr;
@@ -595,13 +610,28 @@ int pci_create_sysfs_dev_files (struct pci_dev *pdev)
595 rom_attr->attr.owner = THIS_MODULE; 610 rom_attr->attr.owner = THIS_MODULE;
596 rom_attr->read = pci_read_rom; 611 rom_attr->read = pci_read_rom;
597 rom_attr->write = pci_write_rom; 612 rom_attr->write = pci_write_rom;
598 sysfs_create_bin_file(&pdev->dev.kobj, rom_attr); 613 retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
614 if (retval)
615 goto err_rom;
616 } else {
617 retval = -ENOMEM;
618 goto err_bin_file;
599 } 619 }
600 } 620 }
601 /* add platform-specific attributes */ 621 /* add platform-specific attributes */
602 pcibios_add_platform_entries(pdev); 622 pcibios_add_platform_entries(pdev);
603 623
604 return 0; 624 return 0;
625
626err_rom:
627 kfree(rom_attr);
628err_bin_file:
629 if (pdev->cfg_size < 4096)
630 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
631 else
632 sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
633err:
634 return retval;
605} 635}
606 636
607/** 637/**
@@ -630,10 +660,14 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
630static int __init pci_sysfs_init(void) 660static int __init pci_sysfs_init(void)
631{ 661{
632 struct pci_dev *pdev = NULL; 662 struct pci_dev *pdev = NULL;
633 663 int retval;
664
634 sysfs_initialized = 1; 665 sysfs_initialized = 1;
635 for_each_pci_dev(pdev) 666 for_each_pci_dev(pdev) {
636 pci_create_sysfs_dev_files(pdev); 667 retval = pci_create_sysfs_dev_files(pdev);
668 if (retval)
669 return retval;
670 }
637 671
638 return 0; 672 return 0;
639} 673}
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 5591043acea7..1c7e660d6535 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -357,7 +357,8 @@ static int find_aer_service_iter(struct device *device, void *data)
357static void find_aer_service(struct pci_dev *dev, 357static void find_aer_service(struct pci_dev *dev,
358 struct find_aer_service_data *data) 358 struct find_aer_service_data *data)
359{ 359{
360 device_for_each_child(&dev->dev, data, find_aer_service_iter); 360 int retval;
361 retval = device_for_each_child(&dev->dev, data, find_aer_service_iter);
361} 362}
362 363
363static pci_ers_result_t reset_link(struct pcie_device *aerdev, 364static pci_ers_result_t reset_link(struct pcie_device *aerdev,
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index cf9e810b4bf8..bd6615b4d40e 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -340,8 +340,7 @@ static int suspend_iter(struct device *dev, void *data)
340 340
341int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state) 341int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state)
342{ 342{
343 device_for_each_child(&dev->dev, &state, suspend_iter); 343 return device_for_each_child(&dev->dev, &state, suspend_iter);
344 return 0;
345} 344}
346 345
347static int resume_iter(struct device *dev, void *data) 346static int resume_iter(struct device *dev, void *data)
@@ -359,8 +358,7 @@ static int resume_iter(struct device *dev, void *data)
359 358
360int pcie_port_device_resume(struct pci_dev *dev) 359int pcie_port_device_resume(struct pci_dev *dev)
361{ 360{
362 device_for_each_child(&dev->dev, NULL, resume_iter); 361 return device_for_each_child(&dev->dev, NULL, resume_iter);
363 return 0;
364} 362}
365#endif 363#endif
366 364
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index e4a2429986f0..037690e08f5f 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -147,8 +147,10 @@ static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev,
147{ 147{
148 struct aer_broadcast_data result_data = 148 struct aer_broadcast_data result_data =
149 {error, PCI_ERS_RESULT_CAN_RECOVER}; 149 {error, PCI_ERS_RESULT_CAN_RECOVER};
150 int retval;
150 151
151 device_for_each_child(&dev->dev, &result_data, error_detected_iter); 152 /* can not fail */
153 retval = device_for_each_child(&dev->dev, &result_data, error_detected_iter);
152 154
153 return result_data.result; 155 return result_data.result;
154} 156}
@@ -181,8 +183,10 @@ static int mmio_enabled_iter(struct device *device, void *data)
181static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev) 183static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev)
182{ 184{
183 pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED; 185 pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
186 int retval;
184 187
185 device_for_each_child(&dev->dev, &status, mmio_enabled_iter); 188 /* get true return value from &status */
189 retval = device_for_each_child(&dev->dev, &status, mmio_enabled_iter);
186 return status; 190 return status;
187} 191}
188 192
@@ -214,6 +218,7 @@ static int slot_reset_iter(struct device *device, void *data)
214static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev) 218static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
215{ 219{
216 pci_ers_result_t status; 220 pci_ers_result_t status;
221 int retval;
217 222
218 /* If fatal, restore cfg space for possible link reset at upstream */ 223 /* If fatal, restore cfg space for possible link reset at upstream */
219 if (dev->error_state == pci_channel_io_frozen) { 224 if (dev->error_state == pci_channel_io_frozen) {
@@ -221,7 +226,8 @@ static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
221 pci_enable_pcie_error_reporting(dev); 226 pci_enable_pcie_error_reporting(dev);
222 } 227 }
223 228
224 device_for_each_child(&dev->dev, &status, slot_reset_iter); 229 /* get true return value from &status */
230 retval = device_for_each_child(&dev->dev, &status, slot_reset_iter);
225 231
226 return status; 232 return status;
227} 233}
@@ -248,7 +254,9 @@ static int resume_iter(struct device *device, void *data)
248 254
249static void pcie_portdrv_err_resume(struct pci_dev *dev) 255static void pcie_portdrv_err_resume(struct pci_dev *dev)
250{ 256{
251 device_for_each_child(&dev->dev, NULL, resume_iter); 257 int retval;
258 /* nothing to do with error value, if it ever happens */
259 retval = device_for_each_child(&dev->dev, NULL, resume_iter);
252} 260}
253 261
254/* 262/*
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index c5a58d1c6c1c..a3b0a5eb5054 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -339,6 +339,7 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
339{ 339{
340 struct pci_bus *child; 340 struct pci_bus *child;
341 int i; 341 int i;
342 int retval;
342 343
343 /* 344 /*
344 * Allocate a new bus, and inherit stuff from the parent.. 345 * Allocate a new bus, and inherit stuff from the parent..
@@ -356,8 +357,13 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
356 357
357 child->class_dev.class = &pcibus_class; 358 child->class_dev.class = &pcibus_class;
358 sprintf(child->class_dev.class_id, "%04x:%02x", pci_domain_nr(child), busnr); 359 sprintf(child->class_dev.class_id, "%04x:%02x", pci_domain_nr(child), busnr);
359 class_device_register(&child->class_dev); 360 retval = class_device_register(&child->class_dev);
360 class_device_create_file(&child->class_dev, &class_device_attr_cpuaffinity); 361 if (retval)
362 goto error_register;
363 retval = class_device_create_file(&child->class_dev,
364 &class_device_attr_cpuaffinity);
365 if (retval)
366 goto error_file_create;
361 367
362 /* 368 /*
363 * Set up the primary, secondary and subordinate 369 * Set up the primary, secondary and subordinate
@@ -375,6 +381,12 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
375 bridge->subordinate = child; 381 bridge->subordinate = child;
376 382
377 return child; 383 return child;
384
385error_file_create:
386 class_device_unregister(&child->class_dev);
387error_register:
388 kfree(child);
389 return NULL;
378} 390}
379 391
380struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr) 392struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)