Commit 1cfd2bda8c486ae0e7a8005354758ebb68172bca
Exists in
master
and in
4 other branches
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 ...
Showing 39 changed files Side-by-side Diff
- Documentation/ABI/testing/sysfs-bus-pci
- Documentation/filesystems/sysfs-pci.txt
- Documentation/kernel-parameters.txt
- arch/ia64/kernel/msi_ia64.c
- arch/ia64/sn/kernel/msi_sn.c
- arch/x86/include/asm/pci_x86.h
- arch/x86/kernel/apic/io_apic.c
- arch/x86/pci/acpi.c
- arch/x86/pci/common.c
- arch/x86/pci/irq.c
- arch/x86/pci/legacy.c
- drivers/acpi/pci_root.c
- drivers/firmware/dmi_scan.c
- drivers/net/e1000e/netdev.c
- drivers/net/r8169.c
- drivers/pci/Makefile
- drivers/pci/bus.c
- drivers/pci/hotplug/fakephp.c
- drivers/pci/hotplug/pciehp_pci.c
- drivers/pci/hotplug/shpchp_hpc.c
- drivers/pci/hotplug/shpchp_pci.c
- drivers/pci/msi.c
- drivers/pci/pci-driver.c
- drivers/pci/pci-label.c
- drivers/pci/pci-sysfs.c
- drivers/pci/pci.c
- drivers/pci/pci.h
- drivers/pci/pcie/Kconfig
- drivers/pci/pcie/aer/aerdrv_core.c
- drivers/pci/pcie/aspm.c
- drivers/pci/probe.c
- drivers/pci/proc.c
- drivers/pci/quirks.c
- drivers/pci/search.c
- drivers/pci/setup-bus.c
- drivers/pci/setup-irq.c
- include/linux/dmi.h
- include/linux/msi.h
- include/linux/pci.h
Documentation/ABI/testing/sysfs-bus-pci
... | ... | @@ -139,4 +139,31 @@ |
139 | 139 | Description: |
140 | 140 | This symbolic link points to the PCI hotplug controller driver |
141 | 141 | module that manages the hotplug slot. |
142 | + | |
143 | +What: /sys/bus/pci/devices/.../label | |
144 | +Date: July 2010 | |
145 | +Contact: Narendra K <narendra_k@dell.com>, linux-bugs@dell.com | |
146 | +Description: | |
147 | + Reading this attribute will provide the firmware | |
148 | + given name(SMBIOS type 41 string) of the PCI device. | |
149 | + The attribute will be created only if the firmware | |
150 | + has given a name to the PCI device. | |
151 | +Users: | |
152 | + Userspace applications interested in knowing the | |
153 | + firmware assigned name of the PCI device. | |
154 | + | |
155 | +What: /sys/bus/pci/devices/.../index | |
156 | +Date: July 2010 | |
157 | +Contact: Narendra K <narendra_k@dell.com>, linux-bugs@dell.com | |
158 | +Description: | |
159 | + Reading this attribute will provide the firmware | |
160 | + given instance(SMBIOS type 41 device type instance) | |
161 | + of the PCI device. The attribute will be created | |
162 | + only if the firmware has given a device type instance | |
163 | + to the PCI device. | |
164 | +Users: | |
165 | + Userspace applications interested in knowing the | |
166 | + firmware assigned device type instance of the PCI | |
167 | + device that can help in understanding the firmware | |
168 | + intended order of the PCI device. |
Documentation/filesystems/sysfs-pci.txt
... | ... | @@ -39,7 +39,7 @@ |
39 | 39 | local_cpus nearby CPU mask (cpumask, ro) |
40 | 40 | remove remove device from kernel's list (ascii, wo) |
41 | 41 | resource PCI resource host addresses (ascii, ro) |
42 | - resource0..N PCI resource N, if present (binary, mmap) | |
42 | + resource0..N PCI resource N, if present (binary, mmap, rw[1]) | |
43 | 43 | resource0_wc..N_wc PCI WC map resource N, if prefetchable (binary, mmap) |
44 | 44 | rom PCI ROM resource, if present (binary, ro) |
45 | 45 | subsystem_device PCI subsystem device (ascii, ro) |
46 | 46 | |
... | ... | @@ -54,13 +54,16 @@ |
54 | 54 | binary - file contains binary data |
55 | 55 | cpumask - file contains a cpumask type |
56 | 56 | |
57 | +[1] rw for RESOURCE_IO (I/O port) regions only | |
58 | + | |
57 | 59 | The read only files are informational, writes to them will be ignored, with |
58 | 60 | the exception of the 'rom' file. Writable files can be used to perform |
59 | 61 | actions on the device (e.g. changing config space, detaching a device). |
60 | 62 | mmapable files are available via an mmap of the file at offset 0 and can be |
61 | 63 | used to do actual device programming from userspace. Note that some platforms |
62 | 64 | don't support mmapping of certain resources, so be sure to check the return |
63 | -value from any attempted mmap. | |
65 | +value from any attempted mmap. The most notable of these are I/O port | |
66 | +resources, which also provide read/write access. | |
64 | 67 | |
65 | 68 | The 'enable' file provides a counter that indicates how many times the device |
66 | 69 | has been enabled. If the 'enable' file currently returns '4', and a '1' is |
Documentation/kernel-parameters.txt
... | ... | @@ -1976,6 +1976,8 @@ |
1976 | 1976 | norom [X86] Do not assign address space to |
1977 | 1977 | expansion ROMs that do not already have |
1978 | 1978 | BIOS assigned address ranges. |
1979 | + nobar [X86] Do not assign address space to the | |
1980 | + BARs that weren't assigned by the BIOS. | |
1979 | 1981 | irqmask=0xMMMM [X86] Set a bit mask of IRQs allowed to be |
1980 | 1982 | assigned automatically to PCI devices. You can |
1981 | 1983 | make the kernel exclude IRQs of your ISA cards |
arch/ia64/kernel/msi_ia64.c
arch/ia64/sn/kernel/msi_sn.c
... | ... | @@ -175,7 +175,7 @@ |
175 | 175 | * Release XIO resources for the old MSI PCI address |
176 | 176 | */ |
177 | 177 | |
178 | - read_msi_msg(irq, &msg); | |
178 | + get_cached_msi_msg(irq, &msg); | |
179 | 179 | sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; |
180 | 180 | pdev = sn_pdev->pdi_linux_pcidev; |
181 | 181 | provider = SN_PCIDEV_BUSPROVIDER(pdev); |
arch/x86/include/asm/pci_x86.h
arch/x86/kernel/apic/io_apic.c
arch/x86/pci/acpi.c
... | ... | @@ -34,6 +34,15 @@ |
34 | 34 | DMI_MATCH(DMI_PRODUCT_NAME, "x3800"), |
35 | 35 | }, |
36 | 36 | }, |
37 | + /* https://bugzilla.kernel.org/show_bug.cgi?id=16007 */ | |
38 | + /* 2006 AMD HT/VIA system with two host bridges */ | |
39 | + { | |
40 | + .callback = set_use_crs, | |
41 | + .ident = "ASRock ALiveSATA2-GLAN", | |
42 | + .matches = { | |
43 | + DMI_MATCH(DMI_PRODUCT_NAME, "ALiveSATA2-GLAN"), | |
44 | + }, | |
45 | + }, | |
37 | 46 | {} |
38 | 47 | }; |
39 | 48 |
arch/x86/pci/common.c
... | ... | @@ -125,7 +125,24 @@ |
125 | 125 | static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) |
126 | 126 | { |
127 | 127 | struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE]; |
128 | + struct resource *bar_r; | |
129 | + int bar; | |
128 | 130 | |
131 | + if (pci_probe & PCI_NOASSIGN_BARS) { | |
132 | + /* | |
133 | + * If the BIOS did not assign the BAR, zero out the | |
134 | + * resource so the kernel doesn't attmept to assign | |
135 | + * it later on in pci_assign_unassigned_resources | |
136 | + */ | |
137 | + for (bar = 0; bar <= PCI_STD_RESOURCE_END; bar++) { | |
138 | + bar_r = &dev->resource[bar]; | |
139 | + if (bar_r->start == 0 && bar_r->end != 0) { | |
140 | + bar_r->flags = 0; | |
141 | + bar_r->end = 0; | |
142 | + } | |
143 | + } | |
144 | + } | |
145 | + | |
129 | 146 | if (pci_probe & PCI_NOASSIGN_ROMS) { |
130 | 147 | if (rom_r->parent) |
131 | 148 | return; |
... | ... | @@ -508,6 +525,9 @@ |
508 | 525 | return NULL; |
509 | 526 | } else if (!strcmp(str, "norom")) { |
510 | 527 | pci_probe |= PCI_NOASSIGN_ROMS; |
528 | + return NULL; | |
529 | + } else if (!strcmp(str, "nobar")) { | |
530 | + pci_probe |= PCI_NOASSIGN_BARS; | |
511 | 531 | return NULL; |
512 | 532 | } else if (!strcmp(str, "assign-busses")) { |
513 | 533 | pci_probe |= PCI_ASSIGN_ALL_BUSSES; |
arch/x86/pci/irq.c
... | ... | @@ -989,7 +989,7 @@ |
989 | 989 | dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' + pin - 1, irq); |
990 | 990 | |
991 | 991 | /* Update IRQ for all devices with the same pirq value */ |
992 | - while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) { | |
992 | + for_each_pci_dev(dev2) { | |
993 | 993 | pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin); |
994 | 994 | if (!pin) |
995 | 995 | continue; |
... | ... | @@ -1028,7 +1028,7 @@ |
1028 | 1028 | u8 pin; |
1029 | 1029 | |
1030 | 1030 | DBG(KERN_DEBUG "PCI: IRQ fixup\n"); |
1031 | - while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | |
1031 | + for_each_pci_dev(dev) { | |
1032 | 1032 | /* |
1033 | 1033 | * If the BIOS has set an out of range IRQ number, just |
1034 | 1034 | * ignore it. Also keep track of which IRQ's are |
... | ... | @@ -1052,7 +1052,7 @@ |
1052 | 1052 | return; |
1053 | 1053 | |
1054 | 1054 | dev = NULL; |
1055 | - while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | |
1055 | + for_each_pci_dev(dev) { | |
1056 | 1056 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); |
1057 | 1057 | if (!pin) |
1058 | 1058 | continue; |
arch/x86/pci/legacy.c
drivers/acpi/pci_root.c
... | ... | @@ -33,6 +33,7 @@ |
33 | 33 | #include <linux/pm_runtime.h> |
34 | 34 | #include <linux/pci.h> |
35 | 35 | #include <linux/pci-acpi.h> |
36 | +#include <linux/pci-aspm.h> | |
36 | 37 | #include <linux/acpi.h> |
37 | 38 | #include <linux/slab.h> |
38 | 39 | #include <acpi/acpi_bus.h> |
... | ... | @@ -542,6 +543,14 @@ |
542 | 543 | flags |= OSC_MSI_SUPPORT; |
543 | 544 | if (flags != base_flags) |
544 | 545 | acpi_pci_osc_support(root, flags); |
546 | + | |
547 | + status = acpi_pci_osc_control_set(root->device->handle, | |
548 | + OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | |
549 | + | |
550 | + if (ACPI_FAILURE(status)) { | |
551 | + printk(KERN_INFO "Unable to assume PCIe control: Disabling ASPM\n"); | |
552 | + pcie_no_aspm(); | |
553 | + } | |
545 | 554 | |
546 | 555 | pci_acpi_add_bus_pm_notifier(device, root->bus); |
547 | 556 | if (device->wakeup.flags.run_wake) |
drivers/firmware/dmi_scan.c
... | ... | @@ -277,6 +277,29 @@ |
277 | 277 | list_add_tail(&dev->list, &dmi_devices); |
278 | 278 | } |
279 | 279 | |
280 | +static void __init dmi_save_dev_onboard(int instance, int segment, int bus, | |
281 | + int devfn, const char *name) | |
282 | +{ | |
283 | + struct dmi_dev_onboard *onboard_dev; | |
284 | + | |
285 | + onboard_dev = dmi_alloc(sizeof(*onboard_dev) + strlen(name) + 1); | |
286 | + if (!onboard_dev) { | |
287 | + printk(KERN_ERR "dmi_save_dev_onboard: out of memory.\n"); | |
288 | + return; | |
289 | + } | |
290 | + onboard_dev->instance = instance; | |
291 | + onboard_dev->segment = segment; | |
292 | + onboard_dev->bus = bus; | |
293 | + onboard_dev->devfn = devfn; | |
294 | + | |
295 | + strcpy((char *)&onboard_dev[1], name); | |
296 | + onboard_dev->dev.type = DMI_DEV_TYPE_DEV_ONBOARD; | |
297 | + onboard_dev->dev.name = (char *)&onboard_dev[1]; | |
298 | + onboard_dev->dev.device_data = onboard_dev; | |
299 | + | |
300 | + list_add(&onboard_dev->dev.list, &dmi_devices); | |
301 | +} | |
302 | + | |
280 | 303 | static void __init dmi_save_extended_devices(const struct dmi_header *dm) |
281 | 304 | { |
282 | 305 | const u8 *d = (u8*) dm + 5; |
... | ... | @@ -285,6 +308,8 @@ |
285 | 308 | if ((*d & 0x80) == 0) |
286 | 309 | return; |
287 | 310 | |
311 | + dmi_save_dev_onboard(*(d+1), *(u16 *)(d+2), *(d+4), *(d+5), | |
312 | + dmi_string_nosave(dm, *(d-1))); | |
288 | 313 | dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1))); |
289 | 314 | } |
290 | 315 |
drivers/net/e1000e/netdev.c
... | ... | @@ -5825,11 +5825,8 @@ |
5825 | 5825 | |
5826 | 5826 | e1000_print_device_info(adapter); |
5827 | 5827 | |
5828 | - if (pci_dev_run_wake(pdev)) { | |
5829 | - pm_runtime_set_active(&pdev->dev); | |
5830 | - pm_runtime_enable(&pdev->dev); | |
5831 | - } | |
5832 | - pm_schedule_suspend(&pdev->dev, MSEC_PER_SEC); | |
5828 | + if (pci_dev_run_wake(pdev)) | |
5829 | + pm_runtime_put_noidle(&pdev->dev); | |
5833 | 5830 | |
5834 | 5831 | return 0; |
5835 | 5832 | |
... | ... | @@ -5875,8 +5872,6 @@ |
5875 | 5872 | struct e1000_adapter *adapter = netdev_priv(netdev); |
5876 | 5873 | bool down = test_bit(__E1000_DOWN, &adapter->state); |
5877 | 5874 | |
5878 | - pm_runtime_get_sync(&pdev->dev); | |
5879 | - | |
5880 | 5875 | /* |
5881 | 5876 | * flush_scheduled work may reschedule our watchdog task, so |
5882 | 5877 | * explicitly disable watchdog tasks from being rescheduled |
... | ... | @@ -5901,11 +5896,8 @@ |
5901 | 5896 | clear_bit(__E1000_DOWN, &adapter->state); |
5902 | 5897 | unregister_netdev(netdev); |
5903 | 5898 | |
5904 | - if (pci_dev_run_wake(pdev)) { | |
5905 | - pm_runtime_disable(&pdev->dev); | |
5906 | - pm_runtime_set_suspended(&pdev->dev); | |
5907 | - } | |
5908 | - pm_runtime_put_noidle(&pdev->dev); | |
5899 | + if (pci_dev_run_wake(pdev)) | |
5900 | + pm_runtime_get_noresume(&pdev->dev); | |
5909 | 5901 | |
5910 | 5902 | /* |
5911 | 5903 | * Release control of h/w to f/w. If f/w is AMT enabled, this |
drivers/net/r8169.c
... | ... | @@ -3219,11 +3219,8 @@ |
3219 | 3219 | |
3220 | 3220 | device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); |
3221 | 3221 | |
3222 | - if (pci_dev_run_wake(pdev)) { | |
3223 | - pm_runtime_set_active(&pdev->dev); | |
3224 | - pm_runtime_enable(&pdev->dev); | |
3225 | - } | |
3226 | - pm_runtime_idle(&pdev->dev); | |
3222 | + if (pci_dev_run_wake(pdev)) | |
3223 | + pm_runtime_put_noidle(&pdev->dev); | |
3227 | 3224 | |
3228 | 3225 | out: |
3229 | 3226 | return rc; |
3230 | 3227 | |
... | ... | @@ -3246,17 +3243,12 @@ |
3246 | 3243 | struct net_device *dev = pci_get_drvdata(pdev); |
3247 | 3244 | struct rtl8169_private *tp = netdev_priv(dev); |
3248 | 3245 | |
3249 | - pm_runtime_get_sync(&pdev->dev); | |
3250 | - | |
3251 | 3246 | flush_scheduled_work(); |
3252 | 3247 | |
3253 | 3248 | unregister_netdev(dev); |
3254 | 3249 | |
3255 | - if (pci_dev_run_wake(pdev)) { | |
3256 | - pm_runtime_disable(&pdev->dev); | |
3257 | - pm_runtime_set_suspended(&pdev->dev); | |
3258 | - } | |
3259 | - pm_runtime_put_noidle(&pdev->dev); | |
3250 | + if (pci_dev_run_wake(pdev)) | |
3251 | + pm_runtime_get_noresume(&pdev->dev); | |
3260 | 3252 | |
3261 | 3253 | /* restore original MAC address */ |
3262 | 3254 | rtl_rar_set(tp, dev->perm_addr); |
drivers/pci/Makefile
drivers/pci/bus.c
... | ... | @@ -56,7 +56,7 @@ |
56 | 56 | int i; |
57 | 57 | |
58 | 58 | for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) |
59 | - bus->resource[i] = 0; | |
59 | + bus->resource[i] = NULL; | |
60 | 60 | |
61 | 61 | list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) { |
62 | 62 | list_del(&bus_res->list); |
... | ... | @@ -240,6 +240,8 @@ |
240 | 240 | if (dev->subordinate) { |
241 | 241 | if (!pci_is_enabled(dev)) { |
242 | 242 | retval = pci_enable_device(dev); |
243 | + if (retval) | |
244 | + dev_err(&dev->dev, "Error enabling bridge (%d), continuing\n", retval); | |
243 | 245 | pci_set_master(dev); |
244 | 246 | } |
245 | 247 | pci_enable_bridges(dev->subordinate); |
drivers/pci/hotplug/fakephp.c
drivers/pci/hotplug/pciehp_pci.c
drivers/pci/hotplug/shpchp_hpc.c
... | ... | @@ -113,7 +113,7 @@ |
113 | 113 | #define CON_PFAULT_INTR_MASK (1 << 28) |
114 | 114 | #define MRL_CHANGE_SERR_MASK (1 << 29) |
115 | 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 | 119 | * SHPC Command Code definitnions |
drivers/pci/hotplug/shpchp_pci.c
... | ... | @@ -60,12 +60,6 @@ |
60 | 60 | dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn)); |
61 | 61 | if (!dev) |
62 | 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 | 63 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || |
70 | 64 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { |
71 | 65 | /* Find an unused bus number for the new bridge */ |
72 | 66 | |
... | ... | @@ -114,17 +108,11 @@ |
114 | 108 | ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", |
115 | 109 | __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); |
116 | 110 | |
117 | - for (j=0; j<8 ; j++) { | |
118 | - struct pci_dev* temp = pci_get_slot(parent, | |
111 | + for (j = 0; j < 8 ; j++) { | |
112 | + struct pci_dev *temp = pci_get_slot(parent, | |
119 | 113 | (p_slot->device << 3) | j); |
120 | 114 | if (!temp) |
121 | 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 | 116 | if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { |
129 | 117 | pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); |
130 | 118 | if (bctl & PCI_BRIDGE_CTL_VGA) { |
... | ... | @@ -132,7 +120,8 @@ |
132 | 120 | "Cannot remove display device %s\n", |
133 | 121 | pci_name(temp)); |
134 | 122 | pci_dev_put(temp); |
135 | - continue; | |
123 | + rc = -EINVAL; | |
124 | + break; | |
136 | 125 | } |
137 | 126 | } |
138 | 127 | pci_remove_bus_device(temp); |
drivers/pci/msi.c
... | ... | @@ -196,6 +196,9 @@ |
196 | 196 | void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) |
197 | 197 | { |
198 | 198 | struct msi_desc *entry = get_irq_desc_msi(desc); |
199 | + | |
200 | + BUG_ON(entry->dev->current_state != PCI_D0); | |
201 | + | |
199 | 202 | if (entry->msi_attrib.is_msix) { |
200 | 203 | void __iomem *base = entry->mask_base + |
201 | 204 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; |
202 | 205 | |
... | ... | @@ -229,10 +232,32 @@ |
229 | 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 | 254 | void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) |
233 | 255 | { |
234 | 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 | 261 | void __iomem *base; |
237 | 262 | base = entry->mask_base + |
238 | 263 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; |
... | ... | @@ -435,7 +460,7 @@ |
435 | 460 | static void __iomem *msix_map_region(struct pci_dev *dev, unsigned pos, |
436 | 461 | unsigned nr_entries) |
437 | 462 | { |
438 | - unsigned long phys_addr; | |
463 | + resource_size_t phys_addr; | |
439 | 464 | u32 table_offset; |
440 | 465 | u8 bir; |
441 | 466 |
drivers/pci/pci-driver.c
... | ... | @@ -289,8 +289,26 @@ |
289 | 289 | static long local_pci_probe(void *_ddi) |
290 | 290 | { |
291 | 291 | struct drv_dev_and_id *ddi = _ddi; |
292 | + struct device *dev = &ddi->dev->dev; | |
293 | + int rc; | |
292 | 294 | |
293 | - return ddi->drv->probe(ddi->dev, ddi->id); | |
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 | 314 | static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, |
297 | 315 | |
298 | 316 | |
... | ... | @@ -369,10 +387,18 @@ |
369 | 387 | struct pci_driver * drv = pci_dev->driver; |
370 | 388 | |
371 | 389 | if (drv) { |
372 | - if (drv->remove) | |
390 | + if (drv->remove) { | |
391 | + pm_runtime_get_sync(dev); | |
373 | 392 | drv->remove(pci_dev); |
393 | + pm_runtime_put_noidle(dev); | |
394 | + } | |
374 | 395 | pci_dev->driver = NULL; |
375 | 396 | } |
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); | |
376 | 402 | |
377 | 403 | /* |
378 | 404 | * If the device is still on, set the power state as "unknown", |
drivers/pci/pci-label.c
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 | +} |
drivers/pci/pci-sysfs.c
... | ... | @@ -734,7 +734,7 @@ |
734 | 734 | { |
735 | 735 | struct pci_dev *pdev = to_pci_dev(container_of(kobj, |
736 | 736 | struct device, kobj)); |
737 | - struct resource *res = (struct resource *)attr->private; | |
737 | + struct resource *res = attr->private; | |
738 | 738 | enum pci_mmap_state mmap_type; |
739 | 739 | resource_size_t start, end; |
740 | 740 | int i; |
... | ... | @@ -778,6 +778,70 @@ |
778 | 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 | 846 | * pci_remove_resource_files - cleanup resource files |
783 | 847 | * @pdev: dev to cleanup |
... | ... | @@ -828,6 +892,10 @@ |
828 | 892 | sprintf(res_attr_name, "resource%d", num); |
829 | 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 | 899 | res_attr->attr.name = res_attr_name; |
832 | 900 | res_attr->attr.mode = S_IRUSR | S_IWUSR; |
833 | 901 | res_attr->size = pci_resource_len(pdev, num); |
... | ... | @@ -1097,6 +1165,8 @@ |
1097 | 1165 | if (retval) |
1098 | 1166 | goto err_vga_file; |
1099 | 1167 | |
1168 | + pci_create_firmware_label_files(pdev); | |
1169 | + | |
1100 | 1170 | return 0; |
1101 | 1171 | |
1102 | 1172 | err_vga_file: |
... | ... | @@ -1164,6 +1234,9 @@ |
1164 | 1234 | sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); |
1165 | 1235 | kfree(pdev->rom_attr); |
1166 | 1236 | } |
1237 | + | |
1238 | + pci_remove_firmware_label_files(pdev); | |
1239 | + | |
1167 | 1240 | } |
1168 | 1241 | |
1169 | 1242 | static int __init pci_sysfs_init(void) |
drivers/pci/pci.c
... | ... | @@ -2312,21 +2312,17 @@ |
2312 | 2312 | } |
2313 | 2313 | EXPORT_SYMBOL_GPL(pci_msi_off); |
2314 | 2314 | |
2315 | -#ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE | |
2316 | 2315 | int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size) |
2317 | 2316 | { |
2318 | 2317 | return dma_set_max_seg_size(&dev->dev, size); |
2319 | 2318 | } |
2320 | 2319 | EXPORT_SYMBOL(pci_set_dma_max_seg_size); |
2321 | -#endif | |
2322 | 2320 | |
2323 | -#ifndef HAVE_ARCH_PCI_SET_DMA_SEGMENT_BOUNDARY | |
2324 | 2321 | int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask) |
2325 | 2322 | { |
2326 | 2323 | return dma_set_seg_boundary(&dev->dev, mask); |
2327 | 2324 | } |
2328 | 2325 | EXPORT_SYMBOL(pci_set_dma_seg_boundary); |
2329 | -#endif | |
2330 | 2326 | |
2331 | 2327 | static int pcie_flr(struct pci_dev *dev, int probe) |
2332 | 2328 | { |
drivers/pci/pci.h
... | ... | @@ -11,6 +11,15 @@ |
11 | 11 | extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env); |
12 | 12 | extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); |
13 | 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 | 23 | extern void pci_cleanup_rom(struct pci_dev *dev); |
15 | 24 | #ifdef HAVE_PCI_MMAP |
16 | 25 | extern int pci_mmap_fits(struct pci_dev *pdev, int resno, |
drivers/pci/pcie/Kconfig
... | ... | @@ -31,14 +31,22 @@ |
31 | 31 | # PCI Express ASPM |
32 | 32 | # |
33 | 33 | config PCIEASPM |
34 | - bool "PCI Express ASPM support(Experimental)" | |
35 | - depends on PCI && EXPERIMENTAL && PCIEPORTBUS | |
36 | - default n | |
34 | + bool "PCI Express ASPM control" if EMBEDDED | |
35 | + depends on PCI && PCIEPORTBUS | |
36 | + default y | |
37 | 37 | help |
38 | - This enables PCI Express ASPM (Active State Power Management) and | |
39 | - Clock Power Management. ASPM supports state L0/L0s/L1. | |
38 | + This enables OS control over PCI Express ASPM (Active State | |
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 | 50 | config PCIEASPM_DEBUG |
43 | 51 | bool "Debug PCI Express ASPM" |
44 | 52 | depends on PCIEASPM |
drivers/pci/pcie/aer/aerdrv_core.c
... | ... | @@ -727,20 +727,21 @@ |
727 | 727 | static int get_e_source(struct aer_rpc *rpc, struct aer_err_source *e_src) |
728 | 728 | { |
729 | 729 | unsigned long flags; |
730 | - int ret = 0; | |
731 | 730 | |
732 | 731 | /* Lock access to Root error producer/consumer index */ |
733 | 732 | spin_lock_irqsave(&rpc->e_lock, flags); |
734 | - if (rpc->prod_idx != rpc->cons_idx) { | |
735 | - *e_src = rpc->e_sources[rpc->cons_idx]; | |
736 | - rpc->cons_idx++; | |
737 | - if (rpc->cons_idx == AER_ERROR_SOURCES_MAX) | |
738 | - rpc->cons_idx = 0; | |
739 | - ret = 1; | |
733 | + if (rpc->prod_idx == rpc->cons_idx) { | |
734 | + spin_unlock_irqrestore(&rpc->e_lock, flags); | |
735 | + return 0; | |
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 | 742 | spin_unlock_irqrestore(&rpc->e_lock, flags); |
742 | 743 | |
743 | - return ret; | |
744 | + return 1; | |
744 | 745 | } |
745 | 746 | |
746 | 747 | /** |
drivers/pci/pcie/aspm.c
... | ... | @@ -588,11 +588,23 @@ |
588 | 588 | * update through pcie_aspm_cap_init(). |
589 | 589 | */ |
590 | 590 | pcie_aspm_cap_init(link, blacklist); |
591 | - pcie_config_aspm_path(link); | |
592 | 591 | |
593 | 592 | /* Setup initial Clock PM state */ |
594 | 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 | 608 | unlock: |
597 | 609 | mutex_unlock(&aspm_lock); |
598 | 610 | out: |
drivers/pci/probe.c
... | ... | @@ -163,15 +163,25 @@ |
163 | 163 | struct resource *res, unsigned int pos) |
164 | 164 | { |
165 | 165 | u32 l, sz, mask; |
166 | + u16 orig_cmd; | |
166 | 167 | |
167 | 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 | 176 | res->name = pci_name(dev); |
170 | 177 | |
171 | 178 | pci_read_config_dword(dev, pos, &l); |
172 | 179 | pci_write_config_dword(dev, pos, l | mask); |
173 | 180 | pci_read_config_dword(dev, pos, &sz); |
174 | 181 | pci_write_config_dword(dev, pos, l); |
182 | + | |
183 | + if (!dev->mmio_always_on) | |
184 | + pci_write_config_word(dev, PCI_COMMAND, orig_cmd); | |
175 | 185 | |
176 | 186 | /* |
177 | 187 | * All bits set in sz means the device isn't working properly. |
drivers/pci/proc.c
... | ... | @@ -431,8 +431,6 @@ |
431 | 431 | struct proc_dir_entry *e; |
432 | 432 | |
433 | 433 | if ((e = dev->procent)) { |
434 | - if (atomic_read(&e->count) > 1) | |
435 | - return -EBUSY; | |
436 | 434 | remove_proc_entry(e->name, dev->bus->procdir); |
437 | 435 | dev->procent = NULL; |
438 | 436 | } |
439 | 437 | |
... | ... | @@ -485,9 +483,9 @@ |
485 | 483 | proc_create("devices", 0, proc_bus_pci_dir, |
486 | 484 | &proc_bus_pci_dev_operations); |
487 | 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 | 487 | pci_proc_attach_device(dev); |
490 | - } | |
488 | + | |
491 | 489 | return 0; |
492 | 490 | } |
493 | 491 |
drivers/pci/quirks.c
... | ... | @@ -91,6 +91,19 @@ |
91 | 91 | } |
92 | 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 | 107 | /* The Mellanox Tavor device gives false positive parity errors |
95 | 108 | * Mark this device with a broken_parity_status, to allow |
96 | 109 | * PCI scanning code to "skip" this now blacklisted device. |
... | ... | @@ -2121,6 +2134,7 @@ |
2121 | 2134 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3336, quirk_disable_all_msi); |
2122 | 2135 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi); |
2123 | 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 | 2139 | /* Disable MSI on chipsets that are known to not support it */ |
2126 | 2140 | static void __devinit quirk_disable_msi(struct pci_dev *dev) |
2127 | 2141 | |
... | ... | @@ -2132,12 +2146,29 @@ |
2132 | 2146 | } |
2133 | 2147 | } |
2134 | 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 | 2149 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0xa238, quirk_disable_msi); |
2139 | 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 | 2172 | /* Go through the list of Hypertransport capabilities and |
2142 | 2173 | * return 1 if a HT MSI capability is found and enabled */ |
2143 | 2174 | static int __devinit msi_ht_cap_enabled(struct pci_dev *dev) |
... | ... | @@ -2396,6 +2427,9 @@ |
2396 | 2427 | int pos; |
2397 | 2428 | int found; |
2398 | 2429 | |
2430 | + if (!pci_msi_enabled()) | |
2431 | + return; | |
2432 | + | |
2399 | 2433 | /* check if there is HT MSI cap or enabled on this device */ |
2400 | 2434 | found = ht_check_msi_mapping(dev); |
2401 | 2435 | |
... | ... | @@ -2748,7 +2782,7 @@ |
2748 | 2782 | printk(KERN_DEBUG "PCI: CLS %u bytes\n", |
2749 | 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 | 2786 | pci_fixup_device(pci_fixup_final, dev); |
2753 | 2787 | /* |
2754 | 2788 | * If arch hasn't set it explicitly yet, use the CLS |
drivers/pci/search.c
... | ... | @@ -169,7 +169,7 @@ |
169 | 169 | { |
170 | 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 | 173 | if (pci_domain_nr(dev->bus) == domain && |
174 | 174 | (dev->bus->number == bus && dev->devfn == devfn)) |
175 | 175 | return dev; |
drivers/pci/setup-bus.c
... | ... | @@ -874,19 +874,16 @@ |
874 | 874 | again: |
875 | 875 | pci_bus_size_bridges(parent); |
876 | 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 | 878 | tried_times++; |
882 | 879 | |
883 | 880 | if (!head.next) |
884 | - return; | |
881 | + goto enable_all; | |
885 | 882 | |
886 | 883 | if (tried_times >= 2) { |
887 | 884 | /* still fail, don't need to try more */ |
888 | 885 | free_failed_list(&head); |
889 | - return; | |
886 | + goto enable_all; | |
890 | 887 | } |
891 | 888 | |
892 | 889 | printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", |
... | ... | @@ -919,6 +916,11 @@ |
919 | 916 | free_failed_list(&head); |
920 | 917 | |
921 | 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 | 925 | EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources); |
drivers/pci/setup-irq.c
include/linux/dmi.h
... | ... | @@ -20,6 +20,7 @@ |
20 | 20 | DMI_DEV_TYPE_SAS, |
21 | 21 | DMI_DEV_TYPE_IPMI = -1, |
22 | 22 | DMI_DEV_TYPE_OEM_STRING = -2, |
23 | + DMI_DEV_TYPE_DEV_ONBOARD = -3, | |
23 | 24 | }; |
24 | 25 | |
25 | 26 | struct dmi_header { |
... | ... | @@ -36,6 +37,14 @@ |
36 | 37 | }; |
37 | 38 | |
38 | 39 | #ifdef CONFIG_DMI |
40 | + | |
41 | +struct dmi_dev_onboard { | |
42 | + struct dmi_device dev; | |
43 | + int instance; | |
44 | + int segment; | |
45 | + int bus; | |
46 | + int devfn; | |
47 | +}; | |
39 | 48 | |
40 | 49 | extern int dmi_check_system(const struct dmi_system_id *list); |
41 | 50 | const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list); |
include/linux/msi.h
... | ... | @@ -14,8 +14,10 @@ |
14 | 14 | extern void mask_msi_irq(unsigned int irq); |
15 | 15 | extern void unmask_msi_irq(unsigned int irq); |
16 | 16 | extern void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg); |
17 | +extern void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg); | |
17 | 18 | extern void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg); |
18 | 19 | extern void read_msi_msg(unsigned int irq, struct msi_msg *msg); |
20 | +extern void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg); | |
19 | 21 | extern void write_msi_msg(unsigned int irq, struct msi_msg *msg); |
20 | 22 | |
21 | 23 | struct msi_desc { |
include/linux/pci.h
... | ... | @@ -270,6 +270,8 @@ |
270 | 270 | unsigned int d1_support:1; /* Low power state D1 is supported */ |
271 | 271 | unsigned int d2_support:1; /* Low power state D2 is supported */ |
272 | 272 | unsigned int no_d1d2:1; /* Only allow D0 and D3 */ |
273 | + unsigned int mmio_always_on:1; /* disallow turning off io/mem | |
274 | + decoding during bar sizing */ | |
273 | 275 | unsigned int wakeup_prepared:1; |
274 | 276 | unsigned int d3_delay; /* D3->D0 transition time in ms */ |
275 | 277 |