diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/cpci_hotplug_core.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/cpci_hotplug_pci.c | 5 | ||||
-rw-r--r-- | drivers/pci/hotplug/cpqphp_sysfs.c | 4 | ||||
-rw-r--r-- | drivers/pci/hotplug/pci_hotplug_core.c | 4 | ||||
-rw-r--r-- | drivers/pci/hotplug/rpadlpar_sysfs.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_sysfs.c | 4 | ||||
-rw-r--r-- | drivers/pci/pci-driver.c | 31 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 21 | ||||
-rw-r--r-- | drivers/pci/pcie/portdrv_core.c | 139 | ||||
-rw-r--r-- | drivers/pci/probe.c | 2 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 6 |
11 files changed, 114 insertions, 106 deletions
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index 8132d946c384..30af105271a2 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c | |||
@@ -217,6 +217,8 @@ static void release_slot(struct hotplug_slot *hotplug_slot) | |||
217 | kfree(slot->hotplug_slot->info); | 217 | kfree(slot->hotplug_slot->info); |
218 | kfree(slot->hotplug_slot->name); | 218 | kfree(slot->hotplug_slot->name); |
219 | kfree(slot->hotplug_slot); | 219 | kfree(slot->hotplug_slot); |
220 | if (slot->dev) | ||
221 | pci_dev_put(slot->dev); | ||
220 | kfree(slot); | 222 | kfree(slot); |
221 | } | 223 | } |
222 | 224 | ||
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index c878028ad215..225b5e551dd6 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c | |||
@@ -315,9 +315,12 @@ int cpci_unconfigure_slot(struct slot* slot) | |||
315 | PCI_DEVFN(PCI_SLOT(slot->devfn), i)); | 315 | PCI_DEVFN(PCI_SLOT(slot->devfn), i)); |
316 | if (dev) { | 316 | if (dev) { |
317 | pci_remove_bus_device(dev); | 317 | pci_remove_bus_device(dev); |
318 | slot->dev = NULL; | 318 | pci_dev_put(dev); |
319 | } | 319 | } |
320 | } | 320 | } |
321 | pci_dev_put(slot->dev); | ||
322 | slot->dev = NULL; | ||
323 | |||
321 | dbg("%s - exit", __FUNCTION__); | 324 | dbg("%s - exit", __FUNCTION__); |
322 | return 0; | 325 | return 0; |
323 | } | 326 | } |
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c index 41c7971d06c5..4c11048ad51b 100644 --- a/drivers/pci/hotplug/cpqphp_sysfs.c +++ b/drivers/pci/hotplug/cpqphp_sysfs.c | |||
@@ -38,7 +38,7 @@ | |||
38 | 38 | ||
39 | /* A few routines that create sysfs entries for the hot plug controller */ | 39 | /* A few routines that create sysfs entries for the hot plug controller */ |
40 | 40 | ||
41 | static ssize_t show_ctrl (struct device *dev, char *buf) | 41 | static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf) |
42 | { | 42 | { |
43 | struct pci_dev *pci_dev; | 43 | struct pci_dev *pci_dev; |
44 | struct controller *ctrl; | 44 | struct controller *ctrl; |
@@ -82,7 +82,7 @@ static ssize_t show_ctrl (struct device *dev, char *buf) | |||
82 | } | 82 | } |
83 | static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL); | 83 | static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL); |
84 | 84 | ||
85 | static ssize_t show_dev (struct device *dev, char *buf) | 85 | static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf) |
86 | { | 86 | { |
87 | struct pci_dev *pci_dev; | 87 | struct pci_dev *pci_dev; |
88 | struct controller *ctrl; | 88 | struct controller *ctrl; |
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index c802f6270b89..c4282902cb52 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c | |||
@@ -73,7 +73,7 @@ static ssize_t hotplug_slot_attr_show(struct kobject *kobj, | |||
73 | { | 73 | { |
74 | struct hotplug_slot *slot = to_hotplug_slot(kobj); | 74 | struct hotplug_slot *slot = to_hotplug_slot(kobj); |
75 | struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr); | 75 | struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr); |
76 | return attribute->show ? attribute->show(slot, buf) : 0; | 76 | return attribute->show ? attribute->show(slot, buf) : -EIO; |
77 | } | 77 | } |
78 | 78 | ||
79 | static ssize_t hotplug_slot_attr_store(struct kobject *kobj, | 79 | static ssize_t hotplug_slot_attr_store(struct kobject *kobj, |
@@ -81,7 +81,7 @@ static ssize_t hotplug_slot_attr_store(struct kobject *kobj, | |||
81 | { | 81 | { |
82 | struct hotplug_slot *slot = to_hotplug_slot(kobj); | 82 | struct hotplug_slot *slot = to_hotplug_slot(kobj); |
83 | struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr); | 83 | struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr); |
84 | return attribute->store ? attribute->store(slot, buf, len) : 0; | 84 | return attribute->store ? attribute->store(slot, buf, len) : -EIO; |
85 | } | 85 | } |
86 | 86 | ||
87 | static struct sysfs_ops hotplug_slot_sysfs_ops = { | 87 | static struct sysfs_ops hotplug_slot_sysfs_ops = { |
diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c index 3285b822478d..752e6513c447 100644 --- a/drivers/pci/hotplug/rpadlpar_sysfs.c +++ b/drivers/pci/hotplug/rpadlpar_sysfs.c | |||
@@ -48,7 +48,7 @@ dlpar_attr_store(struct kobject * kobj, struct attribute * attr, | |||
48 | struct dlpar_io_attr *dlpar_attr = container_of(attr, | 48 | struct dlpar_io_attr *dlpar_attr = container_of(attr, |
49 | struct dlpar_io_attr, attr); | 49 | struct dlpar_io_attr, attr); |
50 | return dlpar_attr->store ? | 50 | return dlpar_attr->store ? |
51 | dlpar_attr->store(dlpar_attr, buf, nbytes) : 0; | 51 | dlpar_attr->store(dlpar_attr, buf, nbytes) : -EIO; |
52 | } | 52 | } |
53 | 53 | ||
54 | static struct sysfs_ops dlpar_attr_sysfs_ops = { | 54 | static struct sysfs_ops dlpar_attr_sysfs_ops = { |
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c index 9a1ee132d12c..c9445ebda5c7 100644 --- a/drivers/pci/hotplug/shpchp_sysfs.c +++ b/drivers/pci/hotplug/shpchp_sysfs.c | |||
@@ -38,7 +38,7 @@ | |||
38 | 38 | ||
39 | /* A few routines that create sysfs entries for the hot plug controller */ | 39 | /* A few routines that create sysfs entries for the hot plug controller */ |
40 | 40 | ||
41 | static ssize_t show_ctrl (struct device *dev, char *buf) | 41 | static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf) |
42 | { | 42 | { |
43 | struct pci_dev *pci_dev; | 43 | struct pci_dev *pci_dev; |
44 | struct controller *ctrl; | 44 | struct controller *ctrl; |
@@ -82,7 +82,7 @@ static ssize_t show_ctrl (struct device *dev, char *buf) | |||
82 | } | 82 | } |
83 | static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL); | 83 | static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL); |
84 | 84 | ||
85 | static ssize_t show_dev (struct device *dev, char *buf) | 85 | static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf) |
86 | { | 86 | { |
87 | struct pci_dev *pci_dev; | 87 | struct pci_dev *pci_dev; |
88 | struct controller *ctrl; | 88 | struct controller *ctrl; |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index fe98553c978f..e65bf2b395aa 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -335,13 +335,14 @@ pci_driver_attr_show(struct kobject * kobj, struct attribute *attr, char *buf) | |||
335 | { | 335 | { |
336 | struct device_driver *driver = kobj_to_pci_driver(kobj); | 336 | struct device_driver *driver = kobj_to_pci_driver(kobj); |
337 | struct driver_attribute *dattr = attr_to_driver_attribute(attr); | 337 | struct driver_attribute *dattr = attr_to_driver_attribute(attr); |
338 | ssize_t ret = 0; | 338 | ssize_t ret; |
339 | 339 | ||
340 | if (get_driver(driver)) { | 340 | if (!get_driver(driver)) |
341 | if (dattr->show) | 341 | return -ENODEV; |
342 | ret = dattr->show(driver, buf); | 342 | |
343 | put_driver(driver); | 343 | ret = dattr->show ? dattr->show(driver, buf) : -EIO; |
344 | } | 344 | |
345 | put_driver(driver); | ||
345 | return ret; | 346 | return ret; |
346 | } | 347 | } |
347 | 348 | ||
@@ -351,13 +352,14 @@ pci_driver_attr_store(struct kobject * kobj, struct attribute *attr, | |||
351 | { | 352 | { |
352 | struct device_driver *driver = kobj_to_pci_driver(kobj); | 353 | struct device_driver *driver = kobj_to_pci_driver(kobj); |
353 | struct driver_attribute *dattr = attr_to_driver_attribute(attr); | 354 | struct driver_attribute *dattr = attr_to_driver_attribute(attr); |
354 | ssize_t ret = 0; | 355 | ssize_t ret; |
355 | 356 | ||
356 | if (get_driver(driver)) { | 357 | if (!get_driver(driver)) |
357 | if (dattr->store) | 358 | return -ENODEV; |
358 | ret = dattr->store(driver, buf, count); | 359 | |
359 | put_driver(driver); | 360 | ret = dattr->store ? dattr->store(driver, buf, count) : -EIO; |
360 | } | 361 | |
362 | put_driver(driver); | ||
361 | return ret; | 363 | return ret; |
362 | } | 364 | } |
363 | 365 | ||
@@ -393,7 +395,10 @@ int pci_register_driver(struct pci_driver *drv) | |||
393 | drv->driver.bus = &pci_bus_type; | 395 | drv->driver.bus = &pci_bus_type; |
394 | drv->driver.probe = pci_device_probe; | 396 | drv->driver.probe = pci_device_probe; |
395 | drv->driver.remove = pci_device_remove; | 397 | drv->driver.remove = pci_device_remove; |
396 | drv->driver.shutdown = pci_device_shutdown, | 398 | /* FIXME, once all of the existing PCI drivers have been fixed to set |
399 | * the pci shutdown function, this test can go away. */ | ||
400 | if (!drv->driver.shutdown) | ||
401 | drv->driver.shutdown = pci_device_shutdown; | ||
397 | drv->driver.owner = drv->owner; | 402 | drv->driver.owner = drv->owner; |
398 | drv->driver.kobj.ktype = &pci_driver_kobj_type; | 403 | drv->driver.kobj.ktype = &pci_driver_kobj_type; |
399 | pci_init_dynids(&drv->dynids); | 404 | pci_init_dynids(&drv->dynids); |
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 6ca0061137a6..a15f94072a6f 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -29,7 +29,7 @@ static int sysfs_initialized; /* = 0 */ | |||
29 | /* show configuration fields */ | 29 | /* show configuration fields */ |
30 | #define pci_config_attr(field, format_string) \ | 30 | #define pci_config_attr(field, format_string) \ |
31 | static ssize_t \ | 31 | static ssize_t \ |
32 | field##_show(struct device *dev, char *buf) \ | 32 | field##_show(struct device *dev, struct device_attribute *attr, char *buf) \ |
33 | { \ | 33 | { \ |
34 | struct pci_dev *pdev; \ | 34 | struct pci_dev *pdev; \ |
35 | \ | 35 | \ |
@@ -44,7 +44,7 @@ pci_config_attr(subsystem_device, "0x%04x\n"); | |||
44 | pci_config_attr(class, "0x%06x\n"); | 44 | pci_config_attr(class, "0x%06x\n"); |
45 | pci_config_attr(irq, "%u\n"); | 45 | pci_config_attr(irq, "%u\n"); |
46 | 46 | ||
47 | static ssize_t local_cpus_show(struct device *dev, char *buf) | 47 | static ssize_t local_cpus_show(struct device *dev, struct device_attribute *attr, char *buf) |
48 | { | 48 | { |
49 | cpumask_t mask = pcibus_to_cpumask(to_pci_dev(dev)->bus); | 49 | cpumask_t mask = pcibus_to_cpumask(to_pci_dev(dev)->bus); |
50 | int len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask); | 50 | int len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask); |
@@ -54,7 +54,7 @@ static ssize_t local_cpus_show(struct device *dev, char *buf) | |||
54 | 54 | ||
55 | /* show resources */ | 55 | /* show resources */ |
56 | static ssize_t | 56 | static ssize_t |
57 | resource_show(struct device * dev, char * buf) | 57 | resource_show(struct device * dev, struct device_attribute *attr, char * buf) |
58 | { | 58 | { |
59 | struct pci_dev * pci_dev = to_pci_dev(dev); | 59 | struct pci_dev * pci_dev = to_pci_dev(dev); |
60 | char * str = buf; | 60 | char * str = buf; |
@@ -73,7 +73,7 @@ resource_show(struct device * dev, char * buf) | |||
73 | return (str - buf); | 73 | return (str - buf); |
74 | } | 74 | } |
75 | 75 | ||
76 | static ssize_t modalias_show(struct device *dev, char *buf) | 76 | static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) |
77 | { | 77 | { |
78 | struct pci_dev *pci_dev = to_pci_dev(dev); | 78 | struct pci_dev *pci_dev = to_pci_dev(dev); |
79 | 79 | ||
@@ -339,16 +339,17 @@ pci_create_resource_files(struct pci_dev *pdev) | |||
339 | if (!pci_resource_len(pdev, i)) | 339 | if (!pci_resource_len(pdev, i)) |
340 | continue; | 340 | continue; |
341 | 341 | ||
342 | res_attr = kmalloc(sizeof(*res_attr) + 10, GFP_ATOMIC); | 342 | /* allocate attribute structure, piggyback attribute name */ |
343 | res_attr = kcalloc(1, sizeof(*res_attr) + 10, GFP_ATOMIC); | ||
343 | if (res_attr) { | 344 | if (res_attr) { |
344 | memset(res_attr, 0, sizeof(*res_attr) + 10); | 345 | char *res_attr_name = (char *)(res_attr + 1); |
346 | |||
345 | pdev->res_attr[i] = res_attr; | 347 | pdev->res_attr[i] = res_attr; |
346 | /* Allocated above after the res_attr struct */ | 348 | sprintf(res_attr_name, "resource%d", i); |
347 | res_attr->attr.name = (char *)(res_attr + 1); | 349 | res_attr->attr.name = res_attr_name; |
348 | sprintf(res_attr->attr.name, "resource%d", i); | ||
349 | res_attr->size = pci_resource_len(pdev, i); | ||
350 | res_attr->attr.mode = S_IRUSR | S_IWUSR; | 350 | res_attr->attr.mode = S_IRUSR | S_IWUSR; |
351 | res_attr->attr.owner = THIS_MODULE; | 351 | res_attr->attr.owner = THIS_MODULE; |
352 | res_attr->size = pci_resource_len(pdev, i); | ||
352 | res_attr->mmap = pci_mmap_resource; | 353 | res_attr->mmap = pci_mmap_resource; |
353 | res_attr->private = &pdev->resource[i]; | 354 | res_attr->private = &pdev->resource[i]; |
354 | sysfs_create_bin_file(&pdev->dev.kobj, res_attr); | 355 | sysfs_create_bin_file(&pdev->dev.kobj, res_attr); |
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 576285765e98..f5c5f10a3d2f 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c | |||
@@ -232,19 +232,16 @@ static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev, | |||
232 | /* Initialize generic device interface */ | 232 | /* Initialize generic device interface */ |
233 | device = &dev->device; | 233 | device = &dev->device; |
234 | memset(device, 0, sizeof(struct device)); | 234 | memset(device, 0, sizeof(struct device)); |
235 | INIT_LIST_HEAD(&device->node); | ||
236 | INIT_LIST_HEAD(&device->children); | ||
237 | INIT_LIST_HEAD(&device->bus_list); | ||
238 | device->bus = &pcie_port_bus_type; | 235 | device->bus = &pcie_port_bus_type; |
239 | device->driver = NULL; | 236 | device->driver = NULL; |
240 | device->driver_data = NULL; | 237 | device->driver_data = NULL; |
241 | device->release = release_pcie_device; /* callback to free pcie dev */ | 238 | device->release = release_pcie_device; /* callback to free pcie dev */ |
242 | sprintf(&device->bus_id[0], "pcie%02x", | 239 | sprintf(&device->bus_id[0], "pcie%02x", |
243 | get_descriptor_id(port_type, service_type)); | 240 | get_descriptor_id(port_type, service_type)); |
244 | device->parent = &parent->dev; | 241 | device->parent = &parent->dev; |
245 | } | 242 | } |
246 | 243 | ||
247 | static struct pcie_device* alloc_pcie_device(struct pci_dev *parent, | 244 | static struct pcie_device* alloc_pcie_device(struct pci_dev *parent, |
248 | int port_type, int service_type, int irq, int irq_mode) | 245 | int port_type, int service_type, int irq, int irq_mode) |
249 | { | 246 | { |
250 | struct pcie_device *device; | 247 | struct pcie_device *device; |
@@ -270,9 +267,9 @@ int pcie_port_device_probe(struct pci_dev *dev) | |||
270 | pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, ®); | 267 | pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, ®); |
271 | type = (reg >> 4) & PORT_TYPE_MASK; | 268 | type = (reg >> 4) & PORT_TYPE_MASK; |
272 | if ( type == PCIE_RC_PORT || type == PCIE_SW_UPSTREAM_PORT || | 269 | if ( type == PCIE_RC_PORT || type == PCIE_SW_UPSTREAM_PORT || |
273 | type == PCIE_SW_DOWNSTREAM_PORT ) | 270 | type == PCIE_SW_DOWNSTREAM_PORT ) |
274 | return 0; | 271 | return 0; |
275 | 272 | ||
276 | return -ENODEV; | 273 | return -ENODEV; |
277 | } | 274 | } |
278 | 275 | ||
@@ -283,8 +280,8 @@ int pcie_port_device_register(struct pci_dev *dev) | |||
283 | u16 reg16; | 280 | u16 reg16; |
284 | 281 | ||
285 | /* Get port type */ | 282 | /* Get port type */ |
286 | pci_read_config_word(dev, | 283 | pci_read_config_word(dev, |
287 | pci_find_capability(dev, PCI_CAP_ID_EXP) + | 284 | pci_find_capability(dev, PCI_CAP_ID_EXP) + |
288 | PCIE_CAPABILITIES_REG, ®16); | 285 | PCIE_CAPABILITIES_REG, ®16); |
289 | type = (reg16 >> 4) & PORT_TYPE_MASK; | 286 | type = (reg16 >> 4) & PORT_TYPE_MASK; |
290 | 287 | ||
@@ -299,11 +296,11 @@ int pcie_port_device_register(struct pci_dev *dev) | |||
299 | if (capabilities & (1 << i)) { | 296 | if (capabilities & (1 << i)) { |
300 | child = alloc_pcie_device( | 297 | child = alloc_pcie_device( |
301 | dev, /* parent */ | 298 | dev, /* parent */ |
302 | type, /* port type */ | 299 | type, /* port type */ |
303 | i, /* service type */ | 300 | i, /* service type */ |
304 | vectors[i], /* irq */ | 301 | vectors[i], /* irq */ |
305 | irq_mode /* interrupt mode */); | 302 | irq_mode /* interrupt mode */); |
306 | if (child) { | 303 | if (child) { |
307 | status = device_register(&child->device); | 304 | status = device_register(&child->device); |
308 | if (status) { | 305 | if (status) { |
309 | kfree(child); | 306 | kfree(child); |
@@ -317,84 +314,78 @@ int pcie_port_device_register(struct pci_dev *dev) | |||
317 | } | 314 | } |
318 | 315 | ||
319 | #ifdef CONFIG_PM | 316 | #ifdef CONFIG_PM |
320 | int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state) | 317 | static int suspend_iter(struct device *dev, void *data) |
321 | { | 318 | { |
322 | struct list_head *head, *tmp; | ||
323 | struct device *parent, *child; | ||
324 | struct device_driver *driver; | ||
325 | struct pcie_port_service_driver *service_driver; | 319 | struct pcie_port_service_driver *service_driver; |
320 | u32 state = (u32)data; | ||
321 | |||
322 | if ((dev->bus == &pcie_port_bus_type) && | ||
323 | (dev->driver)) { | ||
324 | service_driver = to_service_driver(dev->driver); | ||
325 | if (service_driver->suspend) | ||
326 | service_driver->suspend(to_pcie_device(dev), state); | ||
327 | } | ||
328 | return 0; | ||
329 | } | ||
326 | 330 | ||
327 | parent = &dev->dev; | 331 | int pcie_port_device_suspend(struct pci_dev *dev, u32 state) |
328 | head = &parent->children; | 332 | { |
329 | tmp = head->next; | 333 | device_for_each_child(&dev->dev, (void *)state, suspend_iter); |
330 | while (head != tmp) { | 334 | return 0; |
331 | child = container_of(tmp, struct device, node); | ||
332 | tmp = tmp->next; | ||
333 | if (child->bus != &pcie_port_bus_type) | ||
334 | continue; | ||
335 | driver = child->driver; | ||
336 | if (!driver) | ||
337 | continue; | ||
338 | service_driver = to_service_driver(driver); | ||
339 | if (service_driver->suspend) | ||
340 | service_driver->suspend(to_pcie_device(child), state); | ||
341 | } | ||
342 | return 0; | ||
343 | } | 335 | } |
344 | 336 | ||
345 | int pcie_port_device_resume(struct pci_dev *dev) | 337 | static int resume_iter(struct device *dev, void *data) |
346 | { | 338 | { |
347 | struct list_head *head, *tmp; | ||
348 | struct device *parent, *child; | ||
349 | struct device_driver *driver; | ||
350 | struct pcie_port_service_driver *service_driver; | 339 | struct pcie_port_service_driver *service_driver; |
351 | 340 | ||
352 | parent = &dev->dev; | 341 | if ((dev->bus == &pcie_port_bus_type) && |
353 | head = &parent->children; | 342 | (dev->driver)) { |
354 | tmp = head->next; | 343 | service_driver = to_service_driver(dev->driver); |
355 | while (head != tmp) { | 344 | if (service_driver->resume) |
356 | child = container_of(tmp, struct device, node); | 345 | service_driver->resume(to_pcie_device(dev)); |
357 | tmp = tmp->next; | ||
358 | if (child->bus != &pcie_port_bus_type) | ||
359 | continue; | ||
360 | driver = child->driver; | ||
361 | if (!driver) | ||
362 | continue; | ||
363 | service_driver = to_service_driver(driver); | ||
364 | if (service_driver->resume) | ||
365 | service_driver->resume(to_pcie_device(child)); | ||
366 | } | 346 | } |
367 | return 0; | 347 | return 0; |
348 | } | ||
368 | 349 | ||
350 | int pcie_port_device_resume(struct pci_dev *dev) | ||
351 | { | ||
352 | device_for_each_child(&dev->dev, NULL, resume_iter); | ||
353 | return 0; | ||
369 | } | 354 | } |
370 | #endif | 355 | #endif |
371 | 356 | ||
372 | void pcie_port_device_remove(struct pci_dev *dev) | 357 | static int remove_iter(struct device *dev, void *data) |
373 | { | 358 | { |
374 | struct list_head *head, *tmp; | ||
375 | struct device *parent, *child; | ||
376 | struct device_driver *driver; | ||
377 | struct pcie_port_service_driver *service_driver; | 359 | struct pcie_port_service_driver *service_driver; |
378 | int interrupt_mode = PCIE_PORT_INTx_MODE; | ||
379 | 360 | ||
380 | parent = &dev->dev; | 361 | if (dev->bus == &pcie_port_bus_type) { |
381 | head = &parent->children; | 362 | if (dev->driver) { |
382 | tmp = head->next; | 363 | service_driver = to_service_driver(dev->driver); |
383 | while (head != tmp) { | 364 | if (service_driver->remove) |
384 | child = container_of(tmp, struct device, node); | 365 | service_driver->remove(to_pcie_device(dev)); |
385 | tmp = tmp->next; | ||
386 | if (child->bus != &pcie_port_bus_type) | ||
387 | continue; | ||
388 | driver = child->driver; | ||
389 | if (driver) { | ||
390 | service_driver = to_service_driver(driver); | ||
391 | if (service_driver->remove) | ||
392 | service_driver->remove(to_pcie_device(child)); | ||
393 | } | 366 | } |
394 | interrupt_mode = (to_pcie_device(child))->interrupt_mode; | 367 | *(unsigned long*)data = (unsigned long)dev; |
395 | put_device(child); | 368 | return 1; |
396 | device_unregister(child); | ||
397 | } | 369 | } |
370 | return 0; | ||
371 | } | ||
372 | |||
373 | void pcie_port_device_remove(struct pci_dev *dev) | ||
374 | { | ||
375 | struct device *device; | ||
376 | unsigned long device_addr; | ||
377 | int interrupt_mode = PCIE_PORT_INTx_MODE; | ||
378 | int status; | ||
379 | |||
380 | do { | ||
381 | status = device_for_each_child(&dev->dev, &device_addr, remove_iter); | ||
382 | if (status) { | ||
383 | device = (struct device*)device_addr; | ||
384 | interrupt_mode = (to_pcie_device(device))->interrupt_mode; | ||
385 | put_device(device); | ||
386 | device_unregister(device); | ||
387 | } | ||
388 | } while (status); | ||
398 | /* Switch to INTx by default if MSI enabled */ | 389 | /* Switch to INTx by default if MSI enabled */ |
399 | if (interrupt_mode == PCIE_PORT_MSIX_MODE) | 390 | if (interrupt_mode == PCIE_PORT_MSIX_MODE) |
400 | pci_disable_msix(dev); | 391 | pci_disable_msix(dev); |
@@ -423,7 +414,7 @@ int pcie_port_service_register(struct pcie_port_service_driver *new) | |||
423 | new->driver.resume = pcie_port_resume_service; | 414 | new->driver.resume = pcie_port_resume_service; |
424 | 415 | ||
425 | return driver_register(&new->driver); | 416 | return driver_register(&new->driver); |
426 | } | 417 | } |
427 | 418 | ||
428 | void pcie_port_service_unregister(struct pcie_port_service_driver *new) | 419 | void pcie_port_service_unregister(struct pcie_port_service_driver *new) |
429 | { | 420 | { |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index b7ae87823c69..fd48b201eb53 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -125,7 +125,7 @@ static inline unsigned int pci_calc_resource_flags(unsigned int flags) | |||
125 | /* | 125 | /* |
126 | * Find the extent of a PCI decode.. | 126 | * Find the extent of a PCI decode.. |
127 | */ | 127 | */ |
128 | static u32 pci_size(u32 base, u32 maxbase, unsigned long mask) | 128 | static u32 pci_size(u32 base, u32 maxbase, u32 mask) |
129 | { | 129 | { |
130 | u32 size = mask & maxbase; /* Find the significant bits */ | 130 | u32 size = mask & maxbase; /* Find the significant bits */ |
131 | if (!size) | 131 | if (!size) |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 2194669300bf..968033fd29f0 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -456,6 +456,12 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) | |||
456 | } | 456 | } |
457 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC, quirk_amd_8131_ioapic ); | 457 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC, quirk_amd_8131_ioapic ); |
458 | 458 | ||
459 | static void __init quirk_svw_msi(struct pci_dev *dev) | ||
460 | { | ||
461 | pci_msi_quirk = 1; | ||
462 | printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n"); | ||
463 | } | ||
464 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_svw_msi ); | ||
459 | #endif /* CONFIG_X86_IO_APIC */ | 465 | #endif /* CONFIG_X86_IO_APIC */ |
460 | 466 | ||
461 | 467 | ||