diff options
| author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-18 20:50:40 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-18 20:50:40 -0400 |
| commit | b6aefcce747b3bc54d701d3c329416d0c9616f10 (patch) | |
| tree | 18340f3dea5abf9f1c67b2ff0e0e4941a432b46e | |
| parent | 65740356ccfa66703e7e0d47fbe372ba5193916b (diff) | |
| parent | 7a54f25cef6c763f16c9fd49ae382de162147873 (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/pci-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/pci-2.6: (22 commits)
PCI Hotplug: move pci_hotplug.h to include/linux/
change pci hotplug subsystem maintainer to Kristen
PCI: optionally sort device lists breadth-first
cpcihp_generic: prevent loading without "bridge" parameter
pci: Additional search functions
PCI: quirks: switch quirks code offender to use pci_get API
PCI: Update MSI-HOWTO.txt according to pci_msi_supported()
PCI: Improve pci_msi_supported() comments
PCI hotplug: ioremap balanced with iounmap
shpchp: remove unnecessary cmd_busy member from struct controller
shpchp: fix command completion check
pci: Stamp out pci_find_* usage in fakephp
PCI: fix pcie_portdrv_restore_config undefined without CONFIG_PM error
Fix DMA resource allocation in ACPIPnP
PCI: Turn pci_fixup_video into generic for embedded VGA
PCI: add ICH7/8 ACPI/GPIO io resource quirks
PCI: pcie-check-and-return-bus_register-errors fix
PCI: VIA IRQ quirk behaviour change
pciehp: Remove unnecessary check in pciehp_ctrl.c
pciehp - add missing locking
...
44 files changed, 584 insertions, 203 deletions
diff --git a/Documentation/MSI-HOWTO.txt b/Documentation/MSI-HOWTO.txt index c70306abb7b2..5c34910665d1 100644 --- a/Documentation/MSI-HOWTO.txt +++ b/Documentation/MSI-HOWTO.txt | |||
| @@ -470,7 +470,68 @@ LOC: 324553 325068 | |||
| 470 | ERR: 0 | 470 | ERR: 0 |
| 471 | MIS: 0 | 471 | MIS: 0 |
| 472 | 472 | ||
| 473 | 6. FAQ | 473 | 6. MSI quirks |
| 474 | |||
| 475 | Several PCI chipsets or devices are known to not support MSI. | ||
| 476 | The PCI stack provides 3 possible levels of MSI disabling: | ||
| 477 | * on a single device | ||
| 478 | * on all devices behind a specific bridge | ||
| 479 | * globally | ||
| 480 | |||
| 481 | 6.1. Disabling MSI on a single device | ||
| 482 | |||
| 483 | Under some circumstances, it might be required to disable MSI on a | ||
| 484 | single device, It may be achived by either not calling pci_enable_msi() | ||
| 485 | or all, or setting the pci_dev->no_msi flag before (most of the time | ||
| 486 | in a quirk). | ||
| 487 | |||
| 488 | 6.2. Disabling MSI below a bridge | ||
| 489 | |||
| 490 | The vast majority of MSI quirks are required by PCI bridges not | ||
| 491 | being able to route MSI between busses. In this case, MSI have to be | ||
| 492 | disabled on all devices behind this bridge. It is achieves by setting | ||
| 493 | the PCI_BUS_FLAGS_NO_MSI flag in the pci_bus->bus_flags of the bridge | ||
| 494 | subordinate bus. There is no need to set the same flag on bridges that | ||
| 495 | are below the broken brigde. When pci_enable_msi() is called to enable | ||
| 496 | MSI on a device, pci_msi_supported() takes care of checking the NO_MSI | ||
| 497 | flag in all parent busses of the device. | ||
| 498 | |||
| 499 | Some bridges actually support dynamic MSI support enabling/disabling | ||
| 500 | by changing some bits in their PCI configuration space (especially | ||
| 501 | the Hypertransport chipsets such as the nVidia nForce and Serverworks | ||
| 502 | HT2000). It may then be required to update the NO_MSI flag on the | ||
| 503 | corresponding devices in the sysfs hierarchy. To enable MSI support | ||
| 504 | on device "0000:00:0e", do: | ||
| 505 | |||
| 506 | echo 1 > /sys/bus/pci/devices/0000:00:0e/msi_bus | ||
| 507 | |||
| 508 | To disable MSI support, echo 0 instead of 1. Note that it should be | ||
| 509 | used with caution since changing this value might break interrupts. | ||
| 510 | |||
| 511 | 6.3. Disabling MSI globally | ||
| 512 | |||
| 513 | Some extreme cases may require to disable MSI globally on the system. | ||
| 514 | For now, the only known case is a Serverworks PCI-X chipsets (MSI are | ||
| 515 | not supported on several busses that are not all connected to the | ||
| 516 | chipset in the Linux PCI hierarchy). In the vast majority of other | ||
| 517 | cases, disabling only behind a specific bridge is enough. | ||
| 518 | |||
| 519 | For debugging purpose, the user may also pass pci=nomsi on the kernel | ||
| 520 | command-line to explicitly disable MSI globally. But, once the appro- | ||
| 521 | priate quirks are added to the kernel, this option should not be | ||
| 522 | required anymore. | ||
| 523 | |||
| 524 | 6.4. Finding why MSI cannot be enabled on a device | ||
| 525 | |||
| 526 | Assuming that MSI are not enabled on a device, you should look at | ||
| 527 | dmesg to find messages that quirks may output when disabling MSI | ||
| 528 | on some devices, some bridges or even globally. | ||
| 529 | Then, lspci -t gives the list of bridges above a device. Reading | ||
| 530 | /sys/bus/pci/devices/0000:00:0e/msi_bus will tell you whether MSI | ||
| 531 | are enabled (1) or disabled (0). In 0 is found in a single bridge | ||
| 532 | msi_bus file above the device, MSI cannot be enabled. | ||
| 533 | |||
| 534 | 7. FAQ | ||
| 474 | 535 | ||
| 475 | Q1. Are there any limitations on using the MSI? | 536 | Q1. Are there any limitations on using the MSI? |
| 476 | 537 | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ff571f9298e0..dd00fd556a60 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -1231,6 +1231,11 @@ and is between 256 and 4096 characters. It is defined in the file | |||
| 1231 | machine check when some devices' config space | 1231 | machine check when some devices' config space |
| 1232 | is read. But various workarounds are disabled | 1232 | is read. But various workarounds are disabled |
| 1233 | and some IOMMU drivers will not work. | 1233 | and some IOMMU drivers will not work. |
| 1234 | bfsort Sort PCI devices into breadth-first order. | ||
| 1235 | This sorting is done to get a device | ||
| 1236 | order compatible with older (<= 2.4) kernels. | ||
| 1237 | nobfsort Don't sort PCI devices into breadth-first order. | ||
| 1238 | |||
| 1234 | pcmv= [HW,PCMCIA] BadgePAD 4 | 1239 | pcmv= [HW,PCMCIA] BadgePAD 4 |
| 1235 | 1240 | ||
| 1236 | pd. [PARIDE] | 1241 | pd. [PARIDE] |
diff --git a/MAINTAINERS b/MAINTAINERS index 5305dd69095b..9b6b88268d3f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -2309,8 +2309,8 @@ T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ | |||
| 2309 | S: Supported | 2309 | S: Supported |
| 2310 | 2310 | ||
| 2311 | PCI HOTPLUG CORE | 2311 | PCI HOTPLUG CORE |
| 2312 | P: Greg Kroah-Hartman | 2312 | P: Kristen Carlson Accardi |
| 2313 | M: gregkh@suse.de | 2313 | M: kristen.c.accardi@intel.com |
| 2314 | S: Supported | 2314 | S: Supported |
| 2315 | 2315 | ||
| 2316 | PCI HOTPLUG COMPAQ DRIVER | 2316 | PCI HOTPLUG COMPAQ DRIVER |
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index 68bce194e688..6d5ace845e44 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | | 20 | unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | |
| 21 | PCI_PROBE_MMCONF; | 21 | PCI_PROBE_MMCONF; |
| 22 | 22 | ||
| 23 | int pci_bf_sort; | ||
| 23 | int pci_routeirq; | 24 | int pci_routeirq; |
| 24 | int pcibios_last_bus = -1; | 25 | int pcibios_last_bus = -1; |
| 25 | unsigned long pirq_table_addr; | 26 | unsigned long pirq_table_addr; |
| @@ -118,6 +119,20 @@ void __devinit pcibios_fixup_bus(struct pci_bus *b) | |||
| 118 | } | 119 | } |
| 119 | 120 | ||
| 120 | /* | 121 | /* |
| 122 | * Only use DMI information to set this if nothing was passed | ||
| 123 | * on the kernel command line (which was parsed earlier). | ||
| 124 | */ | ||
| 125 | |||
| 126 | static int __devinit set_bf_sort(struct dmi_system_id *d) | ||
| 127 | { | ||
| 128 | if (pci_bf_sort == pci_bf_sort_default) { | ||
| 129 | pci_bf_sort = pci_dmi_bf; | ||
| 130 | printk(KERN_INFO "PCI: %s detected, enabling pci=bfsort.\n", d->ident); | ||
| 131 | } | ||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | /* | ||
| 121 | * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus) | 136 | * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus) |
| 122 | */ | 137 | */ |
| 123 | #ifdef __i386__ | 138 | #ifdef __i386__ |
| @@ -130,11 +145,11 @@ static int __devinit assign_all_busses(struct dmi_system_id *d) | |||
| 130 | } | 145 | } |
| 131 | #endif | 146 | #endif |
| 132 | 147 | ||
| 148 | static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { | ||
| 149 | #ifdef __i386__ | ||
| 133 | /* | 150 | /* |
| 134 | * Laptops which need pci=assign-busses to see Cardbus cards | 151 | * Laptops which need pci=assign-busses to see Cardbus cards |
| 135 | */ | 152 | */ |
| 136 | static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { | ||
| 137 | #ifdef __i386__ | ||
| 138 | { | 153 | { |
| 139 | .callback = assign_all_busses, | 154 | .callback = assign_all_busses, |
| 140 | .ident = "Samsung X20 Laptop", | 155 | .ident = "Samsung X20 Laptop", |
| @@ -144,6 +159,38 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { | |||
| 144 | }, | 159 | }, |
| 145 | }, | 160 | }, |
| 146 | #endif /* __i386__ */ | 161 | #endif /* __i386__ */ |
| 162 | { | ||
| 163 | .callback = set_bf_sort, | ||
| 164 | .ident = "Dell PowerEdge 1950", | ||
| 165 | .matches = { | ||
| 166 | DMI_MATCH(DMI_SYS_VENDOR, "Dell"), | ||
| 167 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"), | ||
| 168 | }, | ||
| 169 | }, | ||
| 170 | { | ||
| 171 | .callback = set_bf_sort, | ||
| 172 | .ident = "Dell PowerEdge 1955", | ||
| 173 | .matches = { | ||
| 174 | DMI_MATCH(DMI_SYS_VENDOR, "Dell"), | ||
| 175 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1955"), | ||
| 176 | }, | ||
| 177 | }, | ||
| 178 | { | ||
| 179 | .callback = set_bf_sort, | ||
| 180 | .ident = "Dell PowerEdge 2900", | ||
| 181 | .matches = { | ||
| 182 | DMI_MATCH(DMI_SYS_VENDOR, "Dell"), | ||
| 183 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2900"), | ||
| 184 | }, | ||
| 185 | }, | ||
| 186 | { | ||
| 187 | .callback = set_bf_sort, | ||
| 188 | .ident = "Dell PowerEdge 2950", | ||
| 189 | .matches = { | ||
| 190 | DMI_MATCH(DMI_SYS_VENDOR, "Dell"), | ||
| 191 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"), | ||
| 192 | }, | ||
| 193 | }, | ||
| 147 | {} | 194 | {} |
| 148 | }; | 195 | }; |
| 149 | 196 | ||
| @@ -189,6 +236,8 @@ static int __init pcibios_init(void) | |||
| 189 | 236 | ||
| 190 | pcibios_resource_survey(); | 237 | pcibios_resource_survey(); |
| 191 | 238 | ||
| 239 | if (pci_bf_sort >= pci_force_bf) | ||
| 240 | pci_sort_breadthfirst(); | ||
| 192 | #ifdef CONFIG_PCI_BIOS | 241 | #ifdef CONFIG_PCI_BIOS |
| 193 | if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT)) | 242 | if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT)) |
| 194 | pcibios_sort(); | 243 | pcibios_sort(); |
| @@ -203,6 +252,12 @@ char * __devinit pcibios_setup(char *str) | |||
| 203 | if (!strcmp(str, "off")) { | 252 | if (!strcmp(str, "off")) { |
| 204 | pci_probe = 0; | 253 | pci_probe = 0; |
| 205 | return NULL; | 254 | return NULL; |
| 255 | } else if (!strcmp(str, "bfsort")) { | ||
| 256 | pci_bf_sort = pci_force_bf; | ||
| 257 | return NULL; | ||
| 258 | } else if (!strcmp(str, "nobfsort")) { | ||
| 259 | pci_bf_sort = pci_force_nobf; | ||
| 260 | return NULL; | ||
| 206 | } | 261 | } |
| 207 | #ifdef CONFIG_PCI_BIOS | 262 | #ifdef CONFIG_PCI_BIOS |
| 208 | else if (!strcmp(str, "bios")) { | 263 | else if (!strcmp(str, "bios")) { |
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index b60d7e8689ed..908b410f4c93 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c | |||
| @@ -343,51 +343,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC, pcie_ro | |||
| 343 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_rootport_aspm_quirk ); | 343 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_rootport_aspm_quirk ); |
| 344 | 344 | ||
| 345 | /* | 345 | /* |
| 346 | * Fixup to mark boot BIOS video selected by BIOS before it changes | ||
| 347 | * | ||
| 348 | * From information provided by "Jon Smirl" <jonsmirl@gmail.com> | ||
| 349 | * | ||
| 350 | * The standard boot ROM sequence for an x86 machine uses the BIOS | ||
| 351 | * to select an initial video card for boot display. This boot video | ||
| 352 | * card will have it's BIOS copied to C0000 in system RAM. | ||
| 353 | * IORESOURCE_ROM_SHADOW is used to associate the boot video | ||
| 354 | * card with this copy. On laptops this copy has to be used since | ||
| 355 | * the main ROM may be compressed or combined with another image. | ||
| 356 | * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW | ||
| 357 | * is marked here since the boot video device will be the only enabled | ||
| 358 | * video device at this point. | ||
| 359 | */ | ||
| 360 | |||
| 361 | static void __devinit pci_fixup_video(struct pci_dev *pdev) | ||
| 362 | { | ||
| 363 | struct pci_dev *bridge; | ||
| 364 | struct pci_bus *bus; | ||
| 365 | u16 config; | ||
| 366 | |||
| 367 | if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) | ||
| 368 | return; | ||
| 369 | |||
| 370 | /* Is VGA routed to us? */ | ||
| 371 | bus = pdev->bus; | ||
| 372 | while (bus) { | ||
| 373 | bridge = bus->self; | ||
| 374 | if (bridge) { | ||
| 375 | pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, | ||
| 376 | &config); | ||
| 377 | if (!(config & PCI_BRIDGE_CTL_VGA)) | ||
| 378 | return; | ||
| 379 | } | ||
| 380 | bus = bus->parent; | ||
| 381 | } | ||
| 382 | pci_read_config_word(pdev, PCI_COMMAND, &config); | ||
| 383 | if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { | ||
| 384 | pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; | ||
| 385 | printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev)); | ||
| 386 | } | ||
| 387 | } | ||
| 388 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); | ||
| 389 | |||
| 390 | /* | ||
| 391 | * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A. | 346 | * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A. |
| 392 | * | 347 | * |
| 393 | * We pretend to bring them out of full D3 state, and restore the proper | 348 | * We pretend to bring them out of full D3 state, and restore the proper |
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h index 1814f74569c6..ad065cebd7b9 100644 --- a/arch/i386/pci/pci.h +++ b/arch/i386/pci/pci.h | |||
| @@ -30,6 +30,13 @@ | |||
| 30 | extern unsigned int pci_probe; | 30 | extern unsigned int pci_probe; |
| 31 | extern unsigned long pirq_table_addr; | 31 | extern unsigned long pirq_table_addr; |
| 32 | 32 | ||
| 33 | enum pci_bf_sort_state { | ||
| 34 | pci_bf_sort_default, | ||
| 35 | pci_force_nobf, | ||
| 36 | pci_force_bf, | ||
| 37 | pci_dmi_bf, | ||
| 38 | }; | ||
| 39 | |||
| 33 | /* pci-i386.c */ | 40 | /* pci-i386.c */ |
| 34 | 41 | ||
| 35 | extern unsigned int pcibios_max_latency; | 42 | extern unsigned int pcibios_max_latency; |
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 51cb9f817c22..270a33cc08f6 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
| @@ -29,10 +29,10 @@ | |||
| 29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
| 30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
| 31 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
| 32 | #include <linux/pci_hotplug.h> | ||
| 32 | #include <acpi/acpi.h> | 33 | #include <acpi/acpi.h> |
| 33 | #include <acpi/acpi_bus.h> | 34 | #include <acpi/acpi_bus.h> |
| 34 | #include <acpi/actypes.h> | 35 | #include <acpi/actypes.h> |
| 35 | #include "pci_hotplug.h" | ||
| 36 | 36 | ||
| 37 | #define MY_NAME "acpi_pcihp" | 37 | #define MY_NAME "acpi_pcihp" |
| 38 | 38 | ||
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 7fff07e877c7..59c5b242d86d 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
| @@ -38,7 +38,7 @@ | |||
| 38 | #include <linux/acpi.h> | 38 | #include <linux/acpi.h> |
| 39 | #include <linux/kobject.h> /* for KOBJ_NAME_LEN */ | 39 | #include <linux/kobject.h> /* for KOBJ_NAME_LEN */ |
| 40 | #include <linux/mutex.h> | 40 | #include <linux/mutex.h> |
| 41 | #include "pci_hotplug.h" | 41 | #include <linux/pci_hotplug.h> |
| 42 | 42 | ||
| 43 | #define dbg(format, arg...) \ | 43 | #define dbg(format, arg...) \ |
| 44 | do { \ | 44 | do { \ |
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index e2fef60c2d06..c57d9d5ce84e 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c | |||
| @@ -37,10 +37,10 @@ | |||
| 37 | 37 | ||
| 38 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
| 39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
| 40 | #include <linux/pci_hotplug.h> | ||
| 40 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
| 41 | #include <linux/smp.h> | 42 | #include <linux/smp.h> |
| 42 | #include <linux/smp_lock.h> | 43 | #include <linux/smp_lock.h> |
| 43 | #include "pci_hotplug.h" | ||
| 44 | #include "acpiphp.h" | 44 | #include "acpiphp.h" |
| 45 | 45 | ||
| 46 | #define MY_NAME "acpiphp" | 46 | #define MY_NAME "acpiphp" |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 83e8e4412de5..c44311ac2fd3 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
| @@ -45,11 +45,11 @@ | |||
| 45 | 45 | ||
| 46 | #include <linux/kernel.h> | 46 | #include <linux/kernel.h> |
| 47 | #include <linux/pci.h> | 47 | #include <linux/pci.h> |
| 48 | #include <linux/pci_hotplug.h> | ||
| 48 | #include <linux/smp_lock.h> | 49 | #include <linux/smp_lock.h> |
| 49 | #include <linux/mutex.h> | 50 | #include <linux/mutex.h> |
| 50 | 51 | ||
| 51 | #include "../pci.h" | 52 | #include "../pci.h" |
| 52 | #include "pci_hotplug.h" | ||
| 53 | #include "acpiphp.h" | 53 | #include "acpiphp.h" |
| 54 | 54 | ||
| 55 | static LIST_HEAD(bridge_list); | 55 | static LIST_HEAD(bridge_list); |
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index d0a07d9ab30c..bd40aee10e16 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c | |||
| @@ -35,7 +35,6 @@ | |||
| 35 | #include <linux/moduleparam.h> | 35 | #include <linux/moduleparam.h> |
| 36 | 36 | ||
| 37 | #include "acpiphp.h" | 37 | #include "acpiphp.h" |
| 38 | #include "pci_hotplug.h" | ||
| 39 | 38 | ||
| 40 | #define DRIVER_VERSION "1.0.1" | 39 | #define DRIVER_VERSION "1.0.1" |
| 41 | #define DRIVER_AUTHOR "Irene Zubarev <zubarev@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>" | 40 | #define DRIVER_AUTHOR "Irene Zubarev <zubarev@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>" |
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index d06ab4045134..684551559d44 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c | |||
| @@ -29,12 +29,12 @@ | |||
| 29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
| 30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| 31 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
| 32 | #include <linux/pci_hotplug.h> | ||
| 32 | #include <linux/init.h> | 33 | #include <linux/init.h> |
| 33 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
| 34 | #include <linux/smp_lock.h> | 35 | #include <linux/smp_lock.h> |
| 35 | #include <asm/atomic.h> | 36 | #include <asm/atomic.h> |
| 36 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
| 37 | #include "pci_hotplug.h" | ||
| 38 | #include "cpci_hotplug.h" | 38 | #include "cpci_hotplug.h" |
| 39 | 39 | ||
| 40 | #define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>" | 40 | #define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>" |
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index 4afcaffd031c..7b1beaad2752 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c | |||
| @@ -26,9 +26,9 @@ | |||
| 26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
| 29 | #include <linux/pci_hotplug.h> | ||
| 29 | #include <linux/proc_fs.h> | 30 | #include <linux/proc_fs.h> |
| 30 | #include "../pci.h" | 31 | #include "../pci.h" |
| 31 | #include "pci_hotplug.h" | ||
| 32 | #include "cpci_hotplug.h" | 32 | #include "cpci_hotplug.h" |
| 33 | 33 | ||
| 34 | #define MY_NAME "cpci_hotplug" | 34 | #define MY_NAME "cpci_hotplug" |
diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c index e847f0d6c7fe..f3852a6b74ea 100644 --- a/drivers/pci/hotplug/cpcihp_generic.c +++ b/drivers/pci/hotplug/cpcihp_generic.c | |||
| @@ -84,7 +84,7 @@ static int __init validate_parameters(void) | |||
| 84 | 84 | ||
| 85 | if(!bridge) { | 85 | if(!bridge) { |
| 86 | info("not configured, disabling."); | 86 | info("not configured, disabling."); |
| 87 | return 1; | 87 | return -EINVAL; |
| 88 | } | 88 | } |
| 89 | str = bridge; | 89 | str = bridge; |
| 90 | if(!*str) | 90 | if(!*str) |
| @@ -147,7 +147,7 @@ static int __init cpcihp_generic_init(void) | |||
| 147 | 147 | ||
| 148 | info(DRIVER_DESC " version: " DRIVER_VERSION); | 148 | info(DRIVER_DESC " version: " DRIVER_VERSION); |
| 149 | status = validate_parameters(); | 149 | status = validate_parameters(); |
| 150 | if(status != 0) | 150 | if (status) |
| 151 | return status; | 151 | return status; |
| 152 | 152 | ||
| 153 | r = request_region(port, 1, "#ENUM hotswap signal register"); | 153 | r = request_region(port, 1, "#ENUM hotswap signal register"); |
diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index ea040c32f47d..298ad7f3f4f4 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h | |||
| @@ -28,7 +28,6 @@ | |||
| 28 | #ifndef _CPQPHP_H | 28 | #ifndef _CPQPHP_H |
| 29 | #define _CPQPHP_H | 29 | #define _CPQPHP_H |
| 30 | 30 | ||
| 31 | #include "pci_hotplug.h" | ||
| 32 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
| 33 | #include <asm/io.h> /* for read? and write? functions */ | 32 | #include <asm/io.h> /* for read? and write? functions */ |
| 34 | #include <linux/delay.h> /* for delays */ | 33 | #include <linux/delay.h> /* for delays */ |
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 1fc259913b68..5617cfdadc5c 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
| 38 | #include <linux/workqueue.h> | 38 | #include <linux/workqueue.h> |
| 39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
| 40 | #include <linux/pci_hotplug.h> | ||
| 40 | #include <linux/init.h> | 41 | #include <linux/init.h> |
| 41 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
| 42 | 43 | ||
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 3ec2ad7db49a..79ff6b4de3a6 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/wait.h> | 36 | #include <linux/wait.h> |
| 37 | #include <linux/smp_lock.h> | 37 | #include <linux/smp_lock.h> |
| 38 | #include <linux/pci.h> | 38 | #include <linux/pci.h> |
| 39 | #include <linux/pci_hotplug.h> | ||
| 39 | #include "cpqphp.h" | 40 | #include "cpqphp.h" |
| 40 | 41 | ||
| 41 | static u32 configure_new_device(struct controller* ctrl, struct pci_func *func, | 42 | static u32 configure_new_device(struct controller* ctrl, struct pci_func *func, |
diff --git a/drivers/pci/hotplug/cpqphp_nvram.c b/drivers/pci/hotplug/cpqphp_nvram.c index cf0878917537..298a6cfd8406 100644 --- a/drivers/pci/hotplug/cpqphp_nvram.c +++ b/drivers/pci/hotplug/cpqphp_nvram.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
| 34 | #include <linux/workqueue.h> | 34 | #include <linux/workqueue.h> |
| 35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
| 36 | #include <linux/pci_hotplug.h> | ||
| 36 | #include <linux/init.h> | 37 | #include <linux/init.h> |
| 37 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
| 38 | #include "cpqphp.h" | 39 | #include "cpqphp.h" |
diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c index 0d9688952f4a..fc7c74d72595 100644 --- a/drivers/pci/hotplug/cpqphp_pci.c +++ b/drivers/pci/hotplug/cpqphp_pci.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
| 34 | #include <linux/proc_fs.h> | 34 | #include <linux/proc_fs.h> |
| 35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
| 36 | #include <linux/pci_hotplug.h> | ||
| 36 | #include "../pci.h" | 37 | #include "../pci.h" |
| 37 | #include "cpqphp.h" | 38 | #include "cpqphp.h" |
| 38 | #include "cpqphp_nvram.h" | 39 | #include "cpqphp_nvram.h" |
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c index 5bab666cd67e..634f74d919d3 100644 --- a/drivers/pci/hotplug/cpqphp_sysfs.c +++ b/drivers/pci/hotplug/cpqphp_sysfs.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/proc_fs.h> | 32 | #include <linux/proc_fs.h> |
| 33 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
| 34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
| 35 | #include <linux/pci_hotplug.h> | ||
| 35 | #include <linux/debugfs.h> | 36 | #include <linux/debugfs.h> |
| 36 | #include "cpqphp.h" | 37 | #include "cpqphp.h" |
| 37 | 38 | ||
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 05a4f0f90186..e27907c91d92 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c | |||
| @@ -35,10 +35,10 @@ | |||
| 35 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
| 36 | #include <linux/module.h> | 36 | #include <linux/module.h> |
| 37 | #include <linux/pci.h> | 37 | #include <linux/pci.h> |
| 38 | #include <linux/pci_hotplug.h> | ||
| 38 | #include <linux/init.h> | 39 | #include <linux/init.h> |
| 39 | #include <linux/string.h> | 40 | #include <linux/string.h> |
| 40 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
| 41 | #include "pci_hotplug.h" | ||
| 42 | #include "../pci.h" | 42 | #include "../pci.h" |
| 43 | 43 | ||
| 44 | #if !defined(MODULE) | 44 | #if !defined(MODULE) |
| @@ -181,7 +181,9 @@ static void pci_rescan_slot(struct pci_dev *temp) | |||
| 181 | 181 | ||
| 182 | if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) { | 182 | if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) { |
| 183 | temp->hdr_type = hdr_type & 0x7f; | 183 | temp->hdr_type = hdr_type & 0x7f; |
| 184 | if (!pci_find_slot(bus->number, temp->devfn)) { | 184 | if ((dev = pci_get_slot(bus, temp->devfn)) != NULL) |
| 185 | pci_dev_put(dev); | ||
| 186 | else { | ||
| 185 | dev = pci_scan_single_device(bus, temp->devfn); | 187 | dev = pci_scan_single_device(bus, temp->devfn); |
| 186 | if (dev) { | 188 | if (dev) { |
| 187 | dbg("New device on %s function %x:%x\n", | 189 | dbg("New device on %s function %x:%x\n", |
| @@ -205,7 +207,9 @@ static void pci_rescan_slot(struct pci_dev *temp) | |||
| 205 | continue; | 207 | continue; |
| 206 | temp->hdr_type = hdr_type & 0x7f; | 208 | temp->hdr_type = hdr_type & 0x7f; |
| 207 | 209 | ||
| 208 | if (!pci_find_slot(bus->number, temp->devfn)) { | 210 | if ((dev = pci_get_slot(bus, temp->devfn)) != NULL) |
| 211 | pci_dev_put(dev); | ||
| 212 | else { | ||
| 209 | dev = pci_scan_single_device(bus, temp->devfn); | 213 | dev = pci_scan_single_device(bus, temp->devfn); |
| 210 | if (dev) { | 214 | if (dev) { |
| 211 | dbg("New device on %s function %x:%x\n", | 215 | dbg("New device on %s function %x:%x\n", |
| @@ -305,7 +309,7 @@ static int disable_slot(struct hotplug_slot *slot) | |||
| 305 | /* search for subfunctions and disable them first */ | 309 | /* search for subfunctions and disable them first */ |
| 306 | if (!(dslot->dev->devfn & 7)) { | 310 | if (!(dslot->dev->devfn & 7)) { |
| 307 | for (func = 1; func < 8; func++) { | 311 | for (func = 1; func < 8; func++) { |
| 308 | dev = pci_find_slot(dslot->dev->bus->number, | 312 | dev = pci_get_slot(dslot->dev->bus, |
| 309 | dslot->dev->devfn + func); | 313 | dslot->dev->devfn + func); |
| 310 | if (dev) { | 314 | if (dev) { |
| 311 | hslot = get_slot_from_dev(dev); | 315 | hslot = get_slot_from_dev(dev); |
| @@ -315,6 +319,7 @@ static int disable_slot(struct hotplug_slot *slot) | |||
| 315 | err("Hotplug slot not found for subfunction of PCI device\n"); | 319 | err("Hotplug slot not found for subfunction of PCI device\n"); |
| 316 | return -ENODEV; | 320 | return -ENODEV; |
| 317 | } | 321 | } |
| 322 | pci_dev_put(dev); | ||
| 318 | } else | 323 | } else |
| 319 | dbg("No device in slot found\n"); | 324 | dbg("No device in slot found\n"); |
| 320 | } | 325 | } |
diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h index dba6d8ca9bda..612d96301509 100644 --- a/drivers/pci/hotplug/ibmphp.h +++ b/drivers/pci/hotplug/ibmphp.h | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | * | 30 | * |
| 31 | */ | 31 | */ |
| 32 | 32 | ||
| 33 | #include "pci_hotplug.h" | 33 | #include <linux/pci_hotplug.h> |
| 34 | 34 | ||
| 35 | extern int ibmphp_debug; | 35 | extern int ibmphp_debug; |
| 36 | 36 | ||
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index e2823ea9c4ed..f5d632e72323 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c | |||
| @@ -21,9 +21,7 @@ | |||
| 21 | * along with this program; if not, write to the Free Software | 21 | * along with this program; if not, write to the Free Software |
| 22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 23 | * | 23 | * |
| 24 | * Send feedback to <greg@kroah.com> | 24 | * Send feedback to <kristen.c.accardi@intel.com> |
| 25 | * | ||
| 26 | * Filesystem portion based on work done by Pat Mochel on ddfs/driverfs | ||
| 27 | * | 25 | * |
| 28 | */ | 26 | */ |
| 29 | 27 | ||
| @@ -32,6 +30,8 @@ | |||
| 32 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
| 33 | #include <linux/types.h> | 31 | #include <linux/types.h> |
| 34 | #include <linux/list.h> | 32 | #include <linux/list.h> |
| 33 | #include <linux/kobject.h> | ||
| 34 | #include <linux/sysfs.h> | ||
| 35 | #include <linux/pagemap.h> | 35 | #include <linux/pagemap.h> |
| 36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
| 37 | #include <linux/smp_lock.h> | 37 | #include <linux/smp_lock.h> |
| @@ -39,11 +39,8 @@ | |||
| 39 | #include <linux/mount.h> | 39 | #include <linux/mount.h> |
| 40 | #include <linux/namei.h> | 40 | #include <linux/namei.h> |
| 41 | #include <linux/pci.h> | 41 | #include <linux/pci.h> |
| 42 | #include <linux/pci_hotplug.h> | ||
| 42 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
| 43 | #include <linux/kobject.h> | ||
| 44 | #include <linux/sysfs.h> | ||
| 45 | #include "pci_hotplug.h" | ||
| 46 | |||
| 47 | 44 | ||
| 48 | #define MY_NAME "pci_hotplug" | 45 | #define MY_NAME "pci_hotplug" |
| 49 | 46 | ||
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index eaea9d36a1bb..4fb12fcda563 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
| @@ -31,11 +31,11 @@ | |||
| 31 | 31 | ||
| 32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
| 33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
| 34 | #include <linux/pci_hotplug.h> | ||
| 34 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
| 35 | #include <linux/sched.h> /* signal_pending() */ | 36 | #include <linux/sched.h> /* signal_pending() */ |
| 36 | #include <linux/pcieport_if.h> | 37 | #include <linux/pcieport_if.h> |
| 37 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
| 38 | #include "pci_hotplug.h" | ||
| 39 | 39 | ||
| 40 | #define MY_NAME "pciehp" | 40 | #define MY_NAME "pciehp" |
| 41 | 41 | ||
| @@ -92,6 +92,7 @@ struct php_ctlr_state_s { | |||
| 92 | struct controller { | 92 | struct controller { |
| 93 | struct controller *next; | 93 | struct controller *next; |
| 94 | struct mutex crit_sect; /* critical section mutex */ | 94 | struct mutex crit_sect; /* critical section mutex */ |
| 95 | struct mutex ctrl_lock; /* controller lock */ | ||
| 95 | struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ | 96 | struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ |
| 96 | int num_slots; /* Number of slots on ctlr */ | 97 | int num_slots; /* Number of slots on ctlr */ |
| 97 | int slot_num_inc; /* 1 or -1 */ | 98 | int slot_num_inc; /* 1 or -1 */ |
| @@ -166,10 +167,10 @@ struct controller { | |||
| 166 | * error Messages | 167 | * error Messages |
| 167 | */ | 168 | */ |
| 168 | #define msg_initialization_err "Initialization failure, error=%d\n" | 169 | #define msg_initialization_err "Initialization failure, error=%d\n" |
| 169 | #define msg_button_on "PCI slot #%d - powering on due to button press.\n" | 170 | #define msg_button_on "PCI slot #%s - powering on due to button press.\n" |
| 170 | #define msg_button_off "PCI slot #%d - powering off due to button press.\n" | 171 | #define msg_button_off "PCI slot #%s - powering off due to button press.\n" |
| 171 | #define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" | 172 | #define msg_button_cancel "PCI slot #%s - action canceled due to button press.\n" |
| 172 | #define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n" | 173 | #define msg_button_ignore "PCI slot #%s - button press ignored. (action in progress...)\n" |
| 173 | 174 | ||
| 174 | /* controller functions */ | 175 | /* controller functions */ |
| 175 | extern int pciehp_event_start_thread (void); | 176 | extern int pciehp_event_start_thread (void); |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index c67b7c3f1ddf..f93e81e2d2c7 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
| @@ -448,7 +448,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
| 448 | } | 448 | } |
| 449 | 449 | ||
| 450 | /* Wait for exclusive access to hardware */ | 450 | /* Wait for exclusive access to hardware */ |
| 451 | mutex_lock(&ctrl->crit_sect); | 451 | mutex_lock(&ctrl->ctrl_lock); |
| 452 | 452 | ||
| 453 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ | 453 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ |
| 454 | 454 | ||
| @@ -456,7 +456,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
| 456 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ | 456 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ |
| 457 | if (rc) { | 457 | if (rc) { |
| 458 | /* Done with exclusive hardware access */ | 458 | /* Done with exclusive hardware access */ |
| 459 | mutex_unlock(&ctrl->crit_sect); | 459 | mutex_unlock(&ctrl->ctrl_lock); |
| 460 | goto err_out_free_ctrl_slot; | 460 | goto err_out_free_ctrl_slot; |
| 461 | } else | 461 | } else |
| 462 | /* Wait for the command to complete */ | 462 | /* Wait for the command to complete */ |
| @@ -464,7 +464,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
| 464 | } | 464 | } |
| 465 | 465 | ||
| 466 | /* Done with exclusive hardware access */ | 466 | /* Done with exclusive hardware access */ |
| 467 | mutex_unlock(&ctrl->crit_sect); | 467 | mutex_unlock(&ctrl->ctrl_lock); |
| 468 | 468 | ||
| 469 | return 0; | 469 | return 0; |
| 470 | 470 | ||
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 41290a106bd8..372c63e35aa9 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
| @@ -43,6 +43,11 @@ static int event_finished; | |||
| 43 | static unsigned long pushbutton_pending; /* = 0 */ | 43 | static unsigned long pushbutton_pending; /* = 0 */ |
| 44 | static unsigned long surprise_rm_pending; /* = 0 */ | 44 | static unsigned long surprise_rm_pending; /* = 0 */ |
| 45 | 45 | ||
| 46 | static inline char *slot_name(struct slot *p_slot) | ||
| 47 | { | ||
| 48 | return p_slot->hotplug_slot->name; | ||
| 49 | } | ||
| 50 | |||
| 46 | u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) | 51 | u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) |
| 47 | { | 52 | { |
| 48 | struct controller *ctrl = (struct controller *) inst_id; | 53 | struct controller *ctrl = (struct controller *) inst_id; |
| @@ -68,7 +73,7 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) | |||
| 68 | /* | 73 | /* |
| 69 | * Button pressed - See if need to TAKE ACTION!!! | 74 | * Button pressed - See if need to TAKE ACTION!!! |
| 70 | */ | 75 | */ |
| 71 | info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); | 76 | info("Button pressed on Slot(%s)\n", slot_name(p_slot)); |
| 72 | taskInfo->event_type = INT_BUTTON_PRESS; | 77 | taskInfo->event_type = INT_BUTTON_PRESS; |
| 73 | 78 | ||
| 74 | if ((p_slot->state == BLINKINGON_STATE) | 79 | if ((p_slot->state == BLINKINGON_STATE) |
| @@ -78,7 +83,7 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) | |||
| 78 | * or hot-remove | 83 | * or hot-remove |
| 79 | */ | 84 | */ |
| 80 | taskInfo->event_type = INT_BUTTON_CANCEL; | 85 | taskInfo->event_type = INT_BUTTON_CANCEL; |
| 81 | info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot); | 86 | info("Button cancel on Slot(%s)\n", slot_name(p_slot)); |
| 82 | } else if ((p_slot->state == POWERON_STATE) | 87 | } else if ((p_slot->state == POWERON_STATE) |
| 83 | || (p_slot->state == POWEROFF_STATE)) { | 88 | || (p_slot->state == POWEROFF_STATE)) { |
| 84 | /* Ignore if the slot is on power-on or power-off state; this | 89 | /* Ignore if the slot is on power-on or power-off state; this |
| @@ -86,7 +91,7 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) | |||
| 86 | * hot-remove is undergoing | 91 | * hot-remove is undergoing |
| 87 | */ | 92 | */ |
| 88 | taskInfo->event_type = INT_BUTTON_IGNORE; | 93 | taskInfo->event_type = INT_BUTTON_IGNORE; |
| 89 | info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot); | 94 | info("Button ignore on Slot(%s)\n", slot_name(p_slot)); |
| 90 | } | 95 | } |
| 91 | 96 | ||
| 92 | if (rc) | 97 | if (rc) |
| @@ -122,13 +127,13 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
| 122 | /* | 127 | /* |
| 123 | * Switch opened | 128 | * Switch opened |
| 124 | */ | 129 | */ |
| 125 | info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); | 130 | info("Latch open on Slot(%s)\n", slot_name(p_slot)); |
| 126 | taskInfo->event_type = INT_SWITCH_OPEN; | 131 | taskInfo->event_type = INT_SWITCH_OPEN; |
| 127 | } else { | 132 | } else { |
| 128 | /* | 133 | /* |
| 129 | * Switch closed | 134 | * Switch closed |
| 130 | */ | 135 | */ |
| 131 | info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); | 136 | info("Latch close on Slot(%s)\n", slot_name(p_slot)); |
| 132 | taskInfo->event_type = INT_SWITCH_CLOSE; | 137 | taskInfo->event_type = INT_SWITCH_CLOSE; |
| 133 | } | 138 | } |
| 134 | 139 | ||
| @@ -166,13 +171,13 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id) | |||
| 166 | /* | 171 | /* |
| 167 | * Card Present | 172 | * Card Present |
| 168 | */ | 173 | */ |
| 169 | info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot); | 174 | info("Card present on Slot(%s)\n", slot_name(p_slot)); |
| 170 | taskInfo->event_type = INT_PRESENCE_ON; | 175 | taskInfo->event_type = INT_PRESENCE_ON; |
| 171 | } else { | 176 | } else { |
| 172 | /* | 177 | /* |
| 173 | * Not Present | 178 | * Not Present |
| 174 | */ | 179 | */ |
| 175 | info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); | 180 | info("Card not present on Slot(%s)\n", slot_name(p_slot)); |
| 176 | taskInfo->event_type = INT_PRESENCE_OFF; | 181 | taskInfo->event_type = INT_PRESENCE_OFF; |
| 177 | } | 182 | } |
| 178 | 183 | ||
| @@ -206,13 +211,13 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
| 206 | /* | 211 | /* |
| 207 | * power fault Cleared | 212 | * power fault Cleared |
| 208 | */ | 213 | */ |
| 209 | info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); | 214 | info("Power fault cleared on Slot(%s)\n", slot_name(p_slot)); |
| 210 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; | 215 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; |
| 211 | } else { | 216 | } else { |
| 212 | /* | 217 | /* |
| 213 | * power fault | 218 | * power fault |
| 214 | */ | 219 | */ |
| 215 | info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); | 220 | info("Power fault on Slot(%s)\n", slot_name(p_slot)); |
| 216 | taskInfo->event_type = INT_POWER_FAULT; | 221 | taskInfo->event_type = INT_POWER_FAULT; |
| 217 | info("power fault bit %x set\n", hp_slot); | 222 | info("power fault bit %x set\n", hp_slot); |
| 218 | } | 223 | } |
| @@ -229,13 +234,13 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
| 229 | static void set_slot_off(struct controller *ctrl, struct slot * pslot) | 234 | static void set_slot_off(struct controller *ctrl, struct slot * pslot) |
| 230 | { | 235 | { |
| 231 | /* Wait for exclusive access to hardware */ | 236 | /* Wait for exclusive access to hardware */ |
| 232 | mutex_lock(&ctrl->crit_sect); | 237 | mutex_lock(&ctrl->ctrl_lock); |
| 233 | 238 | ||
| 234 | /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ | 239 | /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ |
| 235 | if (POWER_CTRL(ctrl->ctrlcap)) { | 240 | if (POWER_CTRL(ctrl->ctrlcap)) { |
| 236 | if (pslot->hpc_ops->power_off_slot(pslot)) { | 241 | if (pslot->hpc_ops->power_off_slot(pslot)) { |
| 237 | err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); | 242 | err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); |
| 238 | mutex_unlock(&ctrl->crit_sect); | 243 | mutex_unlock(&ctrl->ctrl_lock); |
| 239 | return; | 244 | return; |
| 240 | } | 245 | } |
| 241 | wait_for_ctrl_irq (ctrl); | 246 | wait_for_ctrl_irq (ctrl); |
| @@ -249,14 +254,14 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) | |||
| 249 | if (ATTN_LED(ctrl->ctrlcap)) { | 254 | if (ATTN_LED(ctrl->ctrlcap)) { |
| 250 | if (pslot->hpc_ops->set_attention_status(pslot, 1)) { | 255 | if (pslot->hpc_ops->set_attention_status(pslot, 1)) { |
| 251 | err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); | 256 | err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); |
| 252 | mutex_unlock(&ctrl->crit_sect); | 257 | mutex_unlock(&ctrl->ctrl_lock); |
| 253 | return; | 258 | return; |
| 254 | } | 259 | } |
| 255 | wait_for_ctrl_irq (ctrl); | 260 | wait_for_ctrl_irq (ctrl); |
| 256 | } | 261 | } |
| 257 | 262 | ||
| 258 | /* Done with exclusive hardware access */ | 263 | /* Done with exclusive hardware access */ |
| 259 | mutex_unlock(&ctrl->crit_sect); | 264 | mutex_unlock(&ctrl->ctrl_lock); |
| 260 | } | 265 | } |
| 261 | 266 | ||
| 262 | /** | 267 | /** |
| @@ -279,13 +284,13 @@ static int board_added(struct slot *p_slot) | |||
| 279 | ctrl->slot_device_offset, hp_slot); | 284 | ctrl->slot_device_offset, hp_slot); |
| 280 | 285 | ||
| 281 | /* Wait for exclusive access to hardware */ | 286 | /* Wait for exclusive access to hardware */ |
| 282 | mutex_lock(&ctrl->crit_sect); | 287 | mutex_lock(&ctrl->ctrl_lock); |
| 283 | 288 | ||
| 284 | if (POWER_CTRL(ctrl->ctrlcap)) { | 289 | if (POWER_CTRL(ctrl->ctrlcap)) { |
| 285 | /* Power on slot */ | 290 | /* Power on slot */ |
| 286 | rc = p_slot->hpc_ops->power_on_slot(p_slot); | 291 | rc = p_slot->hpc_ops->power_on_slot(p_slot); |
| 287 | if (rc) { | 292 | if (rc) { |
| 288 | mutex_unlock(&ctrl->crit_sect); | 293 | mutex_unlock(&ctrl->ctrl_lock); |
| 289 | return -1; | 294 | return -1; |
| 290 | } | 295 | } |
| 291 | 296 | ||
| @@ -301,7 +306,7 @@ static int board_added(struct slot *p_slot) | |||
| 301 | } | 306 | } |
| 302 | 307 | ||
| 303 | /* Done with exclusive hardware access */ | 308 | /* Done with exclusive hardware access */ |
| 304 | mutex_unlock(&ctrl->crit_sect); | 309 | mutex_unlock(&ctrl->ctrl_lock); |
| 305 | 310 | ||
| 306 | /* Wait for ~1 second */ | 311 | /* Wait for ~1 second */ |
| 307 | wait_for_ctrl_irq (ctrl); | 312 | wait_for_ctrl_irq (ctrl); |
| @@ -335,7 +340,7 @@ static int board_added(struct slot *p_slot) | |||
| 335 | pci_fixup_device(pci_fixup_final, ctrl->pci_dev); | 340 | pci_fixup_device(pci_fixup_final, ctrl->pci_dev); |
| 336 | if (PWR_LED(ctrl->ctrlcap)) { | 341 | if (PWR_LED(ctrl->ctrlcap)) { |
| 337 | /* Wait for exclusive access to hardware */ | 342 | /* Wait for exclusive access to hardware */ |
| 338 | mutex_lock(&ctrl->crit_sect); | 343 | mutex_lock(&ctrl->ctrl_lock); |
| 339 | 344 | ||
| 340 | p_slot->hpc_ops->green_led_on(p_slot); | 345 | p_slot->hpc_ops->green_led_on(p_slot); |
| 341 | 346 | ||
| @@ -343,7 +348,7 @@ static int board_added(struct slot *p_slot) | |||
| 343 | wait_for_ctrl_irq (ctrl); | 348 | wait_for_ctrl_irq (ctrl); |
| 344 | 349 | ||
| 345 | /* Done with exclusive hardware access */ | 350 | /* Done with exclusive hardware access */ |
| 346 | mutex_unlock(&ctrl->crit_sect); | 351 | mutex_unlock(&ctrl->ctrl_lock); |
| 347 | } | 352 | } |
| 348 | return 0; | 353 | return 0; |
| 349 | 354 | ||
| @@ -375,14 +380,14 @@ static int remove_board(struct slot *p_slot) | |||
| 375 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); | 380 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); |
| 376 | 381 | ||
| 377 | /* Wait for exclusive access to hardware */ | 382 | /* Wait for exclusive access to hardware */ |
| 378 | mutex_lock(&ctrl->crit_sect); | 383 | mutex_lock(&ctrl->ctrl_lock); |
| 379 | 384 | ||
| 380 | if (POWER_CTRL(ctrl->ctrlcap)) { | 385 | if (POWER_CTRL(ctrl->ctrlcap)) { |
| 381 | /* power off slot */ | 386 | /* power off slot */ |
| 382 | rc = p_slot->hpc_ops->power_off_slot(p_slot); | 387 | rc = p_slot->hpc_ops->power_off_slot(p_slot); |
| 383 | if (rc) { | 388 | if (rc) { |
| 384 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); | 389 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); |
| 385 | mutex_unlock(&ctrl->crit_sect); | 390 | mutex_unlock(&ctrl->ctrl_lock); |
| 386 | return rc; | 391 | return rc; |
| 387 | } | 392 | } |
| 388 | /* Wait for the command to complete */ | 393 | /* Wait for the command to complete */ |
| @@ -398,7 +403,7 @@ static int remove_board(struct slot *p_slot) | |||
| 398 | } | 403 | } |
| 399 | 404 | ||
| 400 | /* Done with exclusive hardware access */ | 405 | /* Done with exclusive hardware access */ |
| 401 | mutex_unlock(&ctrl->crit_sect); | 406 | mutex_unlock(&ctrl->ctrl_lock); |
| 402 | 407 | ||
| 403 | return 0; | 408 | return 0; |
| 404 | } | 409 | } |
| @@ -445,7 +450,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) | |||
| 445 | 450 | ||
| 446 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { | 451 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { |
| 447 | /* Wait for exclusive access to hardware */ | 452 | /* Wait for exclusive access to hardware */ |
| 448 | mutex_lock(&p_slot->ctrl->crit_sect); | 453 | mutex_lock(&p_slot->ctrl->ctrl_lock); |
| 449 | 454 | ||
| 450 | p_slot->hpc_ops->green_led_off(p_slot); | 455 | p_slot->hpc_ops->green_led_off(p_slot); |
| 451 | 456 | ||
| @@ -453,7 +458,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) | |||
| 453 | wait_for_ctrl_irq (p_slot->ctrl); | 458 | wait_for_ctrl_irq (p_slot->ctrl); |
| 454 | 459 | ||
| 455 | /* Done with exclusive hardware access */ | 460 | /* Done with exclusive hardware access */ |
| 456 | mutex_unlock(&p_slot->ctrl->crit_sect); | 461 | mutex_unlock(&p_slot->ctrl->ctrl_lock); |
| 457 | } | 462 | } |
| 458 | p_slot->state = STATIC_STATE; | 463 | p_slot->state = STATIC_STATE; |
| 459 | } | 464 | } |
| @@ -495,7 +500,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot) | |||
| 495 | 500 | ||
| 496 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { | 501 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { |
| 497 | /* Wait for exclusive access to hardware */ | 502 | /* Wait for exclusive access to hardware */ |
| 498 | mutex_lock(&p_slot->ctrl->crit_sect); | 503 | mutex_lock(&p_slot->ctrl->ctrl_lock); |
| 499 | 504 | ||
| 500 | p_slot->hpc_ops->green_led_off(p_slot); | 505 | p_slot->hpc_ops->green_led_off(p_slot); |
| 501 | 506 | ||
| @@ -503,7 +508,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot) | |||
| 503 | wait_for_ctrl_irq (p_slot->ctrl); | 508 | wait_for_ctrl_irq (p_slot->ctrl); |
| 504 | 509 | ||
| 505 | /* Done with exclusive hardware access */ | 510 | /* Done with exclusive hardware access */ |
| 506 | mutex_unlock(&p_slot->ctrl->crit_sect); | 511 | mutex_unlock(&p_slot->ctrl->ctrl_lock); |
| 507 | } | 512 | } |
| 508 | p_slot->state = STATIC_STATE; | 513 | p_slot->state = STATIC_STATE; |
| 509 | } | 514 | } |
| @@ -616,7 +621,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
| 616 | switch (p_slot->state) { | 621 | switch (p_slot->state) { |
| 617 | case BLINKINGOFF_STATE: | 622 | case BLINKINGOFF_STATE: |
| 618 | /* Wait for exclusive access to hardware */ | 623 | /* Wait for exclusive access to hardware */ |
| 619 | mutex_lock(&ctrl->crit_sect); | 624 | mutex_lock(&ctrl->ctrl_lock); |
| 620 | 625 | ||
| 621 | if (PWR_LED(ctrl->ctrlcap)) { | 626 | if (PWR_LED(ctrl->ctrlcap)) { |
| 622 | p_slot->hpc_ops->green_led_on(p_slot); | 627 | p_slot->hpc_ops->green_led_on(p_slot); |
| @@ -630,11 +635,11 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
| 630 | wait_for_ctrl_irq (ctrl); | 635 | wait_for_ctrl_irq (ctrl); |
| 631 | } | 636 | } |
| 632 | /* Done with exclusive hardware access */ | 637 | /* Done with exclusive hardware access */ |
| 633 | mutex_unlock(&ctrl->crit_sect); | 638 | mutex_unlock(&ctrl->ctrl_lock); |
| 634 | break; | 639 | break; |
| 635 | case BLINKINGON_STATE: | 640 | case BLINKINGON_STATE: |
| 636 | /* Wait for exclusive access to hardware */ | 641 | /* Wait for exclusive access to hardware */ |
| 637 | mutex_lock(&ctrl->crit_sect); | 642 | mutex_lock(&ctrl->ctrl_lock); |
| 638 | 643 | ||
| 639 | if (PWR_LED(ctrl->ctrlcap)) { | 644 | if (PWR_LED(ctrl->ctrlcap)) { |
| 640 | p_slot->hpc_ops->green_led_off(p_slot); | 645 | p_slot->hpc_ops->green_led_off(p_slot); |
| @@ -647,14 +652,14 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
| 647 | wait_for_ctrl_irq (ctrl); | 652 | wait_for_ctrl_irq (ctrl); |
| 648 | } | 653 | } |
| 649 | /* Done with exclusive hardware access */ | 654 | /* Done with exclusive hardware access */ |
| 650 | mutex_unlock(&ctrl->crit_sect); | 655 | mutex_unlock(&ctrl->ctrl_lock); |
| 651 | 656 | ||
| 652 | break; | 657 | break; |
| 653 | default: | 658 | default: |
| 654 | warn("Not a valid state\n"); | 659 | warn("Not a valid state\n"); |
| 655 | return; | 660 | return; |
| 656 | } | 661 | } |
| 657 | info(msg_button_cancel, p_slot->number); | 662 | info(msg_button_cancel, slot_name(p_slot)); |
| 658 | p_slot->state = STATIC_STATE; | 663 | p_slot->state = STATIC_STATE; |
| 659 | } | 664 | } |
| 660 | /* ***********Button Pressed (No action on 1st press...) */ | 665 | /* ***********Button Pressed (No action on 1st press...) */ |
| @@ -667,16 +672,16 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
| 667 | /* slot is on */ | 672 | /* slot is on */ |
| 668 | dbg("slot is on\n"); | 673 | dbg("slot is on\n"); |
| 669 | p_slot->state = BLINKINGOFF_STATE; | 674 | p_slot->state = BLINKINGOFF_STATE; |
| 670 | info(msg_button_off, p_slot->number); | 675 | info(msg_button_off, slot_name(p_slot)); |
| 671 | } else { | 676 | } else { |
| 672 | /* slot is off */ | 677 | /* slot is off */ |
| 673 | dbg("slot is off\n"); | 678 | dbg("slot is off\n"); |
| 674 | p_slot->state = BLINKINGON_STATE; | 679 | p_slot->state = BLINKINGON_STATE; |
| 675 | info(msg_button_on, p_slot->number); | 680 | info(msg_button_on, slot_name(p_slot)); |
| 676 | } | 681 | } |
| 677 | 682 | ||
| 678 | /* Wait for exclusive access to hardware */ | 683 | /* Wait for exclusive access to hardware */ |
| 679 | mutex_lock(&ctrl->crit_sect); | 684 | mutex_lock(&ctrl->ctrl_lock); |
| 680 | 685 | ||
| 681 | /* blink green LED and turn off amber */ | 686 | /* blink green LED and turn off amber */ |
| 682 | if (PWR_LED(ctrl->ctrlcap)) { | 687 | if (PWR_LED(ctrl->ctrlcap)) { |
| @@ -693,7 +698,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
| 693 | } | 698 | } |
| 694 | 699 | ||
| 695 | /* Done with exclusive hardware access */ | 700 | /* Done with exclusive hardware access */ |
| 696 | mutex_unlock(&ctrl->crit_sect); | 701 | mutex_unlock(&ctrl->ctrl_lock); |
| 697 | 702 | ||
| 698 | init_timer(&p_slot->task_event); | 703 | init_timer(&p_slot->task_event); |
| 699 | p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ | 704 | p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ |
| @@ -708,7 +713,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
| 708 | if (POWER_CTRL(ctrl->ctrlcap)) { | 713 | if (POWER_CTRL(ctrl->ctrlcap)) { |
| 709 | dbg("power fault\n"); | 714 | dbg("power fault\n"); |
| 710 | /* Wait for exclusive access to hardware */ | 715 | /* Wait for exclusive access to hardware */ |
| 711 | mutex_lock(&ctrl->crit_sect); | 716 | mutex_lock(&ctrl->ctrl_lock); |
| 712 | 717 | ||
| 713 | if (ATTN_LED(ctrl->ctrlcap)) { | 718 | if (ATTN_LED(ctrl->ctrlcap)) { |
| 714 | p_slot->hpc_ops->set_attention_status(p_slot, 1); | 719 | p_slot->hpc_ops->set_attention_status(p_slot, 1); |
| @@ -721,7 +726,7 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
| 721 | } | 726 | } |
| 722 | 727 | ||
| 723 | /* Done with exclusive hardware access */ | 728 | /* Done with exclusive hardware access */ |
| 724 | mutex_unlock(&ctrl->crit_sect); | 729 | mutex_unlock(&ctrl->ctrl_lock); |
| 725 | } | 730 | } |
| 726 | } | 731 | } |
| 727 | /***********SURPRISE REMOVAL********************/ | 732 | /***********SURPRISE REMOVAL********************/ |
| @@ -760,14 +765,16 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
| 760 | 765 | ||
| 761 | rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); | 766 | rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); |
| 762 | if (rc || !getstatus) { | 767 | if (rc || !getstatus) { |
| 763 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); | 768 | info("%s: no adapter on slot(%s)\n", __FUNCTION__, |
| 769 | slot_name(p_slot)); | ||
| 764 | mutex_unlock(&p_slot->ctrl->crit_sect); | 770 | mutex_unlock(&p_slot->ctrl->crit_sect); |
| 765 | return -ENODEV; | 771 | return -ENODEV; |
| 766 | } | 772 | } |
| 767 | if (MRL_SENS(p_slot->ctrl->ctrlcap)) { | 773 | if (MRL_SENS(p_slot->ctrl->ctrlcap)) { |
| 768 | rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 774 | rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
| 769 | if (rc || getstatus) { | 775 | if (rc || getstatus) { |
| 770 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); | 776 | info("%s: latch open on slot(%s)\n", __FUNCTION__, |
| 777 | slot_name(p_slot)); | ||
| 771 | mutex_unlock(&p_slot->ctrl->crit_sect); | 778 | mutex_unlock(&p_slot->ctrl->crit_sect); |
| 772 | return -ENODEV; | 779 | return -ENODEV; |
| 773 | } | 780 | } |
| @@ -776,12 +783,12 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
| 776 | if (POWER_CTRL(p_slot->ctrl->ctrlcap)) { | 783 | if (POWER_CTRL(p_slot->ctrl->ctrlcap)) { |
| 777 | rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | 784 | rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); |
| 778 | if (rc || getstatus) { | 785 | if (rc || getstatus) { |
| 779 | info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); | 786 | info("%s: already enabled on slot(%s)\n", __FUNCTION__, |
| 787 | slot_name(p_slot)); | ||
| 780 | mutex_unlock(&p_slot->ctrl->crit_sect); | 788 | mutex_unlock(&p_slot->ctrl->crit_sect); |
| 781 | return -EINVAL; | 789 | return -EINVAL; |
| 782 | } | 790 | } |
| 783 | } | 791 | } |
| 784 | mutex_unlock(&p_slot->ctrl->crit_sect); | ||
| 785 | 792 | ||
| 786 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 793 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
| 787 | 794 | ||
| @@ -790,9 +797,9 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
| 790 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 797 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
| 791 | } | 798 | } |
| 792 | 799 | ||
| 793 | if (p_slot) | 800 | update_slot_info(p_slot); |
| 794 | update_slot_info(p_slot); | ||
| 795 | 801 | ||
| 802 | mutex_unlock(&p_slot->ctrl->crit_sect); | ||
| 796 | return rc; | 803 | return rc; |
| 797 | } | 804 | } |
| 798 | 805 | ||
| @@ -811,7 +818,8 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
| 811 | if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) { | 818 | if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) { |
| 812 | ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); | 819 | ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); |
| 813 | if (ret || !getstatus) { | 820 | if (ret || !getstatus) { |
| 814 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); | 821 | info("%s: no adapter on slot(%s)\n", __FUNCTION__, |
| 822 | slot_name(p_slot)); | ||
| 815 | mutex_unlock(&p_slot->ctrl->crit_sect); | 823 | mutex_unlock(&p_slot->ctrl->crit_sect); |
| 816 | return -ENODEV; | 824 | return -ENODEV; |
| 817 | } | 825 | } |
| @@ -820,7 +828,8 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
| 820 | if (MRL_SENS(p_slot->ctrl->ctrlcap)) { | 828 | if (MRL_SENS(p_slot->ctrl->ctrlcap)) { |
| 821 | ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 829 | ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
| 822 | if (ret || getstatus) { | 830 | if (ret || getstatus) { |
| 823 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); | 831 | info("%s: latch open on slot(%s)\n", __FUNCTION__, |
| 832 | slot_name(p_slot)); | ||
| 824 | mutex_unlock(&p_slot->ctrl->crit_sect); | 833 | mutex_unlock(&p_slot->ctrl->crit_sect); |
| 825 | return -ENODEV; | 834 | return -ENODEV; |
| 826 | } | 835 | } |
| @@ -829,16 +838,17 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
| 829 | if (POWER_CTRL(p_slot->ctrl->ctrlcap)) { | 838 | if (POWER_CTRL(p_slot->ctrl->ctrlcap)) { |
| 830 | ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | 839 | ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); |
| 831 | if (ret || !getstatus) { | 840 | if (ret || !getstatus) { |
| 832 | info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); | 841 | info("%s: already disabled slot(%s)\n", __FUNCTION__, |
| 842 | slot_name(p_slot)); | ||
| 833 | mutex_unlock(&p_slot->ctrl->crit_sect); | 843 | mutex_unlock(&p_slot->ctrl->crit_sect); |
| 834 | return -EINVAL; | 844 | return -EINVAL; |
| 835 | } | 845 | } |
| 836 | } | 846 | } |
| 837 | 847 | ||
| 838 | mutex_unlock(&p_slot->ctrl->crit_sect); | ||
| 839 | |||
| 840 | ret = remove_board(p_slot); | 848 | ret = remove_board(p_slot); |
| 841 | update_slot_info(p_slot); | 849 | update_slot_info(p_slot); |
| 850 | |||
| 851 | mutex_unlock(&p_slot->ctrl->crit_sect); | ||
| 842 | return ret; | 852 | return ret; |
| 843 | } | 853 | } |
| 844 | 854 | ||
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 703a64a39fe8..1c551c697c35 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
| @@ -1402,6 +1402,8 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
| 1402 | pdev->subsystem_vendor, pdev->subsystem_device); | 1402 | pdev->subsystem_vendor, pdev->subsystem_device); |
| 1403 | 1403 | ||
| 1404 | mutex_init(&ctrl->crit_sect); | 1404 | mutex_init(&ctrl->crit_sect); |
| 1405 | mutex_init(&ctrl->ctrl_lock); | ||
| 1406 | |||
| 1405 | /* setup wait queue */ | 1407 | /* setup wait queue */ |
| 1406 | init_waitqueue_head(&ctrl->queue); | 1408 | init_waitqueue_head(&ctrl->queue); |
| 1407 | 1409 | ||
diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c index 2b9e10e38613..50bcd3fe61da 100644 --- a/drivers/pci/hotplug/pcihp_skeleton.c +++ b/drivers/pci/hotplug/pcihp_skeleton.c | |||
| @@ -33,8 +33,8 @@ | |||
| 33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
| 34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
| 35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
| 36 | #include <linux/pci_hotplug.h> | ||
| 36 | #include <linux/init.h> | 37 | #include <linux/init.h> |
| 37 | #include "pci_hotplug.h" | ||
| 38 | 38 | ||
| 39 | #define SLOT_NAME_SIZE 10 | 39 | #define SLOT_NAME_SIZE 10 |
| 40 | struct slot { | 40 | struct slot { |
diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c index db69be85b458..6c5be3ff578c 100644 --- a/drivers/pci/hotplug/rpadlpar_sysfs.c +++ b/drivers/pci/hotplug/rpadlpar_sysfs.c | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | */ | 14 | */ |
| 15 | #include <linux/kobject.h> | 15 | #include <linux/kobject.h> |
| 16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
| 17 | #include "pci_hotplug.h" | 17 | #include <linux/pci_hotplug.h> |
| 18 | #include "rpadlpar.h" | 18 | #include "rpadlpar.h" |
| 19 | 19 | ||
| 20 | #define DLPAR_KOBJ_NAME "control" | 20 | #define DLPAR_KOBJ_NAME "control" |
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 7288a3eccfb3..141486df235b 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 27 | #include <linux/moduleparam.h> | 27 | #include <linux/moduleparam.h> |
| 28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
| 29 | #include <linux/pci_hotplug.h> | ||
| 29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| 30 | #include <linux/smp.h> | 31 | #include <linux/smp.h> |
| 31 | #include <linux/smp_lock.h> | 32 | #include <linux/smp_lock.h> |
| @@ -36,7 +37,6 @@ | |||
| 36 | #include "../pci.h" /* for pci_add_new_bus */ | 37 | #include "../pci.h" /* for pci_add_new_bus */ |
| 37 | /* and pci_do_scan_bus */ | 38 | /* and pci_do_scan_bus */ |
| 38 | #include "rpaphp.h" | 39 | #include "rpaphp.h" |
| 39 | #include "pci_hotplug.h" | ||
| 40 | 40 | ||
| 41 | int debug; | 41 | int debug; |
| 42 | static struct semaphore rpaphp_sem; | 42 | static struct semaphore rpaphp_sem; |
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index f31d83c2c633..b62ad31a9739 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/pci.h> | 15 | #include <linux/pci.h> |
| 16 | #include <linux/pci_hotplug.h> | ||
| 16 | #include <linux/proc_fs.h> | 17 | #include <linux/proc_fs.h> |
| 17 | #include <linux/types.h> | 18 | #include <linux/types.h> |
| 18 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
| @@ -29,7 +30,6 @@ | |||
| 29 | #include <asm/sn/types.h> | 30 | #include <asm/sn/types.h> |
| 30 | 31 | ||
| 31 | #include "../pci.h" | 32 | #include "../pci.h" |
| 32 | #include "pci_hotplug.h" | ||
| 33 | 33 | ||
| 34 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
| 35 | MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)"); | 35 | MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)"); |
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index c7103ac5cd06..ea2087c34149 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
| @@ -31,12 +31,11 @@ | |||
| 31 | 31 | ||
| 32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
| 33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
| 34 | #include <linux/pci_hotplug.h> | ||
| 34 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
| 35 | #include <linux/sched.h> /* signal_pending(), struct timer_list */ | 36 | #include <linux/sched.h> /* signal_pending(), struct timer_list */ |
| 36 | #include <linux/mutex.h> | 37 | #include <linux/mutex.h> |
| 37 | 38 | ||
| 38 | #include "pci_hotplug.h" | ||
| 39 | |||
| 40 | #if !defined(MODULE) | 39 | #if !defined(MODULE) |
| 41 | #define MY_NAME "shpchp" | 40 | #define MY_NAME "shpchp" |
| 42 | #else | 41 | #else |
| @@ -103,7 +102,6 @@ struct controller { | |||
| 103 | u32 cap_offset; | 102 | u32 cap_offset; |
| 104 | unsigned long mmio_base; | 103 | unsigned long mmio_base; |
| 105 | unsigned long mmio_size; | 104 | unsigned long mmio_size; |
| 106 | volatile int cmd_busy; | ||
| 107 | }; | 105 | }; |
| 108 | 106 | ||
| 109 | 107 | ||
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 4d8aee119134..83a5226ba9ed 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
| @@ -302,21 +302,51 @@ static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec) | |||
| 302 | add_timer(&php_ctlr->int_poll_timer); | 302 | add_timer(&php_ctlr->int_poll_timer); |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | static inline int is_ctrl_busy(struct controller *ctrl) | ||
| 306 | { | ||
| 307 | u16 cmd_status = shpc_readw(ctrl, CMD_STATUS); | ||
| 308 | return cmd_status & 0x1; | ||
| 309 | } | ||
| 310 | |||
| 311 | /* | ||
| 312 | * Returns 1 if SHPC finishes executing a command within 1 sec, | ||
| 313 | * otherwise returns 0. | ||
| 314 | */ | ||
| 315 | static inline int shpc_poll_ctrl_busy(struct controller *ctrl) | ||
| 316 | { | ||
| 317 | int i; | ||
| 318 | |||
| 319 | if (!is_ctrl_busy(ctrl)) | ||
| 320 | return 1; | ||
| 321 | |||
| 322 | /* Check every 0.1 sec for a total of 1 sec */ | ||
| 323 | for (i = 0; i < 10; i++) { | ||
| 324 | msleep(100); | ||
| 325 | if (!is_ctrl_busy(ctrl)) | ||
| 326 | return 1; | ||
| 327 | } | ||
| 328 | |||
| 329 | return 0; | ||
| 330 | } | ||
| 331 | |||
| 305 | static inline int shpc_wait_cmd(struct controller *ctrl) | 332 | static inline int shpc_wait_cmd(struct controller *ctrl) |
| 306 | { | 333 | { |
| 307 | int retval = 0; | 334 | int retval = 0; |
| 308 | unsigned int timeout_msec = shpchp_poll_mode ? 2000 : 1000; | 335 | unsigned long timeout = msecs_to_jiffies(1000); |
| 309 | unsigned long timeout = msecs_to_jiffies(timeout_msec); | 336 | int rc; |
| 310 | int rc = wait_event_interruptible_timeout(ctrl->queue, | 337 | |
| 311 | !ctrl->cmd_busy, timeout); | 338 | if (shpchp_poll_mode) |
| 312 | if (!rc) { | 339 | rc = shpc_poll_ctrl_busy(ctrl); |
| 340 | else | ||
| 341 | rc = wait_event_interruptible_timeout(ctrl->queue, | ||
| 342 | !is_ctrl_busy(ctrl), timeout); | ||
| 343 | if (!rc && is_ctrl_busy(ctrl)) { | ||
| 313 | retval = -EIO; | 344 | retval = -EIO; |
| 314 | err("Command not completed in %d msec\n", timeout_msec); | 345 | err("Command not completed in 1000 msec\n"); |
| 315 | } else if (rc < 0) { | 346 | } else if (rc < 0) { |
| 316 | retval = -EINTR; | 347 | retval = -EINTR; |
| 317 | info("Command was interrupted by a signal\n"); | 348 | info("Command was interrupted by a signal\n"); |
| 318 | } | 349 | } |
| 319 | ctrl->cmd_busy = 0; | ||
| 320 | 350 | ||
| 321 | return retval; | 351 | return retval; |
| 322 | } | 352 | } |
| @@ -327,26 +357,15 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
| 327 | u16 cmd_status; | 357 | u16 cmd_status; |
| 328 | int retval = 0; | 358 | int retval = 0; |
| 329 | u16 temp_word; | 359 | u16 temp_word; |
| 330 | int i; | ||
| 331 | 360 | ||
| 332 | DBG_ENTER_ROUTINE | 361 | DBG_ENTER_ROUTINE |
| 333 | 362 | ||
| 334 | mutex_lock(&slot->ctrl->cmd_lock); | 363 | mutex_lock(&slot->ctrl->cmd_lock); |
| 335 | 364 | ||
| 336 | for (i = 0; i < 10; i++) { | 365 | if (!shpc_poll_ctrl_busy(ctrl)) { |
| 337 | cmd_status = shpc_readw(ctrl, CMD_STATUS); | ||
| 338 | |||
| 339 | if (!(cmd_status & 0x1)) | ||
| 340 | break; | ||
| 341 | /* Check every 0.1 sec for a total of 1 sec*/ | ||
| 342 | msleep(100); | ||
| 343 | } | ||
| 344 | |||
| 345 | cmd_status = shpc_readw(ctrl, CMD_STATUS); | ||
| 346 | |||
| 347 | if (cmd_status & 0x1) { | ||
| 348 | /* After 1 sec and and the controller is still busy */ | 366 | /* After 1 sec and and the controller is still busy */ |
| 349 | err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__); | 367 | err("%s : Controller is still busy after 1 sec.\n", |
| 368 | __FUNCTION__); | ||
| 350 | retval = -EBUSY; | 369 | retval = -EBUSY; |
| 351 | goto out; | 370 | goto out; |
| 352 | } | 371 | } |
| @@ -358,7 +377,6 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
| 358 | /* To make sure the Controller Busy bit is 0 before we send out the | 377 | /* To make sure the Controller Busy bit is 0 before we send out the |
| 359 | * command. | 378 | * command. |
| 360 | */ | 379 | */ |
| 361 | slot->ctrl->cmd_busy = 1; | ||
| 362 | shpc_writew(ctrl, CMD, temp_word); | 380 | shpc_writew(ctrl, CMD, temp_word); |
| 363 | 381 | ||
| 364 | /* | 382 | /* |
| @@ -908,7 +926,6 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) | |||
| 908 | serr_int &= ~SERR_INTR_RSVDZ_MASK; | 926 | serr_int &= ~SERR_INTR_RSVDZ_MASK; |
| 909 | shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); | 927 | shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); |
| 910 | 928 | ||
| 911 | ctrl->cmd_busy = 0; | ||
| 912 | wake_up_interruptible(&ctrl->queue); | 929 | wake_up_interruptible(&ctrl->queue); |
| 913 | } | 930 | } |
| 914 | 931 | ||
| @@ -1101,7 +1118,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
| 1101 | { | 1118 | { |
| 1102 | struct php_ctlr_state_s *php_ctlr, *p; | 1119 | struct php_ctlr_state_s *php_ctlr, *p; |
| 1103 | void *instance_id = ctrl; | 1120 | void *instance_id = ctrl; |
| 1104 | int rc, num_slots = 0; | 1121 | int rc = -1, num_slots = 0; |
| 1105 | u8 hp_slot; | 1122 | u8 hp_slot; |
| 1106 | u32 shpc_base_offset; | 1123 | u32 shpc_base_offset; |
| 1107 | u32 tempdword, slot_reg, slot_config; | 1124 | u32 tempdword, slot_reg, slot_config; |
| @@ -1167,11 +1184,15 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
| 1167 | info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, | 1184 | info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, |
| 1168 | pdev->subsystem_device); | 1185 | pdev->subsystem_device); |
| 1169 | 1186 | ||
| 1170 | if (pci_enable_device(pdev)) | 1187 | rc = pci_enable_device(pdev); |
| 1188 | if (rc) { | ||
| 1189 | err("%s: pci_enable_device failed\n", __FUNCTION__); | ||
| 1171 | goto abort_free_ctlr; | 1190 | goto abort_free_ctlr; |
| 1191 | } | ||
| 1172 | 1192 | ||
| 1173 | if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) { | 1193 | if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) { |
| 1174 | err("%s: cannot reserve MMIO region\n", __FUNCTION__); | 1194 | err("%s: cannot reserve MMIO region\n", __FUNCTION__); |
| 1195 | rc = -1; | ||
| 1175 | goto abort_free_ctlr; | 1196 | goto abort_free_ctlr; |
| 1176 | } | 1197 | } |
| 1177 | 1198 | ||
| @@ -1180,6 +1201,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
| 1180 | err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, | 1201 | err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, |
| 1181 | ctrl->mmio_size, ctrl->mmio_base); | 1202 | ctrl->mmio_size, ctrl->mmio_base); |
| 1182 | release_mem_region(ctrl->mmio_base, ctrl->mmio_size); | 1203 | release_mem_region(ctrl->mmio_base, ctrl->mmio_size); |
| 1204 | rc = -1; | ||
| 1183 | goto abort_free_ctlr; | 1205 | goto abort_free_ctlr; |
| 1184 | } | 1206 | } |
| 1185 | dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); | 1207 | dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); |
| @@ -1282,8 +1304,10 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
| 1282 | */ | 1304 | */ |
| 1283 | if (atomic_add_return(1, &shpchp_num_controllers) == 1) { | 1305 | if (atomic_add_return(1, &shpchp_num_controllers) == 1) { |
| 1284 | shpchp_wq = create_singlethread_workqueue("shpchpd"); | 1306 | shpchp_wq = create_singlethread_workqueue("shpchpd"); |
| 1285 | if (!shpchp_wq) | 1307 | if (!shpchp_wq) { |
| 1286 | return -ENOMEM; | 1308 | rc = -ENOMEM; |
| 1309 | goto abort_free_ctlr; | ||
| 1310 | } | ||
| 1287 | } | 1311 | } |
| 1288 | 1312 | ||
| 1289 | /* | 1313 | /* |
| @@ -1313,8 +1337,10 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
| 1313 | 1337 | ||
| 1314 | /* We end up here for the many possible ways to fail this API. */ | 1338 | /* We end up here for the many possible ways to fail this API. */ |
| 1315 | abort_free_ctlr: | 1339 | abort_free_ctlr: |
| 1340 | if (php_ctlr->creg) | ||
| 1341 | iounmap(php_ctlr->creg); | ||
| 1316 | kfree(php_ctlr); | 1342 | kfree(php_ctlr); |
| 1317 | abort: | 1343 | abort: |
| 1318 | DBG_LEAVE_ROUTINE | 1344 | DBG_LEAVE_ROUTINE |
| 1319 | return -1; | 1345 | return rc; |
| 1320 | } | 1346 | } |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index f9fdc54473c4..9fc9a34ef24a 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
| @@ -627,22 +627,24 @@ static int msix_capability_init(struct pci_dev *dev, | |||
| 627 | * pci_msi_supported - check whether MSI may be enabled on device | 627 | * pci_msi_supported - check whether MSI may be enabled on device |
| 628 | * @dev: pointer to the pci_dev data structure of MSI device function | 628 | * @dev: pointer to the pci_dev data structure of MSI device function |
| 629 | * | 629 | * |
| 630 | * MSI must be globally enabled and supported by the device and its root | 630 | * Look at global flags, the device itself, and its parent busses |
| 631 | * bus. But, the root bus is not easy to find since some architectures | 631 | * to return 0 if MSI are supported for the device. |
| 632 | * have virtual busses on top of the PCI hierarchy (for instance the | ||
| 633 | * hypertransport bus), while the actual bus where MSI must be supported | ||
| 634 | * is below. So we test the MSI flag on all parent busses and assume | ||
| 635 | * that no quirk will ever set the NO_MSI flag on a non-root bus. | ||
| 636 | **/ | 632 | **/ |
| 637 | static | 633 | static |
| 638 | int pci_msi_supported(struct pci_dev * dev) | 634 | int pci_msi_supported(struct pci_dev * dev) |
| 639 | { | 635 | { |
| 640 | struct pci_bus *bus; | 636 | struct pci_bus *bus; |
| 641 | 637 | ||
| 638 | /* MSI must be globally enabled and supported by the device */ | ||
| 642 | if (!pci_msi_enable || !dev || dev->no_msi) | 639 | if (!pci_msi_enable || !dev || dev->no_msi) |
| 643 | return -EINVAL; | 640 | return -EINVAL; |
| 644 | 641 | ||
| 645 | /* check MSI flags of all parent busses */ | 642 | /* Any bridge which does NOT route MSI transactions from it's |
| 643 | * secondary bus to it's primary bus must set NO_MSI flag on | ||
| 644 | * the secondary pci_bus. | ||
| 645 | * We expect only arch-specific PCI host bus controller driver | ||
| 646 | * or quirks for specific PCI bridges to be setting NO_MSI. | ||
| 647 | */ | ||
| 646 | for (bus = dev->bus; bus; bus = bus->parent) | 648 | for (bus = dev->bus; bus; bus = bus->parent) |
| 647 | if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) | 649 | if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) |
| 648 | return -EINVAL; | 650 | return -EINVAL; |
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index 67fcd176babd..3656e0349dd1 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h | |||
| @@ -9,6 +9,8 @@ | |||
| 9 | #ifndef _PORTDRV_H_ | 9 | #ifndef _PORTDRV_H_ |
| 10 | #define _PORTDRV_H_ | 10 | #define _PORTDRV_H_ |
| 11 | 11 | ||
| 12 | #include <linux/compiler.h> | ||
| 13 | |||
| 12 | #if !defined(PCI_CAP_ID_PME) | 14 | #if !defined(PCI_CAP_ID_PME) |
| 13 | #define PCI_CAP_ID_PME 1 | 15 | #define PCI_CAP_ID_PME 1 |
| 14 | #endif | 16 | #endif |
| @@ -39,7 +41,7 @@ extern int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state); | |||
| 39 | extern int pcie_port_device_resume(struct pci_dev *dev); | 41 | extern int pcie_port_device_resume(struct pci_dev *dev); |
| 40 | #endif | 42 | #endif |
| 41 | extern void pcie_port_device_remove(struct pci_dev *dev); | 43 | extern void pcie_port_device_remove(struct pci_dev *dev); |
| 42 | extern int pcie_port_bus_register(void); | 44 | extern int __must_check pcie_port_bus_register(void); |
| 43 | extern void pcie_port_bus_unregister(void); | 45 | extern void pcie_port_bus_unregister(void); |
| 44 | 46 | ||
| 45 | #endif /* _PORTDRV_H_ */ | 47 | #endif /* _PORTDRV_H_ */ |
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index bd6615b4d40e..b20a9b81dae2 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) | 6 | * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/compiler.h> | ||
| 10 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 11 | #include <linux/pci.h> | 10 | #include <linux/pci.h> |
| 12 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
| @@ -401,7 +400,7 @@ void pcie_port_device_remove(struct pci_dev *dev) | |||
| 401 | pci_disable_msi(dev); | 400 | pci_disable_msi(dev); |
| 402 | } | 401 | } |
| 403 | 402 | ||
| 404 | int __must_check pcie_port_bus_register(void) | 403 | int pcie_port_bus_register(void) |
| 405 | { | 404 | { |
| 406 | return bus_register(&pcie_port_bus_type); | 405 | return bus_register(&pcie_port_bus_type); |
| 407 | } | 406 | } |
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 037690e08f5f..b4da7954611e 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
| @@ -37,7 +37,6 @@ static int pcie_portdrv_save_config(struct pci_dev *dev) | |||
| 37 | return pci_save_state(dev); | 37 | return pci_save_state(dev); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | #ifdef CONFIG_PM | ||
| 41 | static int pcie_portdrv_restore_config(struct pci_dev *dev) | 40 | static int pcie_portdrv_restore_config(struct pci_dev *dev) |
| 42 | { | 41 | { |
| 43 | int retval; | 42 | int retval; |
| @@ -50,6 +49,7 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev) | |||
| 50 | return 0; | 49 | return 0; |
| 51 | } | 50 | } |
| 52 | 51 | ||
| 52 | #ifdef CONFIG_PM | ||
| 53 | static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state) | 53 | static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state) |
| 54 | { | 54 | { |
| 55 | int ret = pcie_port_device_suspend(dev, state); | 55 | int ret = pcie_port_device_suspend(dev, state); |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index a3b0a5eb5054..e159d6604494 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
| @@ -1067,3 +1067,95 @@ EXPORT_SYMBOL(pci_scan_bridge); | |||
| 1067 | EXPORT_SYMBOL(pci_scan_single_device); | 1067 | EXPORT_SYMBOL(pci_scan_single_device); |
| 1068 | EXPORT_SYMBOL_GPL(pci_scan_child_bus); | 1068 | EXPORT_SYMBOL_GPL(pci_scan_child_bus); |
| 1069 | #endif | 1069 | #endif |
| 1070 | |||
| 1071 | static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev *b) | ||
| 1072 | { | ||
| 1073 | if (pci_domain_nr(a->bus) < pci_domain_nr(b->bus)) return -1; | ||
| 1074 | else if (pci_domain_nr(a->bus) > pci_domain_nr(b->bus)) return 1; | ||
| 1075 | |||
| 1076 | if (a->bus->number < b->bus->number) return -1; | ||
| 1077 | else if (a->bus->number > b->bus->number) return 1; | ||
| 1078 | |||
| 1079 | if (a->devfn < b->devfn) return -1; | ||
| 1080 | else if (a->devfn > b->devfn) return 1; | ||
| 1081 | |||
| 1082 | return 0; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | /* | ||
| 1086 | * Yes, this forcably breaks the klist abstraction temporarily. It | ||
| 1087 | * just wants to sort the klist, not change reference counts and | ||
| 1088 | * take/drop locks rapidly in the process. It does all this while | ||
| 1089 | * holding the lock for the list, so objects can't otherwise be | ||
| 1090 | * added/removed while we're swizzling. | ||
| 1091 | */ | ||
| 1092 | static void __init pci_insertion_sort_klist(struct pci_dev *a, struct list_head *list) | ||
| 1093 | { | ||
| 1094 | struct list_head *pos; | ||
| 1095 | struct klist_node *n; | ||
| 1096 | struct device *dev; | ||
| 1097 | struct pci_dev *b; | ||
| 1098 | |||
| 1099 | list_for_each(pos, list) { | ||
| 1100 | n = container_of(pos, struct klist_node, n_node); | ||
| 1101 | dev = container_of(n, struct device, knode_bus); | ||
| 1102 | b = to_pci_dev(dev); | ||
| 1103 | if (pci_sort_bf_cmp(a, b) <= 0) { | ||
| 1104 | list_move_tail(&a->dev.knode_bus.n_node, &b->dev.knode_bus.n_node); | ||
| 1105 | return; | ||
| 1106 | } | ||
| 1107 | } | ||
| 1108 | list_move_tail(&a->dev.knode_bus.n_node, list); | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | static void __init pci_sort_breadthfirst_klist(void) | ||
| 1112 | { | ||
| 1113 | LIST_HEAD(sorted_devices); | ||
| 1114 | struct list_head *pos, *tmp; | ||
| 1115 | struct klist_node *n; | ||
| 1116 | struct device *dev; | ||
| 1117 | struct pci_dev *pdev; | ||
| 1118 | |||
| 1119 | spin_lock(&pci_bus_type.klist_devices.k_lock); | ||
| 1120 | list_for_each_safe(pos, tmp, &pci_bus_type.klist_devices.k_list) { | ||
| 1121 | n = container_of(pos, struct klist_node, n_node); | ||
| 1122 | dev = container_of(n, struct device, knode_bus); | ||
| 1123 | pdev = to_pci_dev(dev); | ||
| 1124 | pci_insertion_sort_klist(pdev, &sorted_devices); | ||
| 1125 | } | ||
| 1126 | list_splice(&sorted_devices, &pci_bus_type.klist_devices.k_list); | ||
| 1127 | spin_unlock(&pci_bus_type.klist_devices.k_lock); | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | static void __init pci_insertion_sort_devices(struct pci_dev *a, struct list_head *list) | ||
| 1131 | { | ||
| 1132 | struct pci_dev *b; | ||
| 1133 | |||
| 1134 | list_for_each_entry(b, list, global_list) { | ||
| 1135 | if (pci_sort_bf_cmp(a, b) <= 0) { | ||
| 1136 | list_move_tail(&a->global_list, &b->global_list); | ||
| 1137 | return; | ||
| 1138 | } | ||
| 1139 | } | ||
| 1140 | list_move_tail(&a->global_list, list); | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | static void __init pci_sort_breadthfirst_devices(void) | ||
| 1144 | { | ||
| 1145 | LIST_HEAD(sorted_devices); | ||
| 1146 | struct pci_dev *dev, *tmp; | ||
| 1147 | |||
| 1148 | down_write(&pci_bus_sem); | ||
| 1149 | list_for_each_entry_safe(dev, tmp, &pci_devices, global_list) { | ||
| 1150 | pci_insertion_sort_devices(dev, &sorted_devices); | ||
| 1151 | } | ||
| 1152 | list_splice(&sorted_devices, &pci_devices); | ||
| 1153 | up_write(&pci_bus_sem); | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | void __init pci_sort_breadthfirst(void) | ||
| 1157 | { | ||
| 1158 | pci_sort_breadthfirst_devices(); | ||
| 1159 | pci_sort_breadthfirst_klist(); | ||
| 1160 | } | ||
| 1161 | |||
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 23b599d6a9d5..e8a7f1b1b2bc 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
| @@ -453,6 +453,12 @@ static void __devinit quirk_ich6_lpc_acpi(struct pci_dev *dev) | |||
| 453 | } | 453 | } |
| 454 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc_acpi ); | 454 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc_acpi ); |
| 455 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi ); | 455 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi ); |
| 456 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, quirk_ich6_lpc_acpi ); | ||
| 457 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, quirk_ich6_lpc_acpi ); | ||
| 458 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, quirk_ich6_lpc_acpi ); | ||
| 459 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, quirk_ich6_lpc_acpi ); | ||
| 460 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, quirk_ich6_lpc_acpi ); | ||
| 461 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, quirk_ich6_lpc_acpi ); | ||
| 456 | 462 | ||
| 457 | /* | 463 | /* |
| 458 | * VIA ACPI: One IO region pointed to by longword at | 464 | * VIA ACPI: One IO region pointed to by longword at |
| @@ -648,11 +654,43 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vi | |||
| 648 | * Some of the on-chip devices are actually '586 devices' so they are | 654 | * Some of the on-chip devices are actually '586 devices' so they are |
| 649 | * listed here. | 655 | * listed here. |
| 650 | */ | 656 | */ |
| 657 | |||
| 658 | static int via_irq_fixup_needed = -1; | ||
| 659 | |||
| 660 | /* | ||
| 661 | * As some VIA hardware is available in PCI-card form, we need to restrict | ||
| 662 | * this quirk to VIA PCI hardware built onto VIA-based motherboards only. | ||
| 663 | * We try to locate a VIA southbridge before deciding whether the quirk | ||
| 664 | * should be applied. | ||
| 665 | */ | ||
| 666 | static const struct pci_device_id via_irq_fixup_tbl[] = { | ||
| 667 | { | ||
| 668 | .vendor = PCI_VENDOR_ID_VIA, | ||
| 669 | .device = PCI_ANY_ID, | ||
| 670 | .subvendor = PCI_ANY_ID, | ||
| 671 | .subdevice = PCI_ANY_ID, | ||
| 672 | .class = PCI_CLASS_BRIDGE_ISA << 8, | ||
| 673 | .class_mask = 0xffff00, | ||
| 674 | }, | ||
| 675 | { 0, }, | ||
| 676 | }; | ||
| 677 | |||
| 651 | static void quirk_via_irq(struct pci_dev *dev) | 678 | static void quirk_via_irq(struct pci_dev *dev) |
| 652 | { | 679 | { |
| 653 | u8 irq, new_irq; | 680 | u8 irq, new_irq; |
| 654 | 681 | ||
| 655 | new_irq = dev->irq & 0xf; | 682 | if (via_irq_fixup_needed == -1) |
| 683 | via_irq_fixup_needed = pci_dev_present(via_irq_fixup_tbl); | ||
| 684 | |||
| 685 | if (!via_irq_fixup_needed) | ||
| 686 | return; | ||
| 687 | |||
| 688 | new_irq = dev->irq; | ||
| 689 | |||
| 690 | /* Don't quirk interrupts outside the legacy IRQ range */ | ||
| 691 | if (!new_irq || new_irq > 15) | ||
| 692 | return; | ||
| 693 | |||
| 656 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); | 694 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); |
| 657 | if (new_irq != irq) { | 695 | if (new_irq != irq) { |
| 658 | printk(KERN_INFO "PCI: VIA IRQ fixup for %s, from %d to %d\n", | 696 | printk(KERN_INFO "PCI: VIA IRQ fixup for %s, from %d to %d\n", |
| @@ -661,14 +699,7 @@ static void quirk_via_irq(struct pci_dev *dev) | |||
| 661 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); | 699 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); |
| 662 | } | 700 | } |
| 663 | } | 701 | } |
| 664 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_via_irq); | 702 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq); |
| 665 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, quirk_via_irq); | ||
| 666 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irq); | ||
| 667 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_irq); | ||
| 668 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235_USB_2, quirk_via_irq); | ||
| 669 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_irq); | ||
| 670 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_irq); | ||
| 671 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irq); | ||
| 672 | 703 | ||
| 673 | /* | 704 | /* |
| 674 | * VIA VT82C598 has its device ID settable and many BIOSes | 705 | * VIA VT82C598 has its device ID settable and many BIOSes |
| @@ -1588,6 +1619,51 @@ static void __devinit fixup_rev1_53c810(struct pci_dev* dev) | |||
| 1588 | } | 1619 | } |
| 1589 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); | 1620 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); |
| 1590 | 1621 | ||
| 1622 | /* | ||
| 1623 | * Fixup to mark boot BIOS video selected by BIOS before it changes | ||
| 1624 | * | ||
| 1625 | * From information provided by "Jon Smirl" <jonsmirl@gmail.com> | ||
| 1626 | * | ||
| 1627 | * The standard boot ROM sequence for an x86 machine uses the BIOS | ||
| 1628 | * to select an initial video card for boot display. This boot video | ||
| 1629 | * card will have it's BIOS copied to C0000 in system RAM. | ||
| 1630 | * IORESOURCE_ROM_SHADOW is used to associate the boot video | ||
| 1631 | * card with this copy. On laptops this copy has to be used since | ||
| 1632 | * the main ROM may be compressed or combined with another image. | ||
| 1633 | * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW | ||
| 1634 | * is marked here since the boot video device will be the only enabled | ||
| 1635 | * video device at this point. | ||
| 1636 | */ | ||
| 1637 | |||
| 1638 | static void __devinit fixup_video(struct pci_dev *pdev) | ||
| 1639 | { | ||
| 1640 | struct pci_dev *bridge; | ||
| 1641 | struct pci_bus *bus; | ||
| 1642 | u16 config; | ||
| 1643 | |||
| 1644 | if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) | ||
| 1645 | return; | ||
| 1646 | |||
| 1647 | /* Is VGA routed to us? */ | ||
| 1648 | bus = pdev->bus; | ||
| 1649 | while (bus) { | ||
| 1650 | bridge = bus->self; | ||
| 1651 | if (bridge) { | ||
| 1652 | pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, | ||
| 1653 | &config); | ||
| 1654 | if (!(config & PCI_BRIDGE_CTL_VGA)) | ||
| 1655 | return; | ||
| 1656 | } | ||
| 1657 | bus = bus->parent; | ||
| 1658 | } | ||
| 1659 | pci_read_config_word(pdev, PCI_COMMAND, &config); | ||
| 1660 | if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { | ||
| 1661 | pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; | ||
| 1662 | printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev)); | ||
| 1663 | } | ||
| 1664 | } | ||
| 1665 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, fixup_video); | ||
| 1666 | |||
| 1591 | 1667 | ||
| 1592 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) | 1668 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) |
| 1593 | { | 1669 | { |
| @@ -1764,7 +1840,7 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) | |||
| 1764 | /* check HT MSI cap on this chipset and the root one. | 1840 | /* check HT MSI cap on this chipset and the root one. |
| 1765 | * a single one having MSI is enough to be sure that MSI are supported. | 1841 | * a single one having MSI is enough to be sure that MSI are supported. |
| 1766 | */ | 1842 | */ |
| 1767 | pdev = pci_find_slot(dev->bus->number, 0); | 1843 | pdev = pci_get_slot(dev->bus, 0); |
| 1768 | if (dev->subordinate && !msi_ht_cap_enabled(dev) | 1844 | if (dev->subordinate && !msi_ht_cap_enabled(dev) |
| 1769 | && !msi_ht_cap_enabled(pdev)) { | 1845 | && !msi_ht_cap_enabled(pdev)) { |
| 1770 | printk(KERN_WARNING "PCI: MSI quirk detected. " | 1846 | printk(KERN_WARNING "PCI: MSI quirk detected. " |
| @@ -1772,6 +1848,7 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) | |||
| 1772 | pci_name(dev)); | 1848 | pci_name(dev)); |
| 1773 | dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; | 1849 | dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; |
| 1774 | } | 1850 | } |
| 1851 | pci_dev_put(pdev); | ||
| 1775 | } | 1852 | } |
| 1776 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, | 1853 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, |
| 1777 | quirk_nvidia_ck804_msi_ht_cap); | 1854 | quirk_nvidia_ck804_msi_ht_cap); |
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index f5ee7ce16fa6..43e4a49f2cc4 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c | |||
| @@ -71,7 +71,10 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) | |||
| 71 | void __iomem *image; | 71 | void __iomem *image; |
| 72 | int last_image; | 72 | int last_image; |
| 73 | 73 | ||
| 74 | /* IORESOURCE_ROM_SHADOW only set on x86 */ | 74 | /* |
| 75 | * IORESOURCE_ROM_SHADOW set if the VGA enable bit of the Bridge Control | ||
| 76 | * register is set for embedded VGA. | ||
| 77 | */ | ||
| 75 | if (res->flags & IORESOURCE_ROM_SHADOW) { | 78 | if (res->flags & IORESOURCE_ROM_SHADOW) { |
| 76 | /* primary video rom always starts here */ | 79 | /* primary video rom always starts here */ |
| 77 | start = (loff_t)0xC0000; | 80 | start = (loff_t)0xC0000; |
diff --git a/drivers/pci/search.c b/drivers/pci/search.c index d529462d1b53..2f13eba5d5ae 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c | |||
| @@ -140,6 +140,31 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) | |||
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | /** | 142 | /** |
| 143 | * pci_get_bus_and_slot - locate PCI device from a given PCI slot | ||
| 144 | * @bus: number of PCI bus on which desired PCI device resides | ||
| 145 | * @devfn: encodes number of PCI slot in which the desired PCI | ||
| 146 | * device resides and the logical device number within that slot | ||
| 147 | * in case of multi-function devices. | ||
| 148 | * | ||
| 149 | * Given a PCI bus and slot/function number, the desired PCI device | ||
| 150 | * is located in system global list of PCI devices. If the device | ||
| 151 | * is found, a pointer to its data structure is returned. If no | ||
| 152 | * device is found, %NULL is returned. The returned device has its | ||
| 153 | * reference count bumped by one. | ||
| 154 | */ | ||
| 155 | |||
| 156 | struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn) | ||
| 157 | { | ||
| 158 | struct pci_dev *dev = NULL; | ||
| 159 | |||
| 160 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | ||
| 161 | if (dev->bus->number == bus && dev->devfn == devfn) | ||
| 162 | return dev; | ||
| 163 | } | ||
| 164 | return NULL; | ||
| 165 | } | ||
| 166 | |||
| 167 | /** | ||
| 143 | * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id | 168 | * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id |
| 144 | * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids | 169 | * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids |
| 145 | * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids | 170 | * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids |
| @@ -274,6 +299,45 @@ pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from) | |||
| 274 | return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); | 299 | return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); |
| 275 | } | 300 | } |
| 276 | 301 | ||
| 302 | /** | ||
| 303 | * pci_get_device_reverse - begin or continue searching for a PCI device by vendor/device id | ||
| 304 | * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids | ||
| 305 | * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids | ||
| 306 | * @from: Previous PCI device found in search, or %NULL for new search. | ||
| 307 | * | ||
| 308 | * Iterates through the list of known PCI devices in the reverse order of | ||
| 309 | * pci_get_device. | ||
| 310 | * If a PCI device is found with a matching @vendor and @device, the reference | ||
| 311 | * count to the device is incremented and a pointer to its device structure | ||
| 312 | * is returned Otherwise, %NULL is returned. A new search is initiated by | ||
| 313 | * passing %NULL as the @from argument. Otherwise if @from is not %NULL, | ||
| 314 | * searches continue from next device on the global list. The reference | ||
| 315 | * count for @from is always decremented if it is not %NULL. | ||
| 316 | */ | ||
| 317 | struct pci_dev * | ||
| 318 | pci_get_device_reverse(unsigned int vendor, unsigned int device, struct pci_dev *from) | ||
| 319 | { | ||
| 320 | struct list_head *n; | ||
| 321 | struct pci_dev *dev; | ||
| 322 | |||
| 323 | WARN_ON(in_interrupt()); | ||
| 324 | down_read(&pci_bus_sem); | ||
| 325 | n = from ? from->global_list.prev : pci_devices.prev; | ||
| 326 | |||
| 327 | while (n && (n != &pci_devices)) { | ||
| 328 | dev = pci_dev_g(n); | ||
| 329 | if ((vendor == PCI_ANY_ID || dev->vendor == vendor) && | ||
| 330 | (device == PCI_ANY_ID || dev->device == device)) | ||
| 331 | goto exit; | ||
| 332 | n = n->prev; | ||
| 333 | } | ||
| 334 | dev = NULL; | ||
| 335 | exit: | ||
| 336 | dev = pci_dev_get(dev); | ||
| 337 | up_read(&pci_bus_sem); | ||
| 338 | pci_dev_put(from); | ||
| 339 | return dev; | ||
| 340 | } | ||
| 277 | 341 | ||
| 278 | /** | 342 | /** |
| 279 | * pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id | 343 | * pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id |
| @@ -382,12 +446,16 @@ exit: | |||
| 382 | } | 446 | } |
| 383 | EXPORT_SYMBOL(pci_dev_present); | 447 | EXPORT_SYMBOL(pci_dev_present); |
| 384 | 448 | ||
| 385 | EXPORT_SYMBOL(pci_find_bus); | ||
| 386 | EXPORT_SYMBOL(pci_find_next_bus); | ||
| 387 | EXPORT_SYMBOL(pci_find_device); | 449 | EXPORT_SYMBOL(pci_find_device); |
| 388 | EXPORT_SYMBOL(pci_find_device_reverse); | 450 | EXPORT_SYMBOL(pci_find_device_reverse); |
| 389 | EXPORT_SYMBOL(pci_find_slot); | 451 | EXPORT_SYMBOL(pci_find_slot); |
| 452 | /* For boot time work */ | ||
| 453 | EXPORT_SYMBOL(pci_find_bus); | ||
| 454 | EXPORT_SYMBOL(pci_find_next_bus); | ||
| 455 | /* For everyone */ | ||
| 390 | EXPORT_SYMBOL(pci_get_device); | 456 | EXPORT_SYMBOL(pci_get_device); |
| 457 | EXPORT_SYMBOL(pci_get_device_reverse); | ||
| 391 | EXPORT_SYMBOL(pci_get_subsys); | 458 | EXPORT_SYMBOL(pci_get_subsys); |
| 392 | EXPORT_SYMBOL(pci_get_slot); | 459 | EXPORT_SYMBOL(pci_get_slot); |
| 460 | EXPORT_SYMBOL(pci_get_bus_and_slot); | ||
| 393 | EXPORT_SYMBOL(pci_get_class); | 461 | EXPORT_SYMBOL(pci_get_class); |
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index dc79b0a0059f..379048fdf05d 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
| @@ -776,21 +776,32 @@ static void pnpacpi_encode_dma(struct acpi_resource *resource, | |||
| 776 | struct resource *p) | 776 | struct resource *p) |
| 777 | { | 777 | { |
| 778 | /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ | 778 | /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ |
| 779 | if (p->flags & IORESOURCE_DMA_COMPATIBLE) | 779 | switch (p->flags & IORESOURCE_DMA_SPEED_MASK) { |
| 780 | resource->data.dma.type = ACPI_COMPATIBILITY; | 780 | case IORESOURCE_DMA_TYPEA: |
| 781 | else if (p->flags & IORESOURCE_DMA_TYPEA) | 781 | resource->data.dma.type = ACPI_TYPE_A; |
| 782 | resource->data.dma.type = ACPI_TYPE_A; | 782 | break; |
| 783 | else if (p->flags & IORESOURCE_DMA_TYPEB) | 783 | case IORESOURCE_DMA_TYPEB: |
| 784 | resource->data.dma.type = ACPI_TYPE_B; | 784 | resource->data.dma.type = ACPI_TYPE_B; |
| 785 | else if (p->flags & IORESOURCE_DMA_TYPEF) | 785 | break; |
| 786 | resource->data.dma.type = ACPI_TYPE_F; | 786 | case IORESOURCE_DMA_TYPEF: |
| 787 | if (p->flags & IORESOURCE_DMA_8BIT) | 787 | resource->data.dma.type = ACPI_TYPE_F; |
| 788 | resource->data.dma.transfer = ACPI_TRANSFER_8; | 788 | break; |
| 789 | else if (p->flags & IORESOURCE_DMA_8AND16BIT) | 789 | default: |
| 790 | resource->data.dma.transfer = ACPI_TRANSFER_8_16; | 790 | resource->data.dma.type = ACPI_COMPATIBILITY; |
| 791 | else if (p->flags & IORESOURCE_DMA_16BIT) | 791 | } |
| 792 | resource->data.dma.transfer = ACPI_TRANSFER_16; | 792 | |
| 793 | resource->data.dma.bus_master = p->flags & IORESOURCE_DMA_MASTER; | 793 | switch (p->flags & IORESOURCE_DMA_TYPE_MASK) { |
| 794 | case IORESOURCE_DMA_8BIT: | ||
| 795 | resource->data.dma.transfer = ACPI_TRANSFER_8; | ||
| 796 | break; | ||
| 797 | case IORESOURCE_DMA_8AND16BIT: | ||
| 798 | resource->data.dma.transfer = ACPI_TRANSFER_8_16; | ||
| 799 | break; | ||
| 800 | default: | ||
| 801 | resource->data.dma.transfer = ACPI_TRANSFER_16; | ||
| 802 | } | ||
| 803 | |||
| 804 | resource->data.dma.bus_master = !!(p->flags & IORESOURCE_DMA_MASTER); | ||
| 794 | resource->data.dma.channel_count = 1; | 805 | resource->data.dma.channel_count = 1; |
| 795 | resource->data.dma.channels[0] = p->start; | 806 | resource->data.dma.channels[0] = p->start; |
| 796 | } | 807 | } |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 5c604f5fad67..4689e2a699c0 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
| @@ -443,6 +443,7 @@ extern void pci_remove_bus(struct pci_bus *b); | |||
| 443 | extern void pci_remove_bus_device(struct pci_dev *dev); | 443 | extern void pci_remove_bus_device(struct pci_dev *dev); |
| 444 | extern void pci_stop_bus_device(struct pci_dev *dev); | 444 | extern void pci_stop_bus_device(struct pci_dev *dev); |
| 445 | void pci_setup_cardbus(struct pci_bus *bus); | 445 | void pci_setup_cardbus(struct pci_bus *bus); |
| 446 | extern void pci_sort_breadthfirst(void); | ||
| 446 | 447 | ||
| 447 | /* Generic PCI functions exported to card drivers */ | 448 | /* Generic PCI functions exported to card drivers */ |
| 448 | 449 | ||
| @@ -452,13 +453,14 @@ struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn); | |||
| 452 | int pci_find_capability (struct pci_dev *dev, int cap); | 453 | int pci_find_capability (struct pci_dev *dev, int cap); |
| 453 | int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap); | 454 | int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap); |
| 454 | int pci_find_ext_capability (struct pci_dev *dev, int cap); | 455 | int pci_find_ext_capability (struct pci_dev *dev, int cap); |
| 455 | struct pci_bus * pci_find_next_bus(const struct pci_bus *from); | 456 | struct pci_bus *pci_find_next_bus(const struct pci_bus *from); |
| 456 | 457 | ||
| 457 | struct pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from); | 458 | struct pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from); |
| 458 | struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device, | 459 | struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device, |
| 459 | unsigned int ss_vendor, unsigned int ss_device, | 460 | unsigned int ss_vendor, unsigned int ss_device, |
| 460 | struct pci_dev *from); | 461 | struct pci_dev *from); |
| 461 | struct pci_dev *pci_get_slot (struct pci_bus *bus, unsigned int devfn); | 462 | struct pci_dev *pci_get_slot (struct pci_bus *bus, unsigned int devfn); |
| 463 | struct pci_dev *pci_get_bus_and_slot (unsigned int bus, unsigned int devfn); | ||
| 462 | struct pci_dev *pci_get_class (unsigned int class, struct pci_dev *from); | 464 | struct pci_dev *pci_get_class (unsigned int class, struct pci_dev *from); |
| 463 | int pci_dev_present(const struct pci_device_id *ids); | 465 | int pci_dev_present(const struct pci_device_id *ids); |
| 464 | 466 | ||
diff --git a/drivers/pci/hotplug/pci_hotplug.h b/include/linux/pci_hotplug.h index 772523dc3860..a675a05c4091 100644 --- a/drivers/pci/hotplug/pci_hotplug.h +++ b/include/linux/pci_hotplug.h | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | * along with this program; if not, write to the Free Software | 22 | * along with this program; if not, write to the Free Software |
| 23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 24 | * | 24 | * |
| 25 | * Send feedback to <greg@kroah.com> | 25 | * Send feedback to <kristen.c.accardi@intel.com> |
| 26 | * | 26 | * |
| 27 | */ | 27 | */ |
| 28 | #ifndef _PCI_HOTPLUG_H | 28 | #ifndef _PCI_HOTPLUG_H |
