diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-06 14:44:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-06 14:44:36 -0400 |
commit | 1cfd2bda8c486ae0e7a8005354758ebb68172bca (patch) | |
tree | 76ce15f377d8d6eb3ae4aa8b8b0b415457e38d36 /drivers/pci | |
parent | b57bdda58cda0aaf6def042d101dd85977a286ed (diff) | |
parent | 763e9db9994e27a7d2cb3701c8a097a867d0e0b4 (diff) |
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (30 commits)
PCI: update for owner removal from struct device_attribute
PCI: Fix warnings when CONFIG_DMI unset
PCI: Do not run NVidia quirks related to MSI with MSI disabled
x86/PCI: use for_each_pci_dev()
PCI: use for_each_pci_dev()
PCI: MSI: Restore read_msi_msg_desc(); add get_cached_msi_msg_desc()
PCI: export SMBIOS provided firmware instance and label to sysfs
PCI: Allow read/write access to sysfs I/O port resources
x86/PCI: use host bridge _CRS info on ASRock ALiveSATA2-GLAN
PCI: remove unused HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_{SIZE|BOUNDARY}
PCI: disable mmio during bar sizing
PCI: MSI: Remove unsafe and unnecessary hardware access
PCI: Default PCIe ASPM control to on and require !EMBEDDED to disable
PCI: kernel oops on access to pci proc file while hot-removal
PCI: pci-sysfs: remove casts from void*
ACPI: Disable ASPM if the platform won't provide _OSC control for PCIe
PCI hotplug: make sure child bridges are enabled at hotplug time
PCI hotplug: shpchp: Removed check for hotplug of display devices
PCI hotplug: pciehp: Fixed return value sign for pciehp_unconfigure_device
PCI: Don't enable aspm before drivers have had a chance to veto it
...
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/Makefile | 3 | ||||
-rw-r--r-- | drivers/pci/bus.c | 4 | ||||
-rw-r--r-- | drivers/pci/hotplug/fakephp.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_pci.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_hpc.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_pci.c | 19 | ||||
-rw-r--r-- | drivers/pci/msi.c | 29 | ||||
-rw-r--r-- | drivers/pci/pci-driver.c | 32 | ||||
-rw-r--r-- | drivers/pci/pci-label.c | 143 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 75 | ||||
-rw-r--r-- | drivers/pci/pci.c | 4 | ||||
-rw-r--r-- | drivers/pci/pci.h | 9 | ||||
-rw-r--r-- | drivers/pci/pcie/Kconfig | 20 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv_core.c | 17 | ||||
-rw-r--r-- | drivers/pci/pcie/aspm.c | 16 | ||||
-rw-r--r-- | drivers/pci/probe.c | 10 | ||||
-rw-r--r-- | drivers/pci/proc.c | 6 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 42 | ||||
-rw-r--r-- | drivers/pci/search.c | 2 | ||||
-rw-r--r-- | drivers/pci/setup-bus.c | 12 | ||||
-rw-r--r-- | drivers/pci/setup-irq.c | 3 |
21 files changed, 391 insertions, 61 deletions
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 0b51857fbaf7..dc1aa0922868 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile | |||
@@ -55,6 +55,9 @@ obj-$(CONFIG_MICROBLAZE) += setup-bus.o | |||
55 | # | 55 | # |
56 | obj-$(CONFIG_ACPI) += pci-acpi.o | 56 | obj-$(CONFIG_ACPI) += pci-acpi.o |
57 | 57 | ||
58 | # SMBIOS provided firmware instance and labels | ||
59 | obj-$(CONFIG_DMI) += pci-label.o | ||
60 | |||
58 | # Cardbus & CompactPCI use setup-bus | 61 | # Cardbus & CompactPCI use setup-bus |
59 | obj-$(CONFIG_HOTPLUG) += setup-bus.o | 62 | obj-$(CONFIG_HOTPLUG) += setup-bus.o |
60 | 63 | ||
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 628ea20a8841..7f0af0e9b826 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c | |||
@@ -56,7 +56,7 @@ void pci_bus_remove_resources(struct pci_bus *bus) | |||
56 | int i; | 56 | int i; |
57 | 57 | ||
58 | for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) | 58 | for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) |
59 | bus->resource[i] = 0; | 59 | bus->resource[i] = NULL; |
60 | 60 | ||
61 | list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) { | 61 | list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) { |
62 | list_del(&bus_res->list); | 62 | list_del(&bus_res->list); |
@@ -240,6 +240,8 @@ void pci_enable_bridges(struct pci_bus *bus) | |||
240 | if (dev->subordinate) { | 240 | if (dev->subordinate) { |
241 | if (!pci_is_enabled(dev)) { | 241 | if (!pci_is_enabled(dev)) { |
242 | retval = pci_enable_device(dev); | 242 | retval = pci_enable_device(dev); |
243 | if (retval) | ||
244 | dev_err(&dev->dev, "Error enabling bridge (%d), continuing\n", retval); | ||
243 | pci_set_master(dev); | 245 | pci_set_master(dev); |
244 | } | 246 | } |
245 | pci_enable_bridges(dev->subordinate); | 247 | pci_enable_bridges(dev->subordinate); |
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 5317e4d7d96e..17d10e2e8fb6 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c | |||
@@ -135,7 +135,7 @@ static int __init init_legacy(void) | |||
135 | struct pci_dev *pdev = NULL; | 135 | struct pci_dev *pdev = NULL; |
136 | 136 | ||
137 | /* Add existing devices */ | 137 | /* Add existing devices */ |
138 | while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) | 138 | for_each_pci_dev(pdev) |
139 | legacy_add_slot(pdev); | 139 | legacy_add_slot(pdev); |
140 | 140 | ||
141 | /* Be alerted of any new ones */ | 141 | /* Be alerted of any new ones */ |
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 2fce726758d2..a4031dfe938e 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c | |||
@@ -137,7 +137,7 @@ int pciehp_unconfigure_device(struct slot *p_slot) | |||
137 | "Cannot remove display device %s\n", | 137 | "Cannot remove display device %s\n", |
138 | pci_name(temp)); | 138 | pci_name(temp)); |
139 | pci_dev_put(temp); | 139 | pci_dev_put(temp); |
140 | rc = EINVAL; | 140 | rc = -EINVAL; |
141 | break; | 141 | break; |
142 | } | 142 | } |
143 | } | 143 | } |
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 5f5e8d2e3552..d3985e7deab7 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
@@ -113,7 +113,7 @@ | |||
113 | #define CON_PFAULT_INTR_MASK (1 << 28) | 113 | #define CON_PFAULT_INTR_MASK (1 << 28) |
114 | #define MRL_CHANGE_SERR_MASK (1 << 29) | 114 | #define MRL_CHANGE_SERR_MASK (1 << 29) |
115 | #define CON_PFAULT_SERR_MASK (1 << 30) | 115 | #define CON_PFAULT_SERR_MASK (1 << 30) |
116 | #define SLOT_REG_RSVDZ_MASK (1 << 15) | (7 << 21) | 116 | #define SLOT_REG_RSVDZ_MASK ((1 << 15) | (7 << 21)) |
117 | 117 | ||
118 | /* | 118 | /* |
119 | * SHPC Command Code definitnions | 119 | * SHPC Command Code definitnions |
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index 8c3d3219f227..a2ccfcd3c298 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c | |||
@@ -60,12 +60,6 @@ int __ref shpchp_configure_device(struct slot *p_slot) | |||
60 | dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn)); | 60 | dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn)); |
61 | if (!dev) | 61 | if (!dev) |
62 | continue; | 62 | continue; |
63 | if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | ||
64 | ctrl_err(ctrl, "Cannot hot-add display device %s\n", | ||
65 | pci_name(dev)); | ||
66 | pci_dev_put(dev); | ||
67 | continue; | ||
68 | } | ||
69 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || | 63 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || |
70 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { | 64 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { |
71 | /* Find an unused bus number for the new bridge */ | 65 | /* Find an unused bus number for the new bridge */ |
@@ -114,17 +108,11 @@ int shpchp_unconfigure_device(struct slot *p_slot) | |||
114 | ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", | 108 | ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", |
115 | __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); | 109 | __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); |
116 | 110 | ||
117 | for (j=0; j<8 ; j++) { | 111 | for (j = 0; j < 8 ; j++) { |
118 | struct pci_dev* temp = pci_get_slot(parent, | 112 | struct pci_dev *temp = pci_get_slot(parent, |
119 | (p_slot->device << 3) | j); | 113 | (p_slot->device << 3) | j); |
120 | if (!temp) | 114 | if (!temp) |
121 | continue; | 115 | continue; |
122 | if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | ||
123 | ctrl_err(ctrl, "Cannot remove display device %s\n", | ||
124 | pci_name(temp)); | ||
125 | pci_dev_put(temp); | ||
126 | continue; | ||
127 | } | ||
128 | if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | 116 | if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { |
129 | pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); | 117 | pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); |
130 | if (bctl & PCI_BRIDGE_CTL_VGA) { | 118 | if (bctl & PCI_BRIDGE_CTL_VGA) { |
@@ -132,7 +120,8 @@ int shpchp_unconfigure_device(struct slot *p_slot) | |||
132 | "Cannot remove display device %s\n", | 120 | "Cannot remove display device %s\n", |
133 | pci_name(temp)); | 121 | pci_name(temp)); |
134 | pci_dev_put(temp); | 122 | pci_dev_put(temp); |
135 | continue; | 123 | rc = -EINVAL; |
124 | break; | ||
136 | } | 125 | } |
137 | } | 126 | } |
138 | pci_remove_bus_device(temp); | 127 | pci_remove_bus_device(temp); |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 77b68eaf021e..69b7be33b3a2 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -196,6 +196,9 @@ void unmask_msi_irq(unsigned int irq) | |||
196 | void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | 196 | void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) |
197 | { | 197 | { |
198 | struct msi_desc *entry = get_irq_desc_msi(desc); | 198 | struct msi_desc *entry = get_irq_desc_msi(desc); |
199 | |||
200 | BUG_ON(entry->dev->current_state != PCI_D0); | ||
201 | |||
199 | if (entry->msi_attrib.is_msix) { | 202 | if (entry->msi_attrib.is_msix) { |
200 | void __iomem *base = entry->mask_base + | 203 | void __iomem *base = entry->mask_base + |
201 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; | 204 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; |
@@ -229,10 +232,32 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg) | |||
229 | read_msi_msg_desc(desc, msg); | 232 | read_msi_msg_desc(desc, msg); |
230 | } | 233 | } |
231 | 234 | ||
235 | void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | ||
236 | { | ||
237 | struct msi_desc *entry = get_irq_desc_msi(desc); | ||
238 | |||
239 | /* Assert that the cache is valid, assuming that | ||
240 | * valid messages are not all-zeroes. */ | ||
241 | BUG_ON(!(entry->msg.address_hi | entry->msg.address_lo | | ||
242 | entry->msg.data)); | ||
243 | |||
244 | *msg = entry->msg; | ||
245 | } | ||
246 | |||
247 | void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg) | ||
248 | { | ||
249 | struct irq_desc *desc = irq_to_desc(irq); | ||
250 | |||
251 | get_cached_msi_msg_desc(desc, msg); | ||
252 | } | ||
253 | |||
232 | void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | 254 | void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) |
233 | { | 255 | { |
234 | struct msi_desc *entry = get_irq_desc_msi(desc); | 256 | struct msi_desc *entry = get_irq_desc_msi(desc); |
235 | if (entry->msi_attrib.is_msix) { | 257 | |
258 | if (entry->dev->current_state != PCI_D0) { | ||
259 | /* Don't touch the hardware now */ | ||
260 | } else if (entry->msi_attrib.is_msix) { | ||
236 | void __iomem *base; | 261 | void __iomem *base; |
237 | base = entry->mask_base + | 262 | base = entry->mask_base + |
238 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; | 263 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; |
@@ -435,7 +460,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) | |||
435 | static void __iomem *msix_map_region(struct pci_dev *dev, unsigned pos, | 460 | static void __iomem *msix_map_region(struct pci_dev *dev, unsigned pos, |
436 | unsigned nr_entries) | 461 | unsigned nr_entries) |
437 | { | 462 | { |
438 | unsigned long phys_addr; | 463 | resource_size_t phys_addr; |
439 | u32 table_offset; | 464 | u32 table_offset; |
440 | u8 bir; | 465 | u8 bir; |
441 | 466 | ||
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index f9a0aec3abcf..8a6f797de8e5 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -289,8 +289,26 @@ struct drv_dev_and_id { | |||
289 | static long local_pci_probe(void *_ddi) | 289 | static long local_pci_probe(void *_ddi) |
290 | { | 290 | { |
291 | struct drv_dev_and_id *ddi = _ddi; | 291 | struct drv_dev_and_id *ddi = _ddi; |
292 | 292 | struct device *dev = &ddi->dev->dev; | |
293 | return ddi->drv->probe(ddi->dev, ddi->id); | 293 | int rc; |
294 | |||
295 | /* Unbound PCI devices are always set to disabled and suspended. | ||
296 | * During probe, the device is set to enabled and active and the | ||
297 | * usage count is incremented. If the driver supports runtime PM, | ||
298 | * it should call pm_runtime_put_noidle() in its probe routine and | ||
299 | * pm_runtime_get_noresume() in its remove routine. | ||
300 | */ | ||
301 | pm_runtime_get_noresume(dev); | ||
302 | pm_runtime_set_active(dev); | ||
303 | pm_runtime_enable(dev); | ||
304 | |||
305 | rc = ddi->drv->probe(ddi->dev, ddi->id); | ||
306 | if (rc) { | ||
307 | pm_runtime_disable(dev); | ||
308 | pm_runtime_set_suspended(dev); | ||
309 | pm_runtime_put_noidle(dev); | ||
310 | } | ||
311 | return rc; | ||
294 | } | 312 | } |
295 | 313 | ||
296 | static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, | 314 | static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, |
@@ -369,11 +387,19 @@ static int pci_device_remove(struct device * dev) | |||
369 | struct pci_driver * drv = pci_dev->driver; | 387 | struct pci_driver * drv = pci_dev->driver; |
370 | 388 | ||
371 | if (drv) { | 389 | if (drv) { |
372 | if (drv->remove) | 390 | if (drv->remove) { |
391 | pm_runtime_get_sync(dev); | ||
373 | drv->remove(pci_dev); | 392 | drv->remove(pci_dev); |
393 | pm_runtime_put_noidle(dev); | ||
394 | } | ||
374 | pci_dev->driver = NULL; | 395 | pci_dev->driver = NULL; |
375 | } | 396 | } |
376 | 397 | ||
398 | /* Undo the runtime PM settings in local_pci_probe() */ | ||
399 | pm_runtime_disable(dev); | ||
400 | pm_runtime_set_suspended(dev); | ||
401 | pm_runtime_put_noidle(dev); | ||
402 | |||
377 | /* | 403 | /* |
378 | * If the device is still on, set the power state as "unknown", | 404 | * If the device is still on, set the power state as "unknown", |
379 | * since it might change by the next time we load the driver. | 405 | * since it might change by the next time we load the driver. |
diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c new file mode 100644 index 000000000000..90c0a729cd3a --- /dev/null +++ b/drivers/pci/pci-label.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * Purpose: Export the firmware instance and label associated with | ||
3 | * a pci device to sysfs | ||
4 | * Copyright (C) 2010 Dell Inc. | ||
5 | * by Narendra K <Narendra_K@dell.com>, | ||
6 | * Jordan Hargrave <Jordan_Hargrave@dell.com> | ||
7 | * | ||
8 | * SMBIOS defines type 41 for onboard pci devices. This code retrieves | ||
9 | * the instance number and string from the type 41 record and exports | ||
10 | * it to sysfs. | ||
11 | * | ||
12 | * Please see http://linux.dell.com/wiki/index.php/Oss/libnetdevname for more | ||
13 | * information. | ||
14 | */ | ||
15 | |||
16 | #include <linux/dmi.h> | ||
17 | #include <linux/sysfs.h> | ||
18 | #include <linux/pci.h> | ||
19 | #include <linux/pci_ids.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/device.h> | ||
22 | #include "pci.h" | ||
23 | |||
24 | enum smbios_attr_enum { | ||
25 | SMBIOS_ATTR_NONE = 0, | ||
26 | SMBIOS_ATTR_LABEL_SHOW, | ||
27 | SMBIOS_ATTR_INSTANCE_SHOW, | ||
28 | }; | ||
29 | |||
30 | static mode_t | ||
31 | find_smbios_instance_string(struct pci_dev *pdev, char *buf, | ||
32 | enum smbios_attr_enum attribute) | ||
33 | { | ||
34 | const struct dmi_device *dmi; | ||
35 | struct dmi_dev_onboard *donboard; | ||
36 | int bus; | ||
37 | int devfn; | ||
38 | |||
39 | bus = pdev->bus->number; | ||
40 | devfn = pdev->devfn; | ||
41 | |||
42 | dmi = NULL; | ||
43 | while ((dmi = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD, | ||
44 | NULL, dmi)) != NULL) { | ||
45 | donboard = dmi->device_data; | ||
46 | if (donboard && donboard->bus == bus && | ||
47 | donboard->devfn == devfn) { | ||
48 | if (buf) { | ||
49 | if (attribute == SMBIOS_ATTR_INSTANCE_SHOW) | ||
50 | return scnprintf(buf, PAGE_SIZE, | ||
51 | "%d\n", | ||
52 | donboard->instance); | ||
53 | else if (attribute == SMBIOS_ATTR_LABEL_SHOW) | ||
54 | return scnprintf(buf, PAGE_SIZE, | ||
55 | "%s\n", | ||
56 | dmi->name); | ||
57 | } | ||
58 | return strlen(dmi->name); | ||
59 | } | ||
60 | } | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static mode_t | ||
65 | smbios_instance_string_exist(struct kobject *kobj, struct attribute *attr, | ||
66 | int n) | ||
67 | { | ||
68 | struct device *dev; | ||
69 | struct pci_dev *pdev; | ||
70 | |||
71 | dev = container_of(kobj, struct device, kobj); | ||
72 | pdev = to_pci_dev(dev); | ||
73 | |||
74 | return find_smbios_instance_string(pdev, NULL, SMBIOS_ATTR_NONE) ? | ||
75 | S_IRUGO : 0; | ||
76 | } | ||
77 | |||
78 | static ssize_t | ||
79 | smbioslabel_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
80 | { | ||
81 | struct pci_dev *pdev; | ||
82 | pdev = to_pci_dev(dev); | ||
83 | |||
84 | return find_smbios_instance_string(pdev, buf, | ||
85 | SMBIOS_ATTR_LABEL_SHOW); | ||
86 | } | ||
87 | |||
88 | static ssize_t | ||
89 | smbiosinstance_show(struct device *dev, | ||
90 | struct device_attribute *attr, char *buf) | ||
91 | { | ||
92 | struct pci_dev *pdev; | ||
93 | pdev = to_pci_dev(dev); | ||
94 | |||
95 | return find_smbios_instance_string(pdev, buf, | ||
96 | SMBIOS_ATTR_INSTANCE_SHOW); | ||
97 | } | ||
98 | |||
99 | static struct device_attribute smbios_attr_label = { | ||
100 | .attr = {.name = "label", .mode = 0444}, | ||
101 | .show = smbioslabel_show, | ||
102 | }; | ||
103 | |||
104 | static struct device_attribute smbios_attr_instance = { | ||
105 | .attr = {.name = "index", .mode = 0444}, | ||
106 | .show = smbiosinstance_show, | ||
107 | }; | ||
108 | |||
109 | static struct attribute *smbios_attributes[] = { | ||
110 | &smbios_attr_label.attr, | ||
111 | &smbios_attr_instance.attr, | ||
112 | NULL, | ||
113 | }; | ||
114 | |||
115 | static struct attribute_group smbios_attr_group = { | ||
116 | .attrs = smbios_attributes, | ||
117 | .is_visible = smbios_instance_string_exist, | ||
118 | }; | ||
119 | |||
120 | static int | ||
121 | pci_create_smbiosname_file(struct pci_dev *pdev) | ||
122 | { | ||
123 | if (!sysfs_create_group(&pdev->dev.kobj, &smbios_attr_group)) | ||
124 | return 0; | ||
125 | return -ENODEV; | ||
126 | } | ||
127 | |||
128 | static void | ||
129 | pci_remove_smbiosname_file(struct pci_dev *pdev) | ||
130 | { | ||
131 | sysfs_remove_group(&pdev->dev.kobj, &smbios_attr_group); | ||
132 | } | ||
133 | |||
134 | void pci_create_firmware_label_files(struct pci_dev *pdev) | ||
135 | { | ||
136 | if (!pci_create_smbiosname_file(pdev)) | ||
137 | ; | ||
138 | } | ||
139 | |||
140 | void pci_remove_firmware_label_files(struct pci_dev *pdev) | ||
141 | { | ||
142 | pci_remove_smbiosname_file(pdev); | ||
143 | } | ||
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index c9957f68ac9b..b5a7d9bfcb24 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -734,7 +734,7 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, | |||
734 | { | 734 | { |
735 | struct pci_dev *pdev = to_pci_dev(container_of(kobj, | 735 | struct pci_dev *pdev = to_pci_dev(container_of(kobj, |
736 | struct device, kobj)); | 736 | struct device, kobj)); |
737 | struct resource *res = (struct resource *)attr->private; | 737 | struct resource *res = attr->private; |
738 | enum pci_mmap_state mmap_type; | 738 | enum pci_mmap_state mmap_type; |
739 | resource_size_t start, end; | 739 | resource_size_t start, end; |
740 | int i; | 740 | int i; |
@@ -778,6 +778,70 @@ pci_mmap_resource_wc(struct file *filp, struct kobject *kobj, | |||
778 | return pci_mmap_resource(kobj, attr, vma, 1); | 778 | return pci_mmap_resource(kobj, attr, vma, 1); |
779 | } | 779 | } |
780 | 780 | ||
781 | static ssize_t | ||
782 | pci_resource_io(struct file *filp, struct kobject *kobj, | ||
783 | struct bin_attribute *attr, char *buf, | ||
784 | loff_t off, size_t count, bool write) | ||
785 | { | ||
786 | struct pci_dev *pdev = to_pci_dev(container_of(kobj, | ||
787 | struct device, kobj)); | ||
788 | struct resource *res = attr->private; | ||
789 | unsigned long port = off; | ||
790 | int i; | ||
791 | |||
792 | for (i = 0; i < PCI_ROM_RESOURCE; i++) | ||
793 | if (res == &pdev->resource[i]) | ||
794 | break; | ||
795 | if (i >= PCI_ROM_RESOURCE) | ||
796 | return -ENODEV; | ||
797 | |||
798 | port += pci_resource_start(pdev, i); | ||
799 | |||
800 | if (port > pci_resource_end(pdev, i)) | ||
801 | return 0; | ||
802 | |||
803 | if (port + count - 1 > pci_resource_end(pdev, i)) | ||
804 | return -EINVAL; | ||
805 | |||
806 | switch (count) { | ||
807 | case 1: | ||
808 | if (write) | ||
809 | outb(*(u8 *)buf, port); | ||
810 | else | ||
811 | *(u8 *)buf = inb(port); | ||
812 | return 1; | ||
813 | case 2: | ||
814 | if (write) | ||
815 | outw(*(u16 *)buf, port); | ||
816 | else | ||
817 | *(u16 *)buf = inw(port); | ||
818 | return 2; | ||
819 | case 4: | ||
820 | if (write) | ||
821 | outl(*(u32 *)buf, port); | ||
822 | else | ||
823 | *(u32 *)buf = inl(port); | ||
824 | return 4; | ||
825 | } | ||
826 | return -EINVAL; | ||
827 | } | ||
828 | |||
829 | static ssize_t | ||
830 | pci_read_resource_io(struct file *filp, struct kobject *kobj, | ||
831 | struct bin_attribute *attr, char *buf, | ||
832 | loff_t off, size_t count) | ||
833 | { | ||
834 | return pci_resource_io(filp, kobj, attr, buf, off, count, false); | ||
835 | } | ||
836 | |||
837 | static ssize_t | ||
838 | pci_write_resource_io(struct file *filp, struct kobject *kobj, | ||
839 | struct bin_attribute *attr, char *buf, | ||
840 | loff_t off, size_t count) | ||
841 | { | ||
842 | return pci_resource_io(filp, kobj, attr, buf, off, count, true); | ||
843 | } | ||
844 | |||
781 | /** | 845 | /** |
782 | * pci_remove_resource_files - cleanup resource files | 846 | * pci_remove_resource_files - cleanup resource files |
783 | * @pdev: dev to cleanup | 847 | * @pdev: dev to cleanup |
@@ -828,6 +892,10 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine) | |||
828 | sprintf(res_attr_name, "resource%d", num); | 892 | sprintf(res_attr_name, "resource%d", num); |
829 | res_attr->mmap = pci_mmap_resource_uc; | 893 | res_attr->mmap = pci_mmap_resource_uc; |
830 | } | 894 | } |
895 | if (pci_resource_flags(pdev, num) & IORESOURCE_IO) { | ||
896 | res_attr->read = pci_read_resource_io; | ||
897 | res_attr->write = pci_write_resource_io; | ||
898 | } | ||
831 | res_attr->attr.name = res_attr_name; | 899 | res_attr->attr.name = res_attr_name; |
832 | res_attr->attr.mode = S_IRUSR | S_IWUSR; | 900 | res_attr->attr.mode = S_IRUSR | S_IWUSR; |
833 | res_attr->size = pci_resource_len(pdev, num); | 901 | res_attr->size = pci_resource_len(pdev, num); |
@@ -1097,6 +1165,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) | |||
1097 | if (retval) | 1165 | if (retval) |
1098 | goto err_vga_file; | 1166 | goto err_vga_file; |
1099 | 1167 | ||
1168 | pci_create_firmware_label_files(pdev); | ||
1169 | |||
1100 | return 0; | 1170 | return 0; |
1101 | 1171 | ||
1102 | err_vga_file: | 1172 | err_vga_file: |
@@ -1164,6 +1234,9 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev) | |||
1164 | sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); | 1234 | sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); |
1165 | kfree(pdev->rom_attr); | 1235 | kfree(pdev->rom_attr); |
1166 | } | 1236 | } |
1237 | |||
1238 | pci_remove_firmware_label_files(pdev); | ||
1239 | |||
1167 | } | 1240 | } |
1168 | 1241 | ||
1169 | static int __init pci_sysfs_init(void) | 1242 | static int __init pci_sysfs_init(void) |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 130ed1daf0f8..7fa3cbd742c5 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -2312,21 +2312,17 @@ void pci_msi_off(struct pci_dev *dev) | |||
2312 | } | 2312 | } |
2313 | EXPORT_SYMBOL_GPL(pci_msi_off); | 2313 | EXPORT_SYMBOL_GPL(pci_msi_off); |
2314 | 2314 | ||
2315 | #ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE | ||
2316 | int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size) | 2315 | int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size) |
2317 | { | 2316 | { |
2318 | return dma_set_max_seg_size(&dev->dev, size); | 2317 | return dma_set_max_seg_size(&dev->dev, size); |
2319 | } | 2318 | } |
2320 | EXPORT_SYMBOL(pci_set_dma_max_seg_size); | 2319 | EXPORT_SYMBOL(pci_set_dma_max_seg_size); |
2321 | #endif | ||
2322 | 2320 | ||
2323 | #ifndef HAVE_ARCH_PCI_SET_DMA_SEGMENT_BOUNDARY | ||
2324 | int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask) | 2321 | int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask) |
2325 | { | 2322 | { |
2326 | return dma_set_seg_boundary(&dev->dev, mask); | 2323 | return dma_set_seg_boundary(&dev->dev, mask); |
2327 | } | 2324 | } |
2328 | EXPORT_SYMBOL(pci_set_dma_seg_boundary); | 2325 | EXPORT_SYMBOL(pci_set_dma_seg_boundary); |
2329 | #endif | ||
2330 | 2326 | ||
2331 | static int pcie_flr(struct pci_dev *dev, int probe) | 2327 | static int pcie_flr(struct pci_dev *dev, int probe) |
2332 | { | 2328 | { |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index c8b7fd056ccd..679c39de6a89 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -11,6 +11,15 @@ | |||
11 | extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env); | 11 | extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env); |
12 | extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); | 12 | extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); |
13 | extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev); | 13 | extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev); |
14 | #ifndef CONFIG_DMI | ||
15 | static inline void pci_create_firmware_label_files(struct pci_dev *pdev) | ||
16 | { return; } | ||
17 | static inline void pci_remove_firmware_label_files(struct pci_dev *pdev) | ||
18 | { return; } | ||
19 | #else | ||
20 | extern void pci_create_firmware_label_files(struct pci_dev *pdev); | ||
21 | extern void pci_remove_firmware_label_files(struct pci_dev *pdev); | ||
22 | #endif | ||
14 | extern void pci_cleanup_rom(struct pci_dev *dev); | 23 | extern void pci_cleanup_rom(struct pci_dev *dev); |
15 | #ifdef HAVE_PCI_MMAP | 24 | #ifdef HAVE_PCI_MMAP |
16 | extern int pci_mmap_fits(struct pci_dev *pdev, int resno, | 25 | extern int pci_mmap_fits(struct pci_dev *pdev, int resno, |
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index b8b494b3e0d0..dda70981b7a6 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig | |||
@@ -31,14 +31,22 @@ source "drivers/pci/pcie/aer/Kconfig" | |||
31 | # PCI Express ASPM | 31 | # PCI Express ASPM |
32 | # | 32 | # |
33 | config PCIEASPM | 33 | config PCIEASPM |
34 | bool "PCI Express ASPM support(Experimental)" | 34 | bool "PCI Express ASPM control" if EMBEDDED |
35 | depends on PCI && EXPERIMENTAL && PCIEPORTBUS | 35 | depends on PCI && PCIEPORTBUS |
36 | default n | 36 | default y |
37 | help | 37 | help |
38 | This enables PCI Express ASPM (Active State Power Management) and | 38 | This enables OS control over PCI Express ASPM (Active State |
39 | Clock Power Management. ASPM supports state L0/L0s/L1. | 39 | Power Management) and Clock Power Management. ASPM supports |
40 | state L0/L0s/L1. | ||
40 | 41 | ||
41 | When in doubt, say N. | 42 | ASPM is initially set up the the firmware. With this option enabled, |
43 | Linux can modify this state in order to disable ASPM on known-bad | ||
44 | hardware or configurations and enable it when known-safe. | ||
45 | |||
46 | ASPM can be disabled or enabled at runtime via | ||
47 | /sys/module/pcie_aspm/parameters/policy | ||
48 | |||
49 | When in doubt, say Y. | ||
42 | config PCIEASPM_DEBUG | 50 | config PCIEASPM_DEBUG |
43 | bool "Debug PCI Express ASPM" | 51 | bool "Debug PCI Express ASPM" |
44 | depends on PCIEASPM | 52 | depends on PCIEASPM |
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 8af4f619bba2..fc0b5a93e1de 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
@@ -727,20 +727,21 @@ static void aer_isr_one_error(struct pcie_device *p_device, | |||
727 | static int get_e_source(struct aer_rpc *rpc, struct aer_err_source *e_src) | 727 | static int get_e_source(struct aer_rpc *rpc, struct aer_err_source *e_src) |
728 | { | 728 | { |
729 | unsigned long flags; | 729 | unsigned long flags; |
730 | int ret = 0; | ||
731 | 730 | ||
732 | /* Lock access to Root error producer/consumer index */ | 731 | /* Lock access to Root error producer/consumer index */ |
733 | spin_lock_irqsave(&rpc->e_lock, flags); | 732 | spin_lock_irqsave(&rpc->e_lock, flags); |
734 | if (rpc->prod_idx != rpc->cons_idx) { | 733 | if (rpc->prod_idx == rpc->cons_idx) { |
735 | *e_src = rpc->e_sources[rpc->cons_idx]; | 734 | spin_unlock_irqrestore(&rpc->e_lock, flags); |
736 | rpc->cons_idx++; | 735 | return 0; |
737 | if (rpc->cons_idx == AER_ERROR_SOURCES_MAX) | ||
738 | rpc->cons_idx = 0; | ||
739 | ret = 1; | ||
740 | } | 736 | } |
737 | |||
738 | *e_src = rpc->e_sources[rpc->cons_idx]; | ||
739 | rpc->cons_idx++; | ||
740 | if (rpc->cons_idx == AER_ERROR_SOURCES_MAX) | ||
741 | rpc->cons_idx = 0; | ||
741 | spin_unlock_irqrestore(&rpc->e_lock, flags); | 742 | spin_unlock_irqrestore(&rpc->e_lock, flags); |
742 | 743 | ||
743 | return ret; | 744 | return 1; |
744 | } | 745 | } |
745 | 746 | ||
746 | /** | 747 | /** |
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index be53d98fa384..71222814c1ec 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
@@ -588,11 +588,23 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) | |||
588 | * update through pcie_aspm_cap_init(). | 588 | * update through pcie_aspm_cap_init(). |
589 | */ | 589 | */ |
590 | pcie_aspm_cap_init(link, blacklist); | 590 | pcie_aspm_cap_init(link, blacklist); |
591 | pcie_config_aspm_path(link); | ||
592 | 591 | ||
593 | /* Setup initial Clock PM state */ | 592 | /* Setup initial Clock PM state */ |
594 | pcie_clkpm_cap_init(link, blacklist); | 593 | pcie_clkpm_cap_init(link, blacklist); |
595 | pcie_set_clkpm(link, policy_to_clkpm_state(link)); | 594 | |
595 | /* | ||
596 | * At this stage drivers haven't had an opportunity to change the | ||
597 | * link policy setting. Enabling ASPM on broken hardware can cripple | ||
598 | * it even before the driver has had a chance to disable ASPM, so | ||
599 | * default to a safe level right now. If we're enabling ASPM beyond | ||
600 | * the BIOS's expectation, we'll do so once pci_enable_device() is | ||
601 | * called. | ||
602 | */ | ||
603 | if (aspm_policy != POLICY_POWERSAVE) { | ||
604 | pcie_config_aspm_path(link); | ||
605 | pcie_set_clkpm(link, policy_to_clkpm_state(link)); | ||
606 | } | ||
607 | |||
596 | unlock: | 608 | unlock: |
597 | mutex_unlock(&aspm_lock); | 609 | mutex_unlock(&aspm_lock); |
598 | out: | 610 | out: |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index f4adba2d1dd3..12625d90f8b5 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -163,9 +163,16 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
163 | struct resource *res, unsigned int pos) | 163 | struct resource *res, unsigned int pos) |
164 | { | 164 | { |
165 | u32 l, sz, mask; | 165 | u32 l, sz, mask; |
166 | u16 orig_cmd; | ||
166 | 167 | ||
167 | mask = type ? PCI_ROM_ADDRESS_MASK : ~0; | 168 | mask = type ? PCI_ROM_ADDRESS_MASK : ~0; |
168 | 169 | ||
170 | if (!dev->mmio_always_on) { | ||
171 | pci_read_config_word(dev, PCI_COMMAND, &orig_cmd); | ||
172 | pci_write_config_word(dev, PCI_COMMAND, | ||
173 | orig_cmd & ~(PCI_COMMAND_MEMORY | PCI_COMMAND_IO)); | ||
174 | } | ||
175 | |||
169 | res->name = pci_name(dev); | 176 | res->name = pci_name(dev); |
170 | 177 | ||
171 | pci_read_config_dword(dev, pos, &l); | 178 | pci_read_config_dword(dev, pos, &l); |
@@ -173,6 +180,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
173 | pci_read_config_dword(dev, pos, &sz); | 180 | pci_read_config_dword(dev, pos, &sz); |
174 | pci_write_config_dword(dev, pos, l); | 181 | pci_write_config_dword(dev, pos, l); |
175 | 182 | ||
183 | if (!dev->mmio_always_on) | ||
184 | pci_write_config_word(dev, PCI_COMMAND, orig_cmd); | ||
185 | |||
176 | /* | 186 | /* |
177 | * All bits set in sz means the device isn't working properly. | 187 | * All bits set in sz means the device isn't working properly. |
178 | * If the BAR isn't implemented, all bits must be 0. If it's a | 188 | * If the BAR isn't implemented, all bits must be 0. If it's a |
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 449e890267a2..01f0306525a5 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c | |||
@@ -431,8 +431,6 @@ int pci_proc_detach_device(struct pci_dev *dev) | |||
431 | struct proc_dir_entry *e; | 431 | struct proc_dir_entry *e; |
432 | 432 | ||
433 | if ((e = dev->procent)) { | 433 | if ((e = dev->procent)) { |
434 | if (atomic_read(&e->count) > 1) | ||
435 | return -EBUSY; | ||
436 | remove_proc_entry(e->name, dev->bus->procdir); | 434 | remove_proc_entry(e->name, dev->bus->procdir); |
437 | dev->procent = NULL; | 435 | dev->procent = NULL; |
438 | } | 436 | } |
@@ -485,9 +483,9 @@ static int __init pci_proc_init(void) | |||
485 | proc_create("devices", 0, proc_bus_pci_dir, | 483 | proc_create("devices", 0, proc_bus_pci_dir, |
486 | &proc_bus_pci_dev_operations); | 484 | &proc_bus_pci_dev_operations); |
487 | proc_initialized = 1; | 485 | proc_initialized = 1; |
488 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | 486 | for_each_pci_dev(dev) |
489 | pci_proc_attach_device(dev); | 487 | pci_proc_attach_device(dev); |
490 | } | 488 | |
491 | return 0; | 489 | return 0; |
492 | } | 490 | } |
493 | 491 | ||
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index a0c20d9e8396..89ed181cd90c 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -91,6 +91,19 @@ static void __devinit quirk_resource_alignment(struct pci_dev *dev) | |||
91 | } | 91 | } |
92 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_resource_alignment); | 92 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_resource_alignment); |
93 | 93 | ||
94 | /* | ||
95 | * Decoding should be disabled for a PCI device during BAR sizing to avoid | ||
96 | * conflict. But doing so may cause problems on host bridge and perhaps other | ||
97 | * key system devices. For devices that need to have mmio decoding always-on, | ||
98 | * we need to set the dev->mmio_always_on bit. | ||
99 | */ | ||
100 | static void __devinit quirk_mmio_always_on(struct pci_dev *dev) | ||
101 | { | ||
102 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) | ||
103 | dev->mmio_always_on = 1; | ||
104 | } | ||
105 | DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, quirk_mmio_always_on); | ||
106 | |||
94 | /* The Mellanox Tavor device gives false positive parity errors | 107 | /* The Mellanox Tavor device gives false positive parity errors |
95 | * Mark this device with a broken_parity_status, to allow | 108 | * Mark this device with a broken_parity_status, to allow |
96 | * PCI scanning code to "skip" this now blacklisted device. | 109 | * PCI scanning code to "skip" this now blacklisted device. |
@@ -2121,6 +2134,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disabl | |||
2121 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3336, quirk_disable_all_msi); | 2134 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3336, quirk_disable_all_msi); |
2122 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi); | 2135 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi); |
2123 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3364, quirk_disable_all_msi); | 2136 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3364, quirk_disable_all_msi); |
2137 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8380_0, quirk_disable_all_msi); | ||
2124 | 2138 | ||
2125 | /* Disable MSI on chipsets that are known to not support it */ | 2139 | /* Disable MSI on chipsets that are known to not support it */ |
2126 | static void __devinit quirk_disable_msi(struct pci_dev *dev) | 2140 | static void __devinit quirk_disable_msi(struct pci_dev *dev) |
@@ -2132,12 +2146,29 @@ static void __devinit quirk_disable_msi(struct pci_dev *dev) | |||
2132 | } | 2146 | } |
2133 | } | 2147 | } |
2134 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi); | 2148 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi); |
2135 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9602, quirk_disable_msi); | ||
2136 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASUSTEK, 0x9602, quirk_disable_msi); | ||
2137 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AI, 0x9602, quirk_disable_msi); | ||
2138 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0xa238, quirk_disable_msi); | 2149 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0xa238, quirk_disable_msi); |
2139 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x5a3f, quirk_disable_msi); | 2150 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x5a3f, quirk_disable_msi); |
2140 | 2151 | ||
2152 | /* | ||
2153 | * The APC bridge device in AMD 780 family northbridges has some random | ||
2154 | * OEM subsystem ID in its vendor ID register (erratum 18), so instead | ||
2155 | * we use the possible vendor/device IDs of the host bridge for the | ||
2156 | * declared quirk, and search for the APC bridge by slot number. | ||
2157 | */ | ||
2158 | static void __devinit quirk_amd_780_apc_msi(struct pci_dev *host_bridge) | ||
2159 | { | ||
2160 | struct pci_dev *apc_bridge; | ||
2161 | |||
2162 | apc_bridge = pci_get_slot(host_bridge->bus, PCI_DEVFN(1, 0)); | ||
2163 | if (apc_bridge) { | ||
2164 | if (apc_bridge->device == 0x9602) | ||
2165 | quirk_disable_msi(apc_bridge); | ||
2166 | pci_dev_put(apc_bridge); | ||
2167 | } | ||
2168 | } | ||
2169 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9600, quirk_amd_780_apc_msi); | ||
2170 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9601, quirk_amd_780_apc_msi); | ||
2171 | |||
2141 | /* Go through the list of Hypertransport capabilities and | 2172 | /* Go through the list of Hypertransport capabilities and |
2142 | * return 1 if a HT MSI capability is found and enabled */ | 2173 | * return 1 if a HT MSI capability is found and enabled */ |
2143 | static int __devinit msi_ht_cap_enabled(struct pci_dev *dev) | 2174 | static int __devinit msi_ht_cap_enabled(struct pci_dev *dev) |
@@ -2396,6 +2427,9 @@ static void __devinit __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all) | |||
2396 | int pos; | 2427 | int pos; |
2397 | int found; | 2428 | int found; |
2398 | 2429 | ||
2430 | if (!pci_msi_enabled()) | ||
2431 | return; | ||
2432 | |||
2399 | /* check if there is HT MSI cap or enabled on this device */ | 2433 | /* check if there is HT MSI cap or enabled on this device */ |
2400 | found = ht_check_msi_mapping(dev); | 2434 | found = ht_check_msi_mapping(dev); |
2401 | 2435 | ||
@@ -2748,7 +2782,7 @@ static int __init pci_apply_final_quirks(void) | |||
2748 | printk(KERN_DEBUG "PCI: CLS %u bytes\n", | 2782 | printk(KERN_DEBUG "PCI: CLS %u bytes\n", |
2749 | pci_cache_line_size << 2); | 2783 | pci_cache_line_size << 2); |
2750 | 2784 | ||
2751 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | 2785 | for_each_pci_dev(dev) { |
2752 | pci_fixup_device(pci_fixup_final, dev); | 2786 | pci_fixup_device(pci_fixup_final, dev); |
2753 | /* | 2787 | /* |
2754 | * If arch hasn't set it explicitly yet, use the CLS | 2788 | * If arch hasn't set it explicitly yet, use the CLS |
diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 20d03f772289..9d75dc8ca602 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c | |||
@@ -169,7 +169,7 @@ struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus, | |||
169 | { | 169 | { |
170 | struct pci_dev *dev = NULL; | 170 | struct pci_dev *dev = NULL; |
171 | 171 | ||
172 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | 172 | for_each_pci_dev(dev) { |
173 | if (pci_domain_nr(dev->bus) == domain && | 173 | if (pci_domain_nr(dev->bus) == domain && |
174 | (dev->bus->number == bus && dev->devfn == devfn)) | 174 | (dev->bus->number == bus && dev->devfn == devfn)) |
175 | return dev; | 175 | return dev; |
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 19b111383f62..66cb8f4cc5f4 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
@@ -874,19 +874,16 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) | |||
874 | again: | 874 | again: |
875 | pci_bus_size_bridges(parent); | 875 | pci_bus_size_bridges(parent); |
876 | __pci_bridge_assign_resources(bridge, &head); | 876 | __pci_bridge_assign_resources(bridge, &head); |
877 | retval = pci_reenable_device(bridge); | ||
878 | pci_set_master(bridge); | ||
879 | pci_enable_bridges(parent); | ||
880 | 877 | ||
881 | tried_times++; | 878 | tried_times++; |
882 | 879 | ||
883 | if (!head.next) | 880 | if (!head.next) |
884 | return; | 881 | goto enable_all; |
885 | 882 | ||
886 | if (tried_times >= 2) { | 883 | if (tried_times >= 2) { |
887 | /* still fail, don't need to try more */ | 884 | /* still fail, don't need to try more */ |
888 | free_failed_list(&head); | 885 | free_failed_list(&head); |
889 | return; | 886 | goto enable_all; |
890 | } | 887 | } |
891 | 888 | ||
892 | printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", | 889 | printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", |
@@ -919,5 +916,10 @@ again: | |||
919 | free_failed_list(&head); | 916 | free_failed_list(&head); |
920 | 917 | ||
921 | goto again; | 918 | goto again; |
919 | |||
920 | enable_all: | ||
921 | retval = pci_reenable_device(bridge); | ||
922 | pci_set_master(bridge); | ||
923 | pci_enable_bridges(parent); | ||
922 | } | 924 | } |
923 | EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources); | 925 | EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources); |
diff --git a/drivers/pci/setup-irq.c b/drivers/pci/setup-irq.c index aa795fd428de..eec9738f3492 100644 --- a/drivers/pci/setup-irq.c +++ b/drivers/pci/setup-irq.c | |||
@@ -59,7 +59,6 @@ pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *), | |||
59 | int (*map_irq)(struct pci_dev *, u8, u8)) | 59 | int (*map_irq)(struct pci_dev *, u8, u8)) |
60 | { | 60 | { |
61 | struct pci_dev *dev = NULL; | 61 | struct pci_dev *dev = NULL; |
62 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | 62 | for_each_pci_dev(dev) |
63 | pdev_fixup_irq(dev, swizzle, map_irq); | 63 | pdev_fixup_irq(dev, swizzle, map_irq); |
64 | } | ||
65 | } | 64 | } |