diff options
| author | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-11-22 13:06:44 -0500 |
|---|---|---|
| committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-11-22 13:06:44 -0500 |
| commit | 0bd2af46839ad6262d25714a6ec0365db9d6b98f (patch) | |
| tree | dcced72d230d69fd0c5816ac6dd03ab84799a93e /drivers/pci | |
| parent | e138a5d2356729b8752e88520cc1525fae9794ac (diff) | |
| parent | f26b90440cd74c78fe10c9bd5160809704a9627c (diff) | |
Merge ../scsi-rc-fixes-2.6
Diffstat (limited to 'drivers/pci')
41 files changed, 447 insertions, 486 deletions
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 30294127a0aa..5f1b9f58070e 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig | |||
| @@ -19,7 +19,7 @@ config PCI_MSI | |||
| 19 | 19 | ||
| 20 | config PCI_MULTITHREAD_PROBE | 20 | config PCI_MULTITHREAD_PROBE |
| 21 | bool "PCI Multi-threaded probe (EXPERIMENTAL)" | 21 | bool "PCI Multi-threaded probe (EXPERIMENTAL)" |
| 22 | depends on PCI && EXPERIMENTAL | 22 | depends on PCI && EXPERIMENTAL && BROKEN |
| 23 | help | 23 | help |
| 24 | Say Y here if you want the PCI core to spawn a new thread for | 24 | Say Y here if you want the PCI core to spawn a new thread for |
| 25 | every PCI device that is probed. This can cause a huge | 25 | every PCI device that is probed. This can cause a huge |
| @@ -55,7 +55,7 @@ config PCI_DEBUG | |||
| 55 | config HT_IRQ | 55 | config HT_IRQ |
| 56 | bool "Interrupts on hypertransport devices" | 56 | bool "Interrupts on hypertransport devices" |
| 57 | default y | 57 | default y |
| 58 | depends on X86_LOCAL_APIC && X86_IO_APIC | 58 | depends on PCI && X86_LOCAL_APIC && X86_IO_APIC |
| 59 | help | 59 | help |
| 60 | This allows native hypertransport devices to use interrupts. | 60 | This allows native hypertransport devices to use interrupts. |
| 61 | 61 | ||
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..16167b016266 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); |
| @@ -1807,8 +1807,8 @@ u8 acpiphp_get_power_status(struct acpiphp_slot *slot) | |||
| 1807 | 1807 | ||
| 1808 | 1808 | ||
| 1809 | /* | 1809 | /* |
| 1810 | * latch closed: 1 | 1810 | * latch open: 1 |
| 1811 | * latch open: 0 | 1811 | * latch closed: 0 |
| 1812 | */ | 1812 | */ |
| 1813 | u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) | 1813 | u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) |
| 1814 | { | 1814 | { |
| @@ -1816,7 +1816,7 @@ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) | |||
| 1816 | 1816 | ||
| 1817 | sta = get_slot_status(slot); | 1817 | sta = get_slot_status(slot); |
| 1818 | 1818 | ||
| 1819 | return (sta & ACPI_STA_SHOW_IN_UI) ? 1 : 0; | 1819 | return (sta & ACPI_STA_SHOW_IN_UI) ? 0 : 1; |
| 1820 | } | 1820 | } |
| 1821 | 1821 | ||
| 1822 | 1822 | ||
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.h b/drivers/pci/hotplug/pci_hotplug.h deleted file mode 100644 index 772523dc3860..000000000000 --- a/drivers/pci/hotplug/pci_hotplug.h +++ /dev/null | |||
| @@ -1,236 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * PCI HotPlug Core Functions | ||
| 3 | * | ||
| 4 | * Copyright (C) 1995,2001 Compaq Computer Corporation | ||
| 5 | * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) | ||
| 6 | * Copyright (C) 2001 IBM Corp. | ||
| 7 | * | ||
| 8 | * All rights reserved. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or (at | ||
| 13 | * your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, but | ||
| 16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
| 18 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
| 19 | * details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the Free Software | ||
| 23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 24 | * | ||
| 25 | * Send feedback to <greg@kroah.com> | ||
| 26 | * | ||
| 27 | */ | ||
| 28 | #ifndef _PCI_HOTPLUG_H | ||
| 29 | #define _PCI_HOTPLUG_H | ||
| 30 | |||
| 31 | |||
| 32 | /* These values come from the PCI Hotplug Spec */ | ||
| 33 | enum pci_bus_speed { | ||
| 34 | PCI_SPEED_33MHz = 0x00, | ||
| 35 | PCI_SPEED_66MHz = 0x01, | ||
| 36 | PCI_SPEED_66MHz_PCIX = 0x02, | ||
| 37 | PCI_SPEED_100MHz_PCIX = 0x03, | ||
| 38 | PCI_SPEED_133MHz_PCIX = 0x04, | ||
| 39 | PCI_SPEED_66MHz_PCIX_ECC = 0x05, | ||
| 40 | PCI_SPEED_100MHz_PCIX_ECC = 0x06, | ||
| 41 | PCI_SPEED_133MHz_PCIX_ECC = 0x07, | ||
| 42 | PCI_SPEED_66MHz_PCIX_266 = 0x09, | ||
| 43 | PCI_SPEED_100MHz_PCIX_266 = 0x0a, | ||
| 44 | PCI_SPEED_133MHz_PCIX_266 = 0x0b, | ||
| 45 | PCI_SPEED_66MHz_PCIX_533 = 0x11, | ||
| 46 | PCI_SPEED_100MHz_PCIX_533 = 0x12, | ||
| 47 | PCI_SPEED_133MHz_PCIX_533 = 0x13, | ||
| 48 | PCI_SPEED_UNKNOWN = 0xff, | ||
| 49 | }; | ||
| 50 | |||
| 51 | /* These values come from the PCI Express Spec */ | ||
| 52 | enum pcie_link_width { | ||
| 53 | PCIE_LNK_WIDTH_RESRV = 0x00, | ||
| 54 | PCIE_LNK_X1 = 0x01, | ||
| 55 | PCIE_LNK_X2 = 0x02, | ||
| 56 | PCIE_LNK_X4 = 0x04, | ||
| 57 | PCIE_LNK_X8 = 0x08, | ||
| 58 | PCIE_LNK_X12 = 0x0C, | ||
| 59 | PCIE_LNK_X16 = 0x10, | ||
| 60 | PCIE_LNK_X32 = 0x20, | ||
| 61 | PCIE_LNK_WIDTH_UNKNOWN = 0xFF, | ||
| 62 | }; | ||
| 63 | |||
| 64 | enum pcie_link_speed { | ||
| 65 | PCIE_2PT5GB = 0x14, | ||
| 66 | PCIE_LNK_SPEED_UNKNOWN = 0xFF, | ||
| 67 | }; | ||
| 68 | |||
| 69 | struct hotplug_slot; | ||
| 70 | struct hotplug_slot_attribute { | ||
| 71 | struct attribute attr; | ||
| 72 | ssize_t (*show)(struct hotplug_slot *, char *); | ||
| 73 | ssize_t (*store)(struct hotplug_slot *, const char *, size_t); | ||
| 74 | }; | ||
| 75 | #define to_hotplug_attr(n) container_of(n, struct hotplug_slot_attribute, attr); | ||
| 76 | |||
| 77 | /** | ||
| 78 | * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use | ||
| 79 | * @owner: The module owner of this structure | ||
| 80 | * @enable_slot: Called when the user wants to enable a specific pci slot | ||
| 81 | * @disable_slot: Called when the user wants to disable a specific pci slot | ||
| 82 | * @set_attention_status: Called to set the specific slot's attention LED to | ||
| 83 | * the specified value | ||
| 84 | * @hardware_test: Called to run a specified hardware test on the specified | ||
| 85 | * slot. | ||
| 86 | * @get_power_status: Called to get the current power status of a slot. | ||
| 87 | * If this field is NULL, the value passed in the struct hotplug_slot_info | ||
| 88 | * will be used when this value is requested by a user. | ||
| 89 | * @get_attention_status: Called to get the current attention status of a slot. | ||
| 90 | * If this field is NULL, the value passed in the struct hotplug_slot_info | ||
| 91 | * will be used when this value is requested by a user. | ||
| 92 | * @get_latch_status: Called to get the current latch status of a slot. | ||
| 93 | * If this field is NULL, the value passed in the struct hotplug_slot_info | ||
| 94 | * will be used when this value is requested by a user. | ||
| 95 | * @get_adapter_status: Called to get see if an adapter is present in the slot or not. | ||
| 96 | * If this field is NULL, the value passed in the struct hotplug_slot_info | ||
| 97 | * will be used when this value is requested by a user. | ||
| 98 | * @get_address: Called to get pci address of a slot. | ||
| 99 | * If this field is NULL, the value passed in the struct hotplug_slot_info | ||
| 100 | * will be used when this value is requested by a user. | ||
| 101 | * @get_max_bus_speed: Called to get the max bus speed for a slot. | ||
| 102 | * If this field is NULL, the value passed in the struct hotplug_slot_info | ||
| 103 | * will be used when this value is requested by a user. | ||
| 104 | * @get_cur_bus_speed: Called to get the current bus speed for a slot. | ||
| 105 | * If this field is NULL, the value passed in the struct hotplug_slot_info | ||
| 106 | * will be used when this value is requested by a user. | ||
| 107 | * | ||
| 108 | * The table of function pointers that is passed to the hotplug pci core by a | ||
| 109 | * hotplug pci driver. These functions are called by the hotplug pci core when | ||
| 110 | * the user wants to do something to a specific slot (query it for information, | ||
| 111 | * set an LED, enable / disable power, etc.) | ||
| 112 | */ | ||
| 113 | struct hotplug_slot_ops { | ||
| 114 | struct module *owner; | ||
| 115 | int (*enable_slot) (struct hotplug_slot *slot); | ||
| 116 | int (*disable_slot) (struct hotplug_slot *slot); | ||
| 117 | int (*set_attention_status) (struct hotplug_slot *slot, u8 value); | ||
| 118 | int (*hardware_test) (struct hotplug_slot *slot, u32 value); | ||
| 119 | int (*get_power_status) (struct hotplug_slot *slot, u8 *value); | ||
| 120 | int (*get_attention_status) (struct hotplug_slot *slot, u8 *value); | ||
| 121 | int (*get_latch_status) (struct hotplug_slot *slot, u8 *value); | ||
| 122 | int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value); | ||
| 123 | int (*get_address) (struct hotplug_slot *slot, u32 *value); | ||
| 124 | int (*get_max_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
| 125 | int (*get_cur_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); | ||
| 126 | }; | ||
| 127 | |||
| 128 | /** | ||
| 129 | * struct hotplug_slot_info - used to notify the hotplug pci core of the state of the slot | ||
| 130 | * @power: if power is enabled or not (1/0) | ||
| 131 | * @attention_status: if the attention light is enabled or not (1/0) | ||
| 132 | * @latch_status: if the latch (if any) is open or closed (1/0) | ||
| 133 | * @adapter_present: if there is a pci board present in the slot or not (1/0) | ||
| 134 | * @address: (domain << 16 | bus << 8 | dev) | ||
| 135 | * | ||
| 136 | * Used to notify the hotplug pci core of the status of a specific slot. | ||
| 137 | */ | ||
| 138 | struct hotplug_slot_info { | ||
| 139 | u8 power_status; | ||
| 140 | u8 attention_status; | ||
| 141 | u8 latch_status; | ||
| 142 | u8 adapter_status; | ||
| 143 | u32 address; | ||
| 144 | enum pci_bus_speed max_bus_speed; | ||
| 145 | enum pci_bus_speed cur_bus_speed; | ||
| 146 | }; | ||
| 147 | |||
| 148 | /** | ||
| 149 | * struct hotplug_slot - used to register a physical slot with the hotplug pci core | ||
| 150 | * @name: the name of the slot being registered. This string must | ||
| 151 | * be unique amoung slots registered on this system. | ||
| 152 | * @ops: pointer to the &struct hotplug_slot_ops to be used for this slot | ||
| 153 | * @info: pointer to the &struct hotplug_slot_info for the initial values for | ||
| 154 | * this slot. | ||
| 155 | * @release: called during pci_hp_deregister to free memory allocated in a | ||
| 156 | * hotplug_slot structure. | ||
| 157 | * @private: used by the hotplug pci controller driver to store whatever it | ||
| 158 | * needs. | ||
| 159 | */ | ||
| 160 | struct hotplug_slot { | ||
| 161 | char *name; | ||
| 162 | struct hotplug_slot_ops *ops; | ||
| 163 | struct hotplug_slot_info *info; | ||
| 164 | void (*release) (struct hotplug_slot *slot); | ||
| 165 | void *private; | ||
| 166 | |||
| 167 | /* Variables below this are for use only by the hotplug pci core. */ | ||
| 168 | struct list_head slot_list; | ||
| 169 | struct kobject kobj; | ||
| 170 | }; | ||
| 171 | #define to_hotplug_slot(n) container_of(n, struct hotplug_slot, kobj) | ||
| 172 | |||
| 173 | extern int pci_hp_register (struct hotplug_slot *slot); | ||
| 174 | extern int pci_hp_deregister (struct hotplug_slot *slot); | ||
| 175 | extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot, | ||
| 176 | struct hotplug_slot_info *info); | ||
| 177 | extern struct subsystem pci_hotplug_slots_subsys; | ||
| 178 | |||
| 179 | /* PCI Setting Record (Type 0) */ | ||
| 180 | struct hpp_type0 { | ||
| 181 | u32 revision; | ||
| 182 | u8 cache_line_size; | ||
| 183 | u8 latency_timer; | ||
| 184 | u8 enable_serr; | ||
| 185 | u8 enable_perr; | ||
| 186 | }; | ||
| 187 | |||
| 188 | /* PCI-X Setting Record (Type 1) */ | ||
| 189 | struct hpp_type1 { | ||
| 190 | u32 revision; | ||
| 191 | u8 max_mem_read; | ||
| 192 | u8 avg_max_split; | ||
| 193 | u16 tot_max_split; | ||
| 194 | }; | ||
| 195 | |||
| 196 | /* PCI Express Setting Record (Type 2) */ | ||
| 197 | struct hpp_type2 { | ||
| 198 | u32 revision; | ||
| 199 | u32 unc_err_mask_and; | ||
| 200 | u32 unc_err_mask_or; | ||
| 201 | u32 unc_err_sever_and; | ||
| 202 | u32 unc_err_sever_or; | ||
| 203 | u32 cor_err_mask_and; | ||
| 204 | u32 cor_err_mask_or; | ||
| 205 | u32 adv_err_cap_and; | ||
| 206 | u32 adv_err_cap_or; | ||
| 207 | u16 pci_exp_devctl_and; | ||
| 208 | u16 pci_exp_devctl_or; | ||
| 209 | u16 pci_exp_lnkctl_and; | ||
| 210 | u16 pci_exp_lnkctl_or; | ||
| 211 | u32 sec_unc_err_sever_and; | ||
| 212 | u32 sec_unc_err_sever_or; | ||
| 213 | u32 sec_unc_err_mask_and; | ||
| 214 | u32 sec_unc_err_mask_or; | ||
| 215 | }; | ||
| 216 | |||
| 217 | struct hotplug_params { | ||
| 218 | struct hpp_type0 *t0; /* Type0: NULL if not available */ | ||
| 219 | struct hpp_type1 *t1; /* Type1: NULL if not available */ | ||
| 220 | struct hpp_type2 *t2; /* Type2: NULL if not available */ | ||
| 221 | struct hpp_type0 type0_data; | ||
| 222 | struct hpp_type1 type1_data; | ||
| 223 | struct hpp_type2 type2_data; | ||
| 224 | }; | ||
| 225 | |||
| 226 | #ifdef CONFIG_ACPI | ||
| 227 | #include <acpi/acpi.h> | ||
| 228 | #include <acpi/acpi_bus.h> | ||
| 229 | #include <acpi/actypes.h> | ||
| 230 | extern acpi_status acpi_run_oshp(acpi_handle handle); | ||
| 231 | extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, | ||
| 232 | struct hotplug_params *hpp); | ||
| 233 | int acpi_root_bridge(acpi_handle handle); | ||
| 234 | #endif | ||
| 235 | #endif | ||
| 236 | |||
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.h b/drivers/pci/hotplug/rpaphp.h index 310b6186c0e5..2e7accf0f734 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | #define _PPC64PHP_H | 28 | #define _PPC64PHP_H |
| 29 | 29 | ||
| 30 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
| 31 | #include "pci_hotplug.h" | 31 | #include <linux/pci_hotplug.h> |
| 32 | 32 | ||
| 33 | #define DR_INDICATOR 9002 | 33 | #define DR_INDICATOR 9002 |
| 34 | #define DR_ENTITY_SENSE 9003 | 34 | #define DR_ENTITY_SENSE 9003 |
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/htirq.c b/drivers/pci/htirq.c index 0e27f2404a83..0a8d1cce9fa0 100644 --- a/drivers/pci/htirq.c +++ b/drivers/pci/htirq.c | |||
| @@ -25,97 +25,72 @@ static DEFINE_SPINLOCK(ht_irq_lock); | |||
| 25 | 25 | ||
| 26 | struct ht_irq_cfg { | 26 | struct ht_irq_cfg { |
| 27 | struct pci_dev *dev; | 27 | struct pci_dev *dev; |
| 28 | /* Update callback used to cope with buggy hardware */ | ||
| 29 | ht_irq_update_t *update; | ||
| 28 | unsigned pos; | 30 | unsigned pos; |
| 29 | unsigned idx; | 31 | unsigned idx; |
| 32 | struct ht_irq_msg msg; | ||
| 30 | }; | 33 | }; |
| 31 | 34 | ||
| 32 | void write_ht_irq_low(unsigned int irq, u32 data) | ||
| 33 | { | ||
| 34 | struct ht_irq_cfg *cfg = get_irq_data(irq); | ||
| 35 | unsigned long flags; | ||
| 36 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
| 37 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); | ||
| 38 | pci_write_config_dword(cfg->dev, cfg->pos + 4, data); | ||
| 39 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
| 40 | } | ||
| 41 | 35 | ||
| 42 | void write_ht_irq_high(unsigned int irq, u32 data) | 36 | void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) |
| 43 | { | 37 | { |
| 44 | struct ht_irq_cfg *cfg = get_irq_data(irq); | 38 | struct ht_irq_cfg *cfg = get_irq_data(irq); |
| 45 | unsigned long flags; | 39 | unsigned long flags; |
| 46 | spin_lock_irqsave(&ht_irq_lock, flags); | 40 | spin_lock_irqsave(&ht_irq_lock, flags); |
| 47 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); | 41 | if (cfg->msg.address_lo != msg->address_lo) { |
| 48 | pci_write_config_dword(cfg->dev, cfg->pos + 4, data); | 42 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); |
| 49 | spin_unlock_irqrestore(&ht_irq_lock, flags); | 43 | pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_lo); |
| 50 | } | 44 | } |
| 51 | 45 | if (cfg->msg.address_hi != msg->address_hi) { | |
| 52 | u32 read_ht_irq_low(unsigned int irq) | 46 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); |
| 53 | { | 47 | pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_hi); |
| 54 | struct ht_irq_cfg *cfg = get_irq_data(irq); | 48 | } |
| 55 | unsigned long flags; | 49 | if (cfg->update) |
| 56 | u32 data; | 50 | cfg->update(cfg->dev, irq, msg); |
| 57 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
| 58 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); | ||
| 59 | pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); | ||
| 60 | spin_unlock_irqrestore(&ht_irq_lock, flags); | 51 | spin_unlock_irqrestore(&ht_irq_lock, flags); |
| 61 | return data; | 52 | cfg->msg = *msg; |
| 62 | } | 53 | } |
| 63 | 54 | ||
| 64 | u32 read_ht_irq_high(unsigned int irq) | 55 | void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) |
| 65 | { | 56 | { |
| 66 | struct ht_irq_cfg *cfg = get_irq_data(irq); | 57 | struct ht_irq_cfg *cfg = get_irq_data(irq); |
| 67 | unsigned long flags; | 58 | *msg = cfg->msg; |
| 68 | u32 data; | ||
| 69 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
| 70 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); | ||
| 71 | pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); | ||
| 72 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
| 73 | return data; | ||
| 74 | } | 59 | } |
| 75 | 60 | ||
| 76 | void mask_ht_irq(unsigned int irq) | 61 | void mask_ht_irq(unsigned int irq) |
| 77 | { | 62 | { |
| 78 | struct ht_irq_cfg *cfg; | 63 | struct ht_irq_cfg *cfg; |
| 79 | unsigned long flags; | 64 | struct ht_irq_msg msg; |
| 80 | u32 data; | ||
| 81 | 65 | ||
| 82 | cfg = get_irq_data(irq); | 66 | cfg = get_irq_data(irq); |
| 83 | 67 | ||
| 84 | spin_lock_irqsave(&ht_irq_lock, flags); | 68 | msg = cfg->msg; |
| 85 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); | 69 | msg.address_lo |= 1; |
| 86 | pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); | 70 | write_ht_irq_msg(irq, &msg); |
| 87 | data |= 1; | ||
| 88 | pci_write_config_dword(cfg->dev, cfg->pos + 4, data); | ||
| 89 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
| 90 | } | 71 | } |
| 91 | 72 | ||
| 92 | void unmask_ht_irq(unsigned int irq) | 73 | void unmask_ht_irq(unsigned int irq) |
| 93 | { | 74 | { |
| 94 | struct ht_irq_cfg *cfg; | 75 | struct ht_irq_cfg *cfg; |
| 95 | unsigned long flags; | 76 | struct ht_irq_msg msg; |
| 96 | u32 data; | ||
| 97 | 77 | ||
| 98 | cfg = get_irq_data(irq); | 78 | cfg = get_irq_data(irq); |
| 99 | 79 | ||
| 100 | spin_lock_irqsave(&ht_irq_lock, flags); | 80 | msg = cfg->msg; |
| 101 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); | 81 | msg.address_lo &= ~1; |
| 102 | pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); | 82 | write_ht_irq_msg(irq, &msg); |
| 103 | data &= ~1; | ||
| 104 | pci_write_config_dword(cfg->dev, cfg->pos + 4, data); | ||
| 105 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
| 106 | } | 83 | } |
| 107 | 84 | ||
| 108 | /** | 85 | /** |
| 109 | * ht_create_irq - create an irq and attach it to a device. | 86 | * __ht_create_irq - create an irq and attach it to a device. |
| 110 | * @dev: The hypertransport device to find the irq capability on. | 87 | * @dev: The hypertransport device to find the irq capability on. |
| 111 | * @idx: Which of the possible irqs to attach to. | 88 | * @idx: Which of the possible irqs to attach to. |
| 112 | * | 89 | * @update: Function to be called when changing the htirq message |
| 113 | * ht_create_irq is needs to be called for all hypertransport devices | ||
| 114 | * that generate irqs. | ||
| 115 | * | 90 | * |
| 116 | * The irq number of the new irq or a negative error value is returned. | 91 | * The irq number of the new irq or a negative error value is returned. |
| 117 | */ | 92 | */ |
| 118 | int ht_create_irq(struct pci_dev *dev, int idx) | 93 | int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update) |
| 119 | { | 94 | { |
| 120 | struct ht_irq_cfg *cfg; | 95 | struct ht_irq_cfg *cfg; |
| 121 | unsigned long flags; | 96 | unsigned long flags; |
| @@ -150,8 +125,12 @@ int ht_create_irq(struct pci_dev *dev, int idx) | |||
| 150 | return -ENOMEM; | 125 | return -ENOMEM; |
| 151 | 126 | ||
| 152 | cfg->dev = dev; | 127 | cfg->dev = dev; |
| 128 | cfg->update = update; | ||
| 153 | cfg->pos = pos; | 129 | cfg->pos = pos; |
| 154 | cfg->idx = 0x10 + (idx * 2); | 130 | cfg->idx = 0x10 + (idx * 2); |
| 131 | /* Initialize msg to a value that will never match the first write. */ | ||
| 132 | cfg->msg.address_lo = 0xffffffff; | ||
| 133 | cfg->msg.address_hi = 0xffffffff; | ||
| 155 | 134 | ||
| 156 | irq = create_irq(); | 135 | irq = create_irq(); |
| 157 | if (irq < 0) { | 136 | if (irq < 0) { |
| @@ -169,6 +148,21 @@ int ht_create_irq(struct pci_dev *dev, int idx) | |||
| 169 | } | 148 | } |
| 170 | 149 | ||
| 171 | /** | 150 | /** |
| 151 | * ht_create_irq - create an irq and attach it to a device. | ||
| 152 | * @dev: The hypertransport device to find the irq capability on. | ||
| 153 | * @idx: Which of the possible irqs to attach to. | ||
| 154 | * | ||
| 155 | * ht_create_irq needs to be called for all hypertransport devices | ||
| 156 | * that generate irqs. | ||
| 157 | * | ||
| 158 | * The irq number of the new irq or a negative error value is returned. | ||
| 159 | */ | ||
| 160 | int ht_create_irq(struct pci_dev *dev, int idx) | ||
| 161 | { | ||
| 162 | return __ht_create_irq(dev, idx, NULL); | ||
| 163 | } | ||
| 164 | |||
| 165 | /** | ||
| 172 | * ht_destroy_irq - destroy an irq created with ht_create_irq | 166 | * ht_destroy_irq - destroy an irq created with ht_create_irq |
| 173 | * | 167 | * |
| 174 | * This reverses ht_create_irq removing the specified irq from | 168 | * This reverses ht_create_irq removing the specified irq from |
| @@ -186,5 +180,6 @@ void ht_destroy_irq(unsigned int irq) | |||
| 186 | kfree(cfg); | 180 | kfree(cfg); |
| 187 | } | 181 | } |
| 188 | 182 | ||
| 183 | EXPORT_SYMBOL(__ht_create_irq); | ||
| 189 | EXPORT_SYMBOL(ht_create_irq); | 184 | EXPORT_SYMBOL(ht_create_irq); |
| 190 | EXPORT_SYMBOL(ht_destroy_irq); | 185 | EXPORT_SYMBOL(ht_destroy_irq); |
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/pci-driver.c b/drivers/pci/pci-driver.c index b1c0c707d96c..194f1d21d3d7 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
| @@ -265,6 +265,13 @@ static int pci_device_remove(struct device * dev) | |||
| 265 | } | 265 | } |
| 266 | 266 | ||
| 267 | /* | 267 | /* |
| 268 | * If the device is still on, set the power state as "unknown", | ||
| 269 | * since it might change by the next time we load the driver. | ||
| 270 | */ | ||
| 271 | if (pci_dev->current_state == PCI_D0) | ||
| 272 | pci_dev->current_state = PCI_UNKNOWN; | ||
| 273 | |||
| 274 | /* | ||
| 268 | * We would love to complain here if pci_dev->is_enabled is set, that | 275 | * We would love to complain here if pci_dev->is_enabled is set, that |
| 269 | * the driver should have called pci_disable_device(), but the | 276 | * the driver should have called pci_disable_device(), but the |
| 270 | * unfortunate fact is there are too many odd BIOS and bridge setups | 277 | * unfortunate fact is there are too many odd BIOS and bridge setups |
| @@ -288,6 +295,12 @@ static int pci_device_suspend(struct device * dev, pm_message_t state) | |||
| 288 | suspend_report_result(drv->suspend, i); | 295 | suspend_report_result(drv->suspend, i); |
| 289 | } else { | 296 | } else { |
| 290 | pci_save_state(pci_dev); | 297 | pci_save_state(pci_dev); |
| 298 | /* | ||
| 299 | * mark its power state as "unknown", since we don't know if | ||
| 300 | * e.g. the BIOS will change its device state when we suspend. | ||
| 301 | */ | ||
| 302 | if (pci_dev->current_state == PCI_D0) | ||
| 303 | pci_dev->current_state = PCI_UNKNOWN; | ||
| 291 | } | 304 | } |
| 292 | return i; | 305 | return i; |
| 293 | } | 306 | } |
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index a1d2e979b17f..f952bfea48a6 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
| @@ -642,6 +642,9 @@ err: | |||
| 642 | */ | 642 | */ |
| 643 | void pci_remove_sysfs_dev_files(struct pci_dev *pdev) | 643 | void pci_remove_sysfs_dev_files(struct pci_dev *pdev) |
| 644 | { | 644 | { |
| 645 | if (!sysfs_initialized) | ||
| 646 | return; | ||
| 647 | |||
| 645 | if (pdev->cfg_size < 4096) | 648 | if (pdev->cfg_size < 4096) |
| 646 | sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); | 649 | sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); |
| 647 | else | 650 | else |
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..5b4483811691 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 |
| @@ -683,33 +714,6 @@ static void __devinit quirk_vt82c598_id(struct pci_dev *dev) | |||
| 683 | } | 714 | } |
| 684 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt82c598_id ); | 715 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt82c598_id ); |
| 685 | 716 | ||
| 686 | #ifdef CONFIG_ACPI_SLEEP | ||
| 687 | |||
| 688 | /* | ||
| 689 | * Some VIA systems boot with the abnormal status flag set. This can cause | ||
| 690 | * the BIOS to re-POST the system on resume rather than passing control | ||
| 691 | * back to the OS. Clear the flag on boot | ||
| 692 | */ | ||
| 693 | static void __devinit quirk_via_abnormal_poweroff(struct pci_dev *dev) | ||
| 694 | { | ||
| 695 | u32 reg; | ||
| 696 | |||
| 697 | acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, | ||
| 698 | ®); | ||
| 699 | |||
| 700 | if (reg & 0x800) { | ||
| 701 | printk("Clearing abnormal poweroff flag\n"); | ||
| 702 | acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, | ||
| 703 | ACPI_REGISTER_PM1_STATUS, | ||
| 704 | (u16)0x800); | ||
| 705 | } | ||
| 706 | } | ||
| 707 | |||
| 708 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_via_abnormal_poweroff); | ||
| 709 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_abnormal_poweroff); | ||
| 710 | |||
| 711 | #endif | ||
| 712 | |||
| 713 | /* | 717 | /* |
| 714 | * CardBus controllers have a legacy base address that enables them | 718 | * CardBus controllers have a legacy base address that enables them |
| 715 | * to respond as i82365 pcmcia controllers. We don't want them to | 719 | * to respond as i82365 pcmcia controllers. We don't want them to |
| @@ -1456,33 +1460,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2609, quirk_intel_pcie_pm); | |||
| 1456 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm); | 1460 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm); |
| 1457 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm); | 1461 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm); |
| 1458 | 1462 | ||
| 1459 | /* | ||
| 1460 | * Fixup the cardbus bridges on the IBM Dock II docking station | ||
| 1461 | */ | ||
| 1462 | static void __devinit quirk_ibm_dock2_cardbus(struct pci_dev *dev) | ||
| 1463 | { | ||
| 1464 | u32 val; | ||
| 1465 | |||
| 1466 | /* | ||
| 1467 | * tie the 2 interrupt pins to INTA, and configure the | ||
| 1468 | * multifunction routing register to handle this. | ||
| 1469 | */ | ||
| 1470 | if ((dev->subsystem_vendor == PCI_VENDOR_ID_IBM) && | ||
| 1471 | (dev->subsystem_device == 0x0148)) { | ||
| 1472 | printk(KERN_INFO "PCI: Found IBM Dock II Cardbus Bridge " | ||
| 1473 | "applying quirk\n"); | ||
| 1474 | pci_read_config_dword(dev, 0x8c, &val); | ||
| 1475 | val = ((val & 0xffffff00) | 0x1002); | ||
| 1476 | pci_write_config_dword(dev, 0x8c, val); | ||
| 1477 | pci_read_config_dword(dev, 0x80, &val); | ||
| 1478 | val = ((val & 0x00ffff00) | 0x2864c077); | ||
| 1479 | pci_write_config_dword(dev, 0x80, val); | ||
| 1480 | } | ||
| 1481 | } | ||
| 1482 | |||
| 1483 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, | ||
| 1484 | quirk_ibm_dock2_cardbus); | ||
| 1485 | |||
| 1486 | static void __devinit quirk_netmos(struct pci_dev *dev) | 1463 | static void __devinit quirk_netmos(struct pci_dev *dev) |
| 1487 | { | 1464 | { |
| 1488 | unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4; | 1465 | unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4; |
| @@ -1588,7 +1565,6 @@ static void __devinit fixup_rev1_53c810(struct pci_dev* dev) | |||
| 1588 | } | 1565 | } |
| 1589 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); | 1566 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); |
| 1590 | 1567 | ||
| 1591 | |||
| 1592 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) | 1568 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) |
| 1593 | { | 1569 | { |
| 1594 | while (f < end) { | 1570 | while (f < end) { |
| @@ -1764,7 +1740,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. | 1740 | /* 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. | 1741 | * a single one having MSI is enough to be sure that MSI are supported. |
| 1766 | */ | 1742 | */ |
| 1767 | pdev = pci_find_slot(dev->bus->number, 0); | 1743 | pdev = pci_get_slot(dev->bus, 0); |
| 1768 | if (dev->subordinate && !msi_ht_cap_enabled(dev) | 1744 | if (dev->subordinate && !msi_ht_cap_enabled(dev) |
| 1769 | && !msi_ht_cap_enabled(pdev)) { | 1745 | && !msi_ht_cap_enabled(pdev)) { |
| 1770 | printk(KERN_WARNING "PCI: MSI quirk detected. " | 1746 | printk(KERN_WARNING "PCI: MSI quirk detected. " |
| @@ -1772,6 +1748,7 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) | |||
| 1772 | pci_name(dev)); | 1748 | pci_name(dev)); |
| 1773 | dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; | 1749 | dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; |
| 1774 | } | 1750 | } |
| 1751 | pci_dev_put(pdev); | ||
| 1775 | } | 1752 | } |
| 1776 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, | 1753 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, |
| 1777 | quirk_nvidia_ck804_msi_ht_cap); | 1754 | quirk_nvidia_ck804_msi_ht_cap); |
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index f5ee7ce16fa6..e1dcefc69bb4 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c | |||
| @@ -71,7 +71,11 @@ 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 on x86, x86_64 and IA64 supports legacy | ||
| 76 | * memory map if the VGA enable bit of the Bridge Control register is | ||
| 77 | * set for embedded VGA. | ||
| 78 | */ | ||
| 75 | if (res->flags & IORESOURCE_ROM_SHADOW) { | 79 | if (res->flags & IORESOURCE_ROM_SHADOW) { |
| 76 | /* primary video rom always starts here */ | 80 | /* primary video rom always starts here */ |
| 77 | start = (loff_t)0xC0000; | 81 | 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); |
