aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/Kconfig25
-rw-r--r--drivers/pci/bus.c22
-rw-r--r--drivers/pci/hotplug/acpiphp.h5
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c127
-rw-r--r--drivers/pci/hotplug/acpiphp_ibm.c4
-rw-r--r--drivers/pci/hotplug/cpqphp_sysfs.c2
-rw-r--r--drivers/pci/hotplug/fakephp.c18
-rw-r--r--drivers/pci/hotplug/pci_hotplug.h4
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c157
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c12
-rw-r--r--drivers/pci/hotplug/pcihp_skeleton.c9
-rw-r--r--drivers/pci/hotplug/shpchp.h2
-rw-r--r--drivers/pci/hotplug/shpchp_core.c6
-rw-r--r--drivers/pci/hotplug/shpchp_sysfs.c4
-rw-r--r--drivers/pci/msi.c64
-rw-r--r--drivers/pci/pci-driver.c47
-rw-r--r--drivers/pci/pci-sysfs.c153
-rw-r--r--drivers/pci/pci.c59
-rw-r--r--drivers/pci/pci.h2
-rw-r--r--drivers/pci/pcie/Kconfig1
-rw-r--r--drivers/pci/pcie/Makefile3
-rw-r--r--drivers/pci/pcie/aer/Kconfig12
-rw-r--r--drivers/pci/pcie/aer/Makefile8
-rw-r--r--drivers/pci/pcie/aer/aerdrv.c346
-rw-r--r--drivers/pci/pcie/aer/aerdrv.h125
-rw-r--r--drivers/pci/pcie/aer/aerdrv_acpi.c68
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c758
-rw-r--r--drivers/pci/pcie/aer/aerdrv_errprint.c248
-rw-r--r--drivers/pci/pcie/portdrv.h2
-rw-r--r--drivers/pci/pcie/portdrv_bus.c1
-rw-r--r--drivers/pci/pcie/portdrv_core.c11
-rw-r--r--drivers/pci/pcie/portdrv_pci.c211
-rw-r--r--drivers/pci/probe.c16
-rw-r--r--drivers/pci/quirks.c104
-rw-r--r--drivers/pci/remove.c37
-rw-r--r--drivers/pci/setup-bus.c13
36 files changed, 2480 insertions, 206 deletions
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 4d762fc4878c..c27e782e6df9 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -17,6 +17,31 @@ config PCI_MSI
17 17
18 If you don't know what to do here, say N. 18 If you don't know what to do here, say N.
19 19
20config PCI_MULTITHREAD_PROBE
21 bool "PCI Multi-threaded probe (EXPERIMENTAL)"
22 depends on PCI && EXPERIMENTAL
23 help
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
26 speedup in boot times on multiprocessor machines, and even a
27 smaller speedup on single processor machines.
28
29 But it can also cause lots of bad things to happen. A number
30 of PCI drivers can not properly handle running in this way,
31 some will just not work properly at all, while others might
32 decide to blow up power supplies with a huge load all at once,
33 so use this option at your own risk.
34
35 It is very unwise to use this option if you are not using a
36 boot process that can handle devices being created in any
37 order. A program that can create persistant block and network
38 device names (like udev) is a good idea if you wish to use
39 this option.
40
41 Again, use this option at your own risk, you have been warned!
42
43 When in doubt, say N.
44
20config PCI_DEBUG 45config PCI_DEBUG
21 bool "PCI Debugging" 46 bool "PCI Debugging"
22 depends on PCI && DEBUG_KERNEL 47 depends on PCI && DEBUG_KERNEL
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 5f7db9d2436e..aadaa3c8096b 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -77,9 +77,12 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
77 * This adds a single pci device to the global 77 * This adds a single pci device to the global
78 * device list and adds sysfs and procfs entries 78 * device list and adds sysfs and procfs entries
79 */ 79 */
80void __devinit pci_bus_add_device(struct pci_dev *dev) 80int __devinit pci_bus_add_device(struct pci_dev *dev)
81{ 81{
82 device_add(&dev->dev); 82 int retval;
83 retval = device_add(&dev->dev);
84 if (retval)
85 return retval;
83 86
84 down_write(&pci_bus_sem); 87 down_write(&pci_bus_sem);
85 list_add_tail(&dev->global_list, &pci_devices); 88 list_add_tail(&dev->global_list, &pci_devices);
@@ -87,6 +90,7 @@ void __devinit pci_bus_add_device(struct pci_dev *dev)
87 90
88 pci_proc_attach_device(dev); 91 pci_proc_attach_device(dev);
89 pci_create_sysfs_dev_files(dev); 92 pci_create_sysfs_dev_files(dev);
93 return 0;
90} 94}
91 95
92/** 96/**
@@ -104,6 +108,7 @@ void __devinit pci_bus_add_device(struct pci_dev *dev)
104void __devinit pci_bus_add_devices(struct pci_bus *bus) 108void __devinit pci_bus_add_devices(struct pci_bus *bus)
105{ 109{
106 struct pci_dev *dev; 110 struct pci_dev *dev;
111 int retval;
107 112
108 list_for_each_entry(dev, &bus->devices, bus_list) { 113 list_for_each_entry(dev, &bus->devices, bus_list) {
109 /* 114 /*
@@ -112,7 +117,9 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
112 */ 117 */
113 if (!list_empty(&dev->global_list)) 118 if (!list_empty(&dev->global_list))
114 continue; 119 continue;
115 pci_bus_add_device(dev); 120 retval = pci_bus_add_device(dev);
121 if (retval)
122 dev_err(&dev->dev, "Error adding device, continuing\n");
116 } 123 }
117 124
118 list_for_each_entry(dev, &bus->devices, bus_list) { 125 list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -129,10 +136,13 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
129 list_add_tail(&dev->subordinate->node, 136 list_add_tail(&dev->subordinate->node,
130 &dev->bus->children); 137 &dev->bus->children);
131 up_write(&pci_bus_sem); 138 up_write(&pci_bus_sem);
132 } 139 }
133 pci_bus_add_devices(dev->subordinate); 140 pci_bus_add_devices(dev->subordinate);
134 141 retval = sysfs_create_link(&dev->subordinate->class_dev.kobj,
135 sysfs_create_link(&dev->subordinate->class_dev.kobj, &dev->dev.kobj, "bridge"); 142 &dev->dev.kobj, "bridge");
143 if (retval)
144 dev_err(&dev->dev, "Error creating sysfs "
145 "bridge symlink, continuing...\n");
136 } 146 }
137 } 147 }
138} 148}
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index be104eced34c..7fff07e877c7 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -150,6 +150,11 @@ struct acpiphp_attention_info
150 struct module *owner; 150 struct module *owner;
151}; 151};
152 152
153struct acpiphp_ioapic {
154 struct pci_dev *dev;
155 u32 gsi_base;
156 struct list_head list;
157};
153 158
154/* PCI bus bridge HID */ 159/* PCI bus bridge HID */
155#define ACPI_PCI_HOST_HID "PNP0A03" 160#define ACPI_PCI_HOST_HID "PNP0A03"
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index ae67a8f55ba1..83e8e4412de5 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -53,6 +53,8 @@
53#include "acpiphp.h" 53#include "acpiphp.h"
54 54
55static LIST_HEAD(bridge_list); 55static LIST_HEAD(bridge_list);
56static LIST_HEAD(ioapic_list);
57static DEFINE_SPINLOCK(ioapic_list_lock);
56 58
57#define MY_NAME "acpiphp_glue" 59#define MY_NAME "acpiphp_glue"
58 60
@@ -797,6 +799,7 @@ ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv)
797 struct pci_dev *pdev; 799 struct pci_dev *pdev;
798 u32 gsi_base; 800 u32 gsi_base;
799 u64 phys_addr; 801 u64 phys_addr;
802 struct acpiphp_ioapic *ioapic;
800 803
801 /* Evaluate _STA if present */ 804 /* Evaluate _STA if present */
802 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); 805 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
@@ -811,41 +814,107 @@ ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv)
811 if (get_gsi_base(handle, &gsi_base)) 814 if (get_gsi_base(handle, &gsi_base))
812 return AE_OK; 815 return AE_OK;
813 816
817 ioapic = kmalloc(sizeof(*ioapic), GFP_KERNEL);
818 if (!ioapic)
819 return AE_NO_MEMORY;
820
814 pdev = get_apic_pci_info(handle); 821 pdev = get_apic_pci_info(handle);
815 if (!pdev) 822 if (!pdev)
816 return AE_OK; 823 goto exit_kfree;
817 824
818 if (pci_enable_device(pdev)) { 825 if (pci_enable_device(pdev))
819 pci_dev_put(pdev); 826 goto exit_pci_dev_put;
820 return AE_OK;
821 }
822 827
823 pci_set_master(pdev); 828 pci_set_master(pdev);
824 829
825 if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)")) { 830 if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)"))
826 pci_disable_device(pdev); 831 goto exit_pci_disable_device;
827 pci_dev_put(pdev);
828 return AE_OK;
829 }
830 832
831 phys_addr = pci_resource_start(pdev, 0); 833 phys_addr = pci_resource_start(pdev, 0);
832 if (acpi_register_ioapic(handle, phys_addr, gsi_base)) { 834 if (acpi_register_ioapic(handle, phys_addr, gsi_base))
833 pci_release_region(pdev, 0); 835 goto exit_pci_release_region;
834 pci_disable_device(pdev); 836
835 pci_dev_put(pdev); 837 ioapic->gsi_base = gsi_base;
838 ioapic->dev = pdev;
839 spin_lock(&ioapic_list_lock);
840 list_add_tail(&ioapic->list, &ioapic_list);
841 spin_unlock(&ioapic_list_lock);
842
843 return AE_OK;
844
845 exit_pci_release_region:
846 pci_release_region(pdev, 0);
847 exit_pci_disable_device:
848 pci_disable_device(pdev);
849 exit_pci_dev_put:
850 pci_dev_put(pdev);
851 exit_kfree:
852 kfree(ioapic);
853
854 return AE_OK;
855}
856
857static acpi_status
858ioapic_remove(acpi_handle handle, u32 lvl, void *context, void **rv)
859{
860 acpi_status status;
861 unsigned long sta;
862 acpi_handle tmp;
863 u32 gsi_base;
864 struct acpiphp_ioapic *pos, *n, *ioapic = NULL;
865
866 /* Evaluate _STA if present */
867 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
868 if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL)
869 return AE_CTRL_DEPTH;
870
871 /* Scan only PCI bus scope */
872 status = acpi_get_handle(handle, "_HID", &tmp);
873 if (ACPI_SUCCESS(status))
874 return AE_CTRL_DEPTH;
875
876 if (get_gsi_base(handle, &gsi_base))
836 return AE_OK; 877 return AE_OK;
878
879 acpi_unregister_ioapic(handle, gsi_base);
880
881 spin_lock(&ioapic_list_lock);
882 list_for_each_entry_safe(pos, n, &ioapic_list, list) {
883 if (pos->gsi_base != gsi_base)
884 continue;
885 ioapic = pos;
886 list_del(&ioapic->list);
887 break;
837 } 888 }
889 spin_unlock(&ioapic_list_lock);
890
891 if (!ioapic)
892 return AE_OK;
893
894 pci_release_region(ioapic->dev, 0);
895 pci_disable_device(ioapic->dev);
896 pci_dev_put(ioapic->dev);
897 kfree(ioapic);
838 898
839 return AE_OK; 899 return AE_OK;
840} 900}
841 901
842static int acpiphp_configure_ioapics(acpi_handle handle) 902static int acpiphp_configure_ioapics(acpi_handle handle)
843{ 903{
904 ioapic_add(handle, 0, NULL, NULL);
844 acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 905 acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
845 ACPI_UINT32_MAX, ioapic_add, NULL, NULL); 906 ACPI_UINT32_MAX, ioapic_add, NULL, NULL);
846 return 0; 907 return 0;
847} 908}
848 909
910static int acpiphp_unconfigure_ioapics(acpi_handle handle)
911{
912 ioapic_remove(handle, 0, NULL, NULL);
913 acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
914 ACPI_UINT32_MAX, ioapic_remove, NULL, NULL);
915 return 0;
916}
917
849static int power_on_slot(struct acpiphp_slot *slot) 918static int power_on_slot(struct acpiphp_slot *slot)
850{ 919{
851 acpi_status status; 920 acpi_status status;
@@ -997,7 +1066,7 @@ acpiphp_bus_add_out:
997 * @handle: handle to acpi namespace 1066 * @handle: handle to acpi namespace
998 * 1067 *
999 */ 1068 */
1000int acpiphp_bus_trim(acpi_handle handle) 1069static int acpiphp_bus_trim(acpi_handle handle)
1001{ 1070{
1002 struct acpi_device *device; 1071 struct acpi_device *device;
1003 int retval; 1072 int retval;
@@ -1074,10 +1143,11 @@ static int enable_device(struct acpiphp_slot *slot)
1074 1143
1075 pci_bus_assign_resources(bus); 1144 pci_bus_assign_resources(bus);
1076 acpiphp_sanitize_bus(bus); 1145 acpiphp_sanitize_bus(bus);
1146 acpiphp_set_hpp_values(slot->bridge->handle, bus);
1147 list_for_each_entry(func, &slot->funcs, sibling)
1148 acpiphp_configure_ioapics(func->handle);
1077 pci_enable_bridges(bus); 1149 pci_enable_bridges(bus);
1078 pci_bus_add_devices(bus); 1150 pci_bus_add_devices(bus);
1079 acpiphp_set_hpp_values(slot->bridge->handle, bus);
1080 acpiphp_configure_ioapics(slot->bridge->handle);
1081 1151
1082 /* associate pci_dev to our representation */ 1152 /* associate pci_dev to our representation */
1083 list_for_each (l, &slot->funcs) { 1153 list_for_each (l, &slot->funcs) {
@@ -1103,6 +1173,16 @@ static int enable_device(struct acpiphp_slot *slot)
1103 return retval; 1173 return retval;
1104} 1174}
1105 1175
1176static void disable_bridges(struct pci_bus *bus)
1177{
1178 struct pci_dev *dev;
1179 list_for_each_entry(dev, &bus->devices, bus_list) {
1180 if (dev->subordinate) {
1181 disable_bridges(dev->subordinate);
1182 pci_disable_device(dev);
1183 }
1184 }
1185}
1106 1186
1107/** 1187/**
1108 * disable_device - disable a slot 1188 * disable_device - disable a slot
@@ -1127,6 +1207,19 @@ static int disable_device(struct acpiphp_slot *slot)
1127 func->bridge = NULL; 1207 func->bridge = NULL;
1128 } 1208 }
1129 1209
1210 if (func->pci_dev) {
1211 pci_stop_bus_device(func->pci_dev);
1212 if (func->pci_dev->subordinate) {
1213 disable_bridges(func->pci_dev->subordinate);
1214 pci_disable_device(func->pci_dev);
1215 }
1216 }
1217 }
1218
1219 list_for_each (l, &slot->funcs) {
1220 func = list_entry(l, struct acpiphp_func, sibling);
1221
1222 acpiphp_unconfigure_ioapics(func->handle);
1130 acpiphp_bus_trim(func->handle); 1223 acpiphp_bus_trim(func->handle);
1131 /* try to remove anyway. 1224 /* try to remove anyway.
1132 * acpiphp_bus_add might have been failed */ 1225 * acpiphp_bus_add might have been failed */
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index 317457dd4014..d0a07d9ab30c 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -487,9 +487,7 @@ static void __exit ibm_acpiphp_exit(void)
487 if (ACPI_FAILURE(status)) 487 if (ACPI_FAILURE(status))
488 err("%s: Notification handler removal failed\n", __FUNCTION__); 488 err("%s: Notification handler removal failed\n", __FUNCTION__);
489 /* remove the /sys entries */ 489 /* remove the /sys entries */
490 if (sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr)) 490 sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr);
491 err("%s: removal of sysfs file apci_table failed\n",
492 __FUNCTION__);
493} 491}
494 492
495module_init(ibm_acpiphp_init); 493module_init(ibm_acpiphp_init);
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
index 8b3da007e859..5bab666cd67e 100644
--- a/drivers/pci/hotplug/cpqphp_sysfs.c
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c
@@ -140,7 +140,7 @@ struct ctrl_dbg {
140 140
141static int open(struct inode *inode, struct file *file) 141static int open(struct inode *inode, struct file *file)
142{ 142{
143 struct controller *ctrl = inode->u.generic_ip; 143 struct controller *ctrl = inode->i_private;
144 struct ctrl_dbg *dbg; 144 struct ctrl_dbg *dbg;
145 int retval = -ENOMEM; 145 int retval = -ENOMEM;
146 146
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index dd2b762777c4..05a4f0f90186 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -176,7 +176,9 @@ static void pci_rescan_slot(struct pci_dev *temp)
176 struct pci_bus *bus = temp->bus; 176 struct pci_bus *bus = temp->bus;
177 struct pci_dev *dev; 177 struct pci_dev *dev;
178 int func; 178 int func;
179 int retval;
179 u8 hdr_type; 180 u8 hdr_type;
181
180 if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) { 182 if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) {
181 temp->hdr_type = hdr_type & 0x7f; 183 temp->hdr_type = hdr_type & 0x7f;
182 if (!pci_find_slot(bus->number, temp->devfn)) { 184 if (!pci_find_slot(bus->number, temp->devfn)) {
@@ -185,8 +187,12 @@ static void pci_rescan_slot(struct pci_dev *temp)
185 dbg("New device on %s function %x:%x\n", 187 dbg("New device on %s function %x:%x\n",
186 bus->name, temp->devfn >> 3, 188 bus->name, temp->devfn >> 3,
187 temp->devfn & 7); 189 temp->devfn & 7);
188 pci_bus_add_device(dev); 190 retval = pci_bus_add_device(dev);
189 add_slot(dev); 191 if (retval)
192 dev_err(&dev->dev, "error adding "
193 "device, continuing.\n");
194 else
195 add_slot(dev);
190 } 196 }
191 } 197 }
192 /* multifunction device? */ 198 /* multifunction device? */
@@ -205,8 +211,12 @@ static void pci_rescan_slot(struct pci_dev *temp)
205 dbg("New device on %s function %x:%x\n", 211 dbg("New device on %s function %x:%x\n",
206 bus->name, temp->devfn >> 3, 212 bus->name, temp->devfn >> 3,
207 temp->devfn & 7); 213 temp->devfn & 7);
208 pci_bus_add_device(dev); 214 retval = pci_bus_add_device(dev);
209 add_slot(dev); 215 if (retval)
216 dev_err(&dev->dev, "error adding "
217 "device, continuing.\n");
218 else
219 add_slot(dev);
210 } 220 }
211 } 221 }
212 } 222 }
diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h
index e929b7c11429..772523dc3860 100644
--- a/drivers/pci/hotplug/pci_hotplug.h
+++ b/drivers/pci/hotplug/pci_hotplug.h
@@ -172,8 +172,8 @@ struct hotplug_slot {
172 172
173extern int pci_hp_register (struct hotplug_slot *slot); 173extern int pci_hp_register (struct hotplug_slot *slot);
174extern int pci_hp_deregister (struct hotplug_slot *slot); 174extern int pci_hp_deregister (struct hotplug_slot *slot);
175extern int pci_hp_change_slot_info (struct hotplug_slot *slot, 175extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot,
176 struct hotplug_slot_info *info); 176 struct hotplug_slot_info *info);
177extern struct subsystem pci_hotplug_slots_subsys; 177extern struct subsystem pci_hotplug_slots_subsys;
178 178
179/* PCI Setting Record (Type 0) */ 179/* PCI Setting Record (Type 0) */
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index b7b378df89e3..e2823ea9c4ed 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -482,31 +482,95 @@ static int has_test_file (struct hotplug_slot *slot)
482 482
483static int fs_add_slot (struct hotplug_slot *slot) 483static int fs_add_slot (struct hotplug_slot *slot)
484{ 484{
485 if (has_power_file(slot) == 0) 485 int retval = 0;
486 sysfs_create_file(&slot->kobj, &hotplug_slot_attr_power.attr);
487 486
488 if (has_attention_file(slot) == 0) 487 if (has_power_file(slot) == 0) {
489 sysfs_create_file(&slot->kobj, &hotplug_slot_attr_attention.attr); 488 retval = sysfs_create_file(&slot->kobj, &hotplug_slot_attr_power.attr);
489 if (retval)
490 goto exit_power;
491 }
490 492
491 if (has_latch_file(slot) == 0) 493 if (has_attention_file(slot) == 0) {
492 sysfs_create_file(&slot->kobj, &hotplug_slot_attr_latch.attr); 494 retval = sysfs_create_file(&slot->kobj,
495 &hotplug_slot_attr_attention.attr);
496 if (retval)
497 goto exit_attention;
498 }
493 499
494 if (has_adapter_file(slot) == 0) 500 if (has_latch_file(slot) == 0) {
495 sysfs_create_file(&slot->kobj, &hotplug_slot_attr_presence.attr); 501 retval = sysfs_create_file(&slot->kobj,
502 &hotplug_slot_attr_latch.attr);
503 if (retval)
504 goto exit_latch;
505 }
496 506
497 if (has_address_file(slot) == 0) 507 if (has_adapter_file(slot) == 0) {
498 sysfs_create_file(&slot->kobj, &hotplug_slot_attr_address.attr); 508 retval = sysfs_create_file(&slot->kobj,
509 &hotplug_slot_attr_presence.attr);
510 if (retval)
511 goto exit_adapter;
512 }
499 513
500 if (has_max_bus_speed_file(slot) == 0) 514 if (has_address_file(slot) == 0) {
501 sysfs_create_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); 515 retval = sysfs_create_file(&slot->kobj,
516 &hotplug_slot_attr_address.attr);
517 if (retval)
518 goto exit_address;
519 }
502 520
521 if (has_max_bus_speed_file(slot) == 0) {
522 retval = sysfs_create_file(&slot->kobj,
523 &hotplug_slot_attr_max_bus_speed.attr);
524 if (retval)
525 goto exit_max_speed;
526 }
527
528 if (has_cur_bus_speed_file(slot) == 0) {
529 retval = sysfs_create_file(&slot->kobj,
530 &hotplug_slot_attr_cur_bus_speed.attr);
531 if (retval)
532 goto exit_cur_speed;
533 }
534
535 if (has_test_file(slot) == 0) {
536 retval = sysfs_create_file(&slot->kobj,
537 &hotplug_slot_attr_test.attr);
538 if (retval)
539 goto exit_test;
540 }
541
542 goto exit;
543
544exit_test:
503 if (has_cur_bus_speed_file(slot) == 0) 545 if (has_cur_bus_speed_file(slot) == 0)
504 sysfs_create_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr); 546 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
505 547
506 if (has_test_file(slot) == 0) 548exit_cur_speed:
507 sysfs_create_file(&slot->kobj, &hotplug_slot_attr_test.attr); 549 if (has_max_bus_speed_file(slot) == 0)
550 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
508 551
509 return 0; 552exit_max_speed:
553 if (has_address_file(slot) == 0)
554 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_address.attr);
555
556exit_address:
557 if (has_adapter_file(slot) == 0)
558 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
559
560exit_adapter:
561 if (has_latch_file(slot) == 0)
562 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
563
564exit_latch:
565 if (has_attention_file(slot) == 0)
566 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
567
568exit_attention:
569 if (has_power_file(slot) == 0)
570 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
571exit_power:
572exit:
573 return retval;
510} 574}
511 575
512static void fs_remove_slot (struct hotplug_slot *slot) 576static void fs_remove_slot (struct hotplug_slot *slot)
@@ -626,8 +690,11 @@ int pci_hp_deregister (struct hotplug_slot *slot)
626 * 690 *
627 * Returns 0 if successful, anything else for an error. 691 * Returns 0 if successful, anything else for an error.
628 */ 692 */
629int pci_hp_change_slot_info (struct hotplug_slot *slot, struct hotplug_slot_info *info) 693int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot,
694 struct hotplug_slot_info *info)
630{ 695{
696 int retval;
697
631 if ((slot == NULL) || (info == NULL)) 698 if ((slot == NULL) || (info == NULL))
632 return -ENODEV; 699 return -ENODEV;
633 700
@@ -636,32 +703,60 @@ int pci_hp_change_slot_info (struct hotplug_slot *slot, struct hotplug_slot_info
636 * for the files referring to the fields that have now changed. 703 * for the files referring to the fields that have now changed.
637 */ 704 */
638 if ((has_power_file(slot) == 0) && 705 if ((has_power_file(slot) == 0) &&
639 (slot->info->power_status != info->power_status)) 706 (slot->info->power_status != info->power_status)) {
640 sysfs_update_file(&slot->kobj, &hotplug_slot_attr_power.attr); 707 retval = sysfs_update_file(&slot->kobj,
708 &hotplug_slot_attr_power.attr);
709 if (retval)
710 return retval;
711 }
641 712
642 if ((has_attention_file(slot) == 0) && 713 if ((has_attention_file(slot) == 0) &&
643 (slot->info->attention_status != info->attention_status)) 714 (slot->info->attention_status != info->attention_status)) {
644 sysfs_update_file(&slot->kobj, &hotplug_slot_attr_attention.attr); 715 retval = sysfs_update_file(&slot->kobj,
716 &hotplug_slot_attr_attention.attr);
717 if (retval)
718 return retval;
719 }
645 720
646 if ((has_latch_file(slot) == 0) && 721 if ((has_latch_file(slot) == 0) &&
647 (slot->info->latch_status != info->latch_status)) 722 (slot->info->latch_status != info->latch_status)) {
648 sysfs_update_file(&slot->kobj, &hotplug_slot_attr_latch.attr); 723 retval = sysfs_update_file(&slot->kobj,
724 &hotplug_slot_attr_latch.attr);
725 if (retval)
726 return retval;
727 }
649 728
650 if ((has_adapter_file(slot) == 0) && 729 if ((has_adapter_file(slot) == 0) &&
651 (slot->info->adapter_status != info->adapter_status)) 730 (slot->info->adapter_status != info->adapter_status)) {
652 sysfs_update_file(&slot->kobj, &hotplug_slot_attr_presence.attr); 731 retval = sysfs_update_file(&slot->kobj,
732 &hotplug_slot_attr_presence.attr);
733 if (retval)
734 return retval;
735 }
653 736
654 if ((has_address_file(slot) == 0) && 737 if ((has_address_file(slot) == 0) &&
655 (slot->info->address != info->address)) 738 (slot->info->address != info->address)) {
656 sysfs_update_file(&slot->kobj, &hotplug_slot_attr_address.attr); 739 retval = sysfs_update_file(&slot->kobj,
740 &hotplug_slot_attr_address.attr);
741 if (retval)
742 return retval;
743 }
657 744
658 if ((has_max_bus_speed_file(slot) == 0) && 745 if ((has_max_bus_speed_file(slot) == 0) &&
659 (slot->info->max_bus_speed != info->max_bus_speed)) 746 (slot->info->max_bus_speed != info->max_bus_speed)) {
660 sysfs_update_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); 747 retval = sysfs_update_file(&slot->kobj,
748 &hotplug_slot_attr_max_bus_speed.attr);
749 if (retval)
750 return retval;
751 }
661 752
662 if ((has_cur_bus_speed_file(slot) == 0) && 753 if ((has_cur_bus_speed_file(slot) == 0) &&
663 (slot->info->cur_bus_speed != info->cur_bus_speed)) 754 (slot->info->cur_bus_speed != info->cur_bus_speed)) {
664 sysfs_update_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr); 755 retval = sysfs_update_file(&slot->kobj,
756 &hotplug_slot_attr_cur_bus_speed.attr);
757 if (retval)
758 return retval;
759 }
665 760
666 memcpy (slot->info, info, sizeof (struct hotplug_slot_info)); 761 memcpy (slot->info, info, sizeof (struct hotplug_slot_info));
667 762
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 33d198768356..41290a106bd8 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -762,14 +762,14 @@ int pciehp_enable_slot(struct slot *p_slot)
762 if (rc || !getstatus) { 762 if (rc || !getstatus) {
763 info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); 763 info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
764 mutex_unlock(&p_slot->ctrl->crit_sect); 764 mutex_unlock(&p_slot->ctrl->crit_sect);
765 return 1; 765 return -ENODEV;
766 } 766 }
767 if (MRL_SENS(p_slot->ctrl->ctrlcap)) { 767 if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
768 rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 768 rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
769 if (rc || getstatus) { 769 if (rc || getstatus) {
770 info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); 770 info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
771 mutex_unlock(&p_slot->ctrl->crit_sect); 771 mutex_unlock(&p_slot->ctrl->crit_sect);
772 return 1; 772 return -ENODEV;
773 } 773 }
774 } 774 }
775 775
@@ -778,7 +778,7 @@ int pciehp_enable_slot(struct slot *p_slot)
778 if (rc || getstatus) { 778 if (rc || getstatus) {
779 info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); 779 info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
780 mutex_unlock(&p_slot->ctrl->crit_sect); 780 mutex_unlock(&p_slot->ctrl->crit_sect);
781 return 1; 781 return -EINVAL;
782 } 782 }
783 } 783 }
784 mutex_unlock(&p_slot->ctrl->crit_sect); 784 mutex_unlock(&p_slot->ctrl->crit_sect);
@@ -813,7 +813,7 @@ int pciehp_disable_slot(struct slot *p_slot)
813 if (ret || !getstatus) { 813 if (ret || !getstatus) {
814 info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); 814 info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
815 mutex_unlock(&p_slot->ctrl->crit_sect); 815 mutex_unlock(&p_slot->ctrl->crit_sect);
816 return 1; 816 return -ENODEV;
817 } 817 }
818 } 818 }
819 819
@@ -822,7 +822,7 @@ int pciehp_disable_slot(struct slot *p_slot)
822 if (ret || getstatus) { 822 if (ret || getstatus) {
823 info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); 823 info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
824 mutex_unlock(&p_slot->ctrl->crit_sect); 824 mutex_unlock(&p_slot->ctrl->crit_sect);
825 return 1; 825 return -ENODEV;
826 } 826 }
827 } 827 }
828 828
@@ -831,7 +831,7 @@ int pciehp_disable_slot(struct slot *p_slot)
831 if (ret || !getstatus) { 831 if (ret || !getstatus) {
832 info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); 832 info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
833 mutex_unlock(&p_slot->ctrl->crit_sect); 833 mutex_unlock(&p_slot->ctrl->crit_sect);
834 return 1; 834 return -EINVAL;
835 } 835 }
836 } 836 }
837 837
diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c
index 8ad446605f75..2b9e10e38613 100644
--- a/drivers/pci/hotplug/pcihp_skeleton.c
+++ b/drivers/pci/hotplug/pcihp_skeleton.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * PCI Hot Plug Controller Skeleton Driver - 0.2 2 * PCI Hot Plug Controller Skeleton Driver - 0.3
3 * 3 *
4 * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) 4 * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
5 * Copyright (C) 2001,2003 IBM Corp. 5 * Copyright (C) 2001,2003 IBM Corp.
@@ -21,7 +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 * This driver is to be used as a skeleton driver to be show how to interface 24 * This driver is to be used as a skeleton driver to show how to interface
25 * with the pci hotplug core easily. 25 * with the pci hotplug core easily.
26 * 26 *
27 * Send feedback to <greg@kroah.com> 27 * Send feedback to <greg@kroah.com>
@@ -58,8 +58,6 @@ static LIST_HEAD(slot_list);
58#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) 58#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
59#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) 59#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
60 60
61
62
63/* local variables */ 61/* local variables */
64static int debug; 62static int debug;
65static int num_slots; 63static int num_slots;
@@ -109,7 +107,6 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
109 return retval; 107 return retval;
110} 108}
111 109
112
113static int disable_slot(struct hotplug_slot *hotplug_slot) 110static int disable_slot(struct hotplug_slot *hotplug_slot)
114{ 111{
115 struct slot *slot = hotplug_slot->private; 112 struct slot *slot = hotplug_slot->private;
@@ -342,7 +339,7 @@ static int __init pcihp_skel_init(void)
342 info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); 339 info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
343 /* 340 /*
344 * Do specific initialization stuff for your driver here 341 * Do specific initialization stuff for your driver here
345 * Like initializing your controller hardware (if any) and 342 * like initializing your controller hardware (if any) and
346 * determining the number of slots you have in the system 343 * determining the number of slots you have in the system
347 * right now. 344 * right now.
348 */ 345 */
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index 7208b95c6ee7..c7103ac5cd06 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -173,7 +173,7 @@ struct controller {
173#define msg_button_cancel "PCI slot #%s - action canceled due to button press.\n" 173#define msg_button_cancel "PCI slot #%s - action canceled due to button press.\n"
174 174
175/* sysfs functions for the hotplug controller info */ 175/* sysfs functions for the hotplug controller info */
176extern void shpchp_create_ctrl_files (struct controller *ctrl); 176extern int __must_check shpchp_create_ctrl_files(struct controller *ctrl);
177 177
178extern int shpchp_sysfs_enable_slot(struct slot *slot); 178extern int shpchp_sysfs_enable_slot(struct slot *slot);
179extern int shpchp_sysfs_disable_slot(struct slot *slot); 179extern int shpchp_sysfs_disable_slot(struct slot *slot);
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index a14e7de19846..235c18a22393 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -449,10 +449,14 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
449 ctrl->speed = PCI_SPEED_33MHz; 449 ctrl->speed = PCI_SPEED_33MHz;
450 } 450 }
451 451
452 shpchp_create_ctrl_files(ctrl); 452 rc = shpchp_create_ctrl_files(ctrl);
453 if (rc)
454 goto err_cleanup_slots;
453 455
454 return 0; 456 return 0;
455 457
458err_cleanup_slots:
459 cleanup_slots(ctrl);
456err_out_release_ctlr: 460err_out_release_ctlr:
457 ctrl->hpc_ops->release_ctlr(ctrl); 461 ctrl->hpc_ops->release_ctlr(ctrl);
458err_out_free_ctrl: 462err_out_free_ctrl:
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c
index 620e1139e607..29fa9d26adae 100644
--- a/drivers/pci/hotplug/shpchp_sysfs.c
+++ b/drivers/pci/hotplug/shpchp_sysfs.c
@@ -91,9 +91,9 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha
91} 91}
92static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL); 92static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
93 93
94void shpchp_create_ctrl_files (struct controller *ctrl) 94int __must_check shpchp_create_ctrl_files (struct controller *ctrl)
95{ 95{
96 device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl); 96 return device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
97} 97}
98 98
99void shpchp_remove_ctrl_files(struct controller *ctrl) 99void shpchp_remove_ctrl_files(struct controller *ctrl)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index a83c1f5735d6..27a057409eca 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -45,16 +45,10 @@ msi_register(struct msi_ops *ops)
45 return 0; 45 return 0;
46} 46}
47 47
48static void msi_cache_ctor(void *p, kmem_cache_t *cache, unsigned long flags)
49{
50 memset(p, 0, sizeof(struct msi_desc));
51}
52
53static int msi_cache_init(void) 48static int msi_cache_init(void)
54{ 49{
55 msi_cachep = kmem_cache_create("msi_cache", 50 msi_cachep = kmem_cache_create("msi_cache", sizeof(struct msi_desc),
56 sizeof(struct msi_desc), 51 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
57 0, SLAB_HWCACHE_ALIGN, msi_cache_ctor, NULL);
58 if (!msi_cachep) 52 if (!msi_cachep)
59 return -ENOMEM; 53 return -ENOMEM;
60 54
@@ -402,11 +396,10 @@ static struct msi_desc* alloc_msi_entry(void)
402{ 396{
403 struct msi_desc *entry; 397 struct msi_desc *entry;
404 398
405 entry = kmem_cache_alloc(msi_cachep, SLAB_KERNEL); 399 entry = kmem_cache_zalloc(msi_cachep, GFP_KERNEL);
406 if (!entry) 400 if (!entry)
407 return NULL; 401 return NULL;
408 402
409 memset(entry, 0, sizeof(struct msi_desc));
410 entry->link.tail = entry->link.head = 0; /* single message */ 403 entry->link.tail = entry->link.head = 0; /* single message */
411 entry->dev = NULL; 404 entry->dev = NULL;
412 405
@@ -901,6 +894,33 @@ static int msix_capability_init(struct pci_dev *dev,
901} 894}
902 895
903/** 896/**
897 * pci_msi_supported - check whether MSI may be enabled on device
898 * @dev: pointer to the pci_dev data structure of MSI device function
899 *
900 * MSI must be globally enabled and supported by the device and its root
901 * bus. But, the root bus is not easy to find since some architectures
902 * have virtual busses on top of the PCI hierarchy (for instance the
903 * hypertransport bus), while the actual bus where MSI must be supported
904 * is below. So we test the MSI flag on all parent busses and assume
905 * that no quirk will ever set the NO_MSI flag on a non-root bus.
906 **/
907static
908int pci_msi_supported(struct pci_dev * dev)
909{
910 struct pci_bus *bus;
911
912 if (!pci_msi_enable || !dev || dev->no_msi)
913 return -EINVAL;
914
915 /* check MSI flags of all parent busses */
916 for (bus = dev->bus; bus; bus = bus->parent)
917 if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
918 return -EINVAL;
919
920 return 0;
921}
922
923/**
904 * pci_enable_msi - configure device's MSI capability structure 924 * pci_enable_msi - configure device's MSI capability structure
905 * @dev: pointer to the pci_dev data structure of MSI device function 925 * @dev: pointer to the pci_dev data structure of MSI device function
906 * 926 *
@@ -912,19 +932,11 @@ static int msix_capability_init(struct pci_dev *dev,
912 **/ 932 **/
913int pci_enable_msi(struct pci_dev* dev) 933int pci_enable_msi(struct pci_dev* dev)
914{ 934{
915 struct pci_bus *bus; 935 int pos, temp, status;
916 int pos, temp, status = -EINVAL;
917 u16 control; 936 u16 control;
918 937
919 if (!pci_msi_enable || !dev) 938 if (pci_msi_supported(dev) < 0)
920 return status; 939 return -EINVAL;
921
922 if (dev->no_msi)
923 return status;
924
925 for (bus = dev->bus; bus; bus = bus->parent)
926 if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
927 return -EINVAL;
928 940
929 temp = dev->irq; 941 temp = dev->irq;
930 942
@@ -1134,22 +1146,14 @@ static int reroute_msix_table(int head, struct msix_entry *entries, int *nvec)
1134 **/ 1146 **/
1135int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) 1147int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
1136{ 1148{
1137 struct pci_bus *bus;
1138 int status, pos, nr_entries, free_vectors; 1149 int status, pos, nr_entries, free_vectors;
1139 int i, j, temp; 1150 int i, j, temp;
1140 u16 control; 1151 u16 control;
1141 unsigned long flags; 1152 unsigned long flags;
1142 1153
1143 if (!pci_msi_enable || !dev || !entries) 1154 if (!entries || pci_msi_supported(dev) < 0)
1144 return -EINVAL; 1155 return -EINVAL;
1145 1156
1146 if (dev->no_msi)
1147 return -EINVAL;
1148
1149 for (bus = dev->bus; bus; bus = bus->parent)
1150 if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
1151 return -EINVAL;
1152
1153 status = msi_init(); 1157 status = msi_init();
1154 if (status < 0) 1158 if (status < 0)
1155 return status; 1159 return status;
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 474e9cd0e9e4..b1c0c707d96c 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -17,6 +17,16 @@
17 * Registration of PCI drivers and handling of hot-pluggable devices. 17 * Registration of PCI drivers and handling of hot-pluggable devices.
18 */ 18 */
19 19
20/* multithreaded probe logic */
21static int pci_multithread_probe =
22#ifdef CONFIG_PCI_MULTITHREAD_PROBE
23 1;
24#else
25 0;
26#endif
27__module_param_call("", pci_multithread_probe, param_set_bool, param_get_bool, &pci_multithread_probe, 0644);
28
29
20/* 30/*
21 * Dynamic device IDs are disabled for !CONFIG_HOTPLUG 31 * Dynamic device IDs are disabled for !CONFIG_HOTPLUG
22 */ 32 */
@@ -46,6 +56,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
46 subdevice=PCI_ANY_ID, class=0, class_mask=0; 56 subdevice=PCI_ANY_ID, class=0, class_mask=0;
47 unsigned long driver_data=0; 57 unsigned long driver_data=0;
48 int fields=0; 58 int fields=0;
59 int retval = 0;
49 60
50 fields = sscanf(buf, "%x %x %x %x %x %x %lux", 61 fields = sscanf(buf, "%x %x %x %x %x %x %lux",
51 &vendor, &device, &subvendor, &subdevice, 62 &vendor, &device, &subvendor, &subdevice,
@@ -72,10 +83,12 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
72 spin_unlock(&pdrv->dynids.lock); 83 spin_unlock(&pdrv->dynids.lock);
73 84
74 if (get_driver(&pdrv->driver)) { 85 if (get_driver(&pdrv->driver)) {
75 driver_attach(&pdrv->driver); 86 retval = driver_attach(&pdrv->driver);
76 put_driver(&pdrv->driver); 87 put_driver(&pdrv->driver);
77 } 88 }
78 89
90 if (retval)
91 return retval;
79 return count; 92 return count;
80} 93}
81static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); 94static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
@@ -279,6 +292,18 @@ static int pci_device_suspend(struct device * dev, pm_message_t state)
279 return i; 292 return i;
280} 293}
281 294
295static int pci_device_suspend_late(struct device * dev, pm_message_t state)
296{
297 struct pci_dev * pci_dev = to_pci_dev(dev);
298 struct pci_driver * drv = pci_dev->driver;
299 int i = 0;
300
301 if (drv && drv->suspend_late) {
302 i = drv->suspend_late(pci_dev, state);
303 suspend_report_result(drv->suspend_late, i);
304 }
305 return i;
306}
282 307
283/* 308/*
284 * Default resume method for devices that have no driver provided resume, 309 * Default resume method for devices that have no driver provided resume,
@@ -313,6 +338,17 @@ static int pci_device_resume(struct device * dev)
313 return error; 338 return error;
314} 339}
315 340
341static int pci_device_resume_early(struct device * dev)
342{
343 int error = 0;
344 struct pci_dev * pci_dev = to_pci_dev(dev);
345 struct pci_driver * drv = pci_dev->driver;
346
347 if (drv && drv->resume_early)
348 error = drv->resume_early(pci_dev);
349 return error;
350}
351
316static void pci_device_shutdown(struct device *dev) 352static void pci_device_shutdown(struct device *dev)
317{ 353{
318 struct pci_dev *pci_dev = to_pci_dev(dev); 354 struct pci_dev *pci_dev = to_pci_dev(dev);
@@ -386,6 +422,11 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner)
386 drv->driver.owner = owner; 422 drv->driver.owner = owner;
387 drv->driver.kobj.ktype = &pci_driver_kobj_type; 423 drv->driver.kobj.ktype = &pci_driver_kobj_type;
388 424
425 if (pci_multithread_probe)
426 drv->driver.multithread_probe = pci_multithread_probe;
427 else
428 drv->driver.multithread_probe = drv->multithread_probe;
429
389 spin_lock_init(&drv->dynids.lock); 430 spin_lock_init(&drv->dynids.lock);
390 INIT_LIST_HEAD(&drv->dynids.list); 431 INIT_LIST_HEAD(&drv->dynids.list);
391 432
@@ -509,8 +550,10 @@ struct bus_type pci_bus_type = {
509 .probe = pci_device_probe, 550 .probe = pci_device_probe,
510 .remove = pci_device_remove, 551 .remove = pci_device_remove,
511 .suspend = pci_device_suspend, 552 .suspend = pci_device_suspend,
512 .shutdown = pci_device_shutdown, 553 .suspend_late = pci_device_suspend_late,
554 .resume_early = pci_device_resume_early,
513 .resume = pci_device_resume, 555 .resume = pci_device_resume,
556 .shutdown = pci_device_shutdown,
514 .dev_attrs = pci_dev_attrs, 557 .dev_attrs = pci_dev_attrs,
515}; 558};
516 559
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index fdefa7dcd156..a1d2e979b17f 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -117,6 +117,7 @@ is_enabled_store(struct device *dev, struct device_attribute *attr,
117 const char *buf, size_t count) 117 const char *buf, size_t count)
118{ 118{
119 struct pci_dev *pdev = to_pci_dev(dev); 119 struct pci_dev *pdev = to_pci_dev(dev);
120 int retval = 0;
120 121
121 /* this can crash the machine when done on the "wrong" device */ 122 /* this can crash the machine when done on the "wrong" device */
122 if (!capable(CAP_SYS_ADMIN)) 123 if (!capable(CAP_SYS_ADMIN))
@@ -126,11 +127,53 @@ is_enabled_store(struct device *dev, struct device_attribute *attr,
126 pci_disable_device(pdev); 127 pci_disable_device(pdev);
127 128
128 if (*buf == '1') 129 if (*buf == '1')
129 pci_enable_device(pdev); 130 retval = pci_enable_device(pdev);
130 131
132 if (retval)
133 return retval;
131 return count; 134 return count;
132} 135}
133 136
137static ssize_t
138msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf)
139{
140 struct pci_dev *pdev = to_pci_dev(dev);
141
142 if (!pdev->subordinate)
143 return 0;
144
145 return sprintf (buf, "%u\n",
146 !(pdev->subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI));
147}
148
149static ssize_t
150msi_bus_store(struct device *dev, struct device_attribute *attr,
151 const char *buf, size_t count)
152{
153 struct pci_dev *pdev = to_pci_dev(dev);
154
155 /* bad things may happen if the no_msi flag is changed
156 * while some drivers are loaded */
157 if (!capable(CAP_SYS_ADMIN))
158 return count;
159
160 if (!pdev->subordinate)
161 return count;
162
163 if (*buf == '0') {
164 pdev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
165 dev_warn(&pdev->dev, "forced subordinate bus to not support MSI,"
166 " bad things could happen.\n");
167 }
168
169 if (*buf == '1') {
170 pdev->subordinate->bus_flags &= ~PCI_BUS_FLAGS_NO_MSI;
171 dev_warn(&pdev->dev, "forced subordinate bus to support MSI,"
172 " bad things could happen.\n");
173 }
174
175 return count;
176}
134 177
135struct device_attribute pci_dev_attrs[] = { 178struct device_attribute pci_dev_attrs[] = {
136 __ATTR_RO(resource), 179 __ATTR_RO(resource),
@@ -145,6 +188,7 @@ struct device_attribute pci_dev_attrs[] = {
145 __ATTR(enable, 0600, is_enabled_show, is_enabled_store), 188 __ATTR(enable, 0600, is_enabled_show, is_enabled_store),
146 __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR), 189 __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR),
147 broken_parity_status_show,broken_parity_status_store), 190 broken_parity_status_show,broken_parity_status_store),
191 __ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store),
148 __ATTR_NULL, 192 __ATTR_NULL,
149}; 193};
150 194
@@ -385,15 +429,38 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
385} 429}
386 430
387/** 431/**
432 * pci_remove_resource_files - cleanup resource files
433 * @dev: dev to cleanup
434 *
435 * If we created resource files for @dev, remove them from sysfs and
436 * free their resources.
437 */
438static void
439pci_remove_resource_files(struct pci_dev *pdev)
440{
441 int i;
442
443 for (i = 0; i < PCI_ROM_RESOURCE; i++) {
444 struct bin_attribute *res_attr;
445
446 res_attr = pdev->res_attr[i];
447 if (res_attr) {
448 sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
449 kfree(res_attr);
450 }
451 }
452}
453
454/**
388 * pci_create_resource_files - create resource files in sysfs for @dev 455 * pci_create_resource_files - create resource files in sysfs for @dev
389 * @dev: dev in question 456 * @dev: dev in question
390 * 457 *
391 * Walk the resources in @dev creating files for each resource available. 458 * Walk the resources in @dev creating files for each resource available.
392 */ 459 */
393static void 460static int pci_create_resource_files(struct pci_dev *pdev)
394pci_create_resource_files(struct pci_dev *pdev)
395{ 461{
396 int i; 462 int i;
463 int retval;
397 464
398 /* Expose the PCI resources from this device as files */ 465 /* Expose the PCI resources from this device as files */
399 for (i = 0; i < PCI_ROM_RESOURCE; i++) { 466 for (i = 0; i < PCI_ROM_RESOURCE; i++) {
@@ -416,35 +483,19 @@ pci_create_resource_files(struct pci_dev *pdev)
416 res_attr->size = pci_resource_len(pdev, i); 483 res_attr->size = pci_resource_len(pdev, i);
417 res_attr->mmap = pci_mmap_resource; 484 res_attr->mmap = pci_mmap_resource;
418 res_attr->private = &pdev->resource[i]; 485 res_attr->private = &pdev->resource[i];
419 sysfs_create_bin_file(&pdev->dev.kobj, res_attr); 486 retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
420 } 487 if (retval) {
421 } 488 pci_remove_resource_files(pdev);
422} 489 return retval;
423 490 }
424/** 491 } else {
425 * pci_remove_resource_files - cleanup resource files 492 return -ENOMEM;
426 * @dev: dev to cleanup
427 *
428 * If we created resource files for @dev, remove them from sysfs and
429 * free their resources.
430 */
431static void
432pci_remove_resource_files(struct pci_dev *pdev)
433{
434 int i;
435
436 for (i = 0; i < PCI_ROM_RESOURCE; i++) {
437 struct bin_attribute *res_attr;
438
439 res_attr = pdev->res_attr[i];
440 if (res_attr) {
441 sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
442 kfree(res_attr);
443 } 493 }
444 } 494 }
495 return 0;
445} 496}
446#else /* !HAVE_PCI_MMAP */ 497#else /* !HAVE_PCI_MMAP */
447static inline void pci_create_resource_files(struct pci_dev *dev) { return; } 498static inline int pci_create_resource_files(struct pci_dev *dev) { return 0; }
448static inline void pci_remove_resource_files(struct pci_dev *dev) { return; } 499static inline void pci_remove_resource_files(struct pci_dev *dev) { return; }
449#endif /* HAVE_PCI_MMAP */ 500#endif /* HAVE_PCI_MMAP */
450 501
@@ -529,22 +580,27 @@ static struct bin_attribute pcie_config_attr = {
529 .write = pci_write_config, 580 .write = pci_write_config,
530}; 581};
531 582
532int pci_create_sysfs_dev_files (struct pci_dev *pdev) 583int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
533{ 584{
585 struct bin_attribute *rom_attr = NULL;
586 int retval;
587
534 if (!sysfs_initialized) 588 if (!sysfs_initialized)
535 return -EACCES; 589 return -EACCES;
536 590
537 if (pdev->cfg_size < 4096) 591 if (pdev->cfg_size < 4096)
538 sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr); 592 retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
539 else 593 else
540 sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr); 594 retval = sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
595 if (retval)
596 goto err;
541 597
542 pci_create_resource_files(pdev); 598 retval = pci_create_resource_files(pdev);
599 if (retval)
600 goto err_bin_file;
543 601
544 /* If the device has a ROM, try to expose it in sysfs. */ 602 /* If the device has a ROM, try to expose it in sysfs. */
545 if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) { 603 if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
546 struct bin_attribute *rom_attr;
547
548 rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC); 604 rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC);
549 if (rom_attr) { 605 if (rom_attr) {
550 pdev->rom_attr = rom_attr; 606 pdev->rom_attr = rom_attr;
@@ -554,13 +610,28 @@ int pci_create_sysfs_dev_files (struct pci_dev *pdev)
554 rom_attr->attr.owner = THIS_MODULE; 610 rom_attr->attr.owner = THIS_MODULE;
555 rom_attr->read = pci_read_rom; 611 rom_attr->read = pci_read_rom;
556 rom_attr->write = pci_write_rom; 612 rom_attr->write = pci_write_rom;
557 sysfs_create_bin_file(&pdev->dev.kobj, rom_attr); 613 retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
614 if (retval)
615 goto err_rom;
616 } else {
617 retval = -ENOMEM;
618 goto err_bin_file;
558 } 619 }
559 } 620 }
560 /* add platform-specific attributes */ 621 /* add platform-specific attributes */
561 pcibios_add_platform_entries(pdev); 622 pcibios_add_platform_entries(pdev);
562 623
563 return 0; 624 return 0;
625
626err_rom:
627 kfree(rom_attr);
628err_bin_file:
629 if (pdev->cfg_size < 4096)
630 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
631 else
632 sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
633err:
634 return retval;
564} 635}
565 636
566/** 637/**
@@ -589,10 +660,14 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
589static int __init pci_sysfs_init(void) 660static int __init pci_sysfs_init(void)
590{ 661{
591 struct pci_dev *pdev = NULL; 662 struct pci_dev *pdev = NULL;
592 663 int retval;
664
593 sysfs_initialized = 1; 665 sysfs_initialized = 1;
594 for_each_pci_dev(pdev) 666 for_each_pci_dev(pdev) {
595 pci_create_sysfs_dev_files(pdev); 667 retval = pci_create_sysfs_dev_files(pdev);
668 if (retval)
669 return retval;
670 }
596 671
597 return 0; 672 return 0;
598} 673}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 9f79dd6d51ab..a544997399b3 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -432,10 +432,12 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
432 case PM_EVENT_ON: 432 case PM_EVENT_ON:
433 return PCI_D0; 433 return PCI_D0;
434 case PM_EVENT_FREEZE: 434 case PM_EVENT_FREEZE:
435 case PM_EVENT_PRETHAW:
436 /* REVISIT both freeze and pre-thaw "should" use D0 */
435 case PM_EVENT_SUSPEND: 437 case PM_EVENT_SUSPEND:
436 return PCI_D3hot; 438 return PCI_D3hot;
437 default: 439 default:
438 printk("They asked me for state %d\n", state.event); 440 printk("Unrecognized suspend event %d\n", state.event);
439 BUG(); 441 BUG();
440 } 442 }
441 return PCI_D0; 443 return PCI_D0;
@@ -443,6 +445,51 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
443 445
444EXPORT_SYMBOL(pci_choose_state); 446EXPORT_SYMBOL(pci_choose_state);
445 447
448static int pci_save_pcie_state(struct pci_dev *dev)
449{
450 int pos, i = 0;
451 struct pci_cap_saved_state *save_state;
452 u16 *cap;
453
454 pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
455 if (pos <= 0)
456 return 0;
457
458 save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
459 if (!save_state) {
460 dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
461 return -ENOMEM;
462 }
463 cap = (u16 *)&save_state->data[0];
464
465 pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &cap[i++]);
466 pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
467 pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
468 pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
469 pci_add_saved_cap(dev, save_state);
470 return 0;
471}
472
473static void pci_restore_pcie_state(struct pci_dev *dev)
474{
475 int i = 0, pos;
476 struct pci_cap_saved_state *save_state;
477 u16 *cap;
478
479 save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
480 pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
481 if (!save_state || pos <= 0)
482 return;
483 cap = (u16 *)&save_state->data[0];
484
485 pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, cap[i++]);
486 pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]);
487 pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]);
488 pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]);
489 pci_remove_saved_cap(save_state);
490 kfree(save_state);
491}
492
446/** 493/**
447 * pci_save_state - save the PCI configuration space of a device before suspending 494 * pci_save_state - save the PCI configuration space of a device before suspending
448 * @dev: - PCI device that we're dealing with 495 * @dev: - PCI device that we're dealing with
@@ -458,6 +505,8 @@ pci_save_state(struct pci_dev *dev)
458 return i; 505 return i;
459 if ((i = pci_save_msix_state(dev)) != 0) 506 if ((i = pci_save_msix_state(dev)) != 0)
460 return i; 507 return i;
508 if ((i = pci_save_pcie_state(dev)) != 0)
509 return i;
461 return 0; 510 return 0;
462} 511}
463 512
@@ -471,6 +520,9 @@ pci_restore_state(struct pci_dev *dev)
471 int i; 520 int i;
472 int val; 521 int val;
473 522
523 /* PCI Express register must be restored first */
524 pci_restore_pcie_state(dev);
525
474 /* 526 /*
475 * The Base Address register should be programmed before the command 527 * The Base Address register should be programmed before the command
476 * register(s) 528 * register(s)
@@ -953,13 +1005,12 @@ static int __devinit pci_setup(char *str)
953 } 1005 }
954 str = k; 1006 str = k;
955 } 1007 }
956 return 1; 1008 return 0;
957} 1009}
1010early_param("pci", pci_setup);
958 1011
959device_initcall(pci_init); 1012device_initcall(pci_init);
960 1013
961__setup("pci=", pci_setup);
962
963#if defined(CONFIG_ISA) || defined(CONFIG_EISA) 1014#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
964/* FIXME: Some boxes have multiple ISA bridges! */ 1015/* FIXME: Some boxes have multiple ISA bridges! */
965struct pci_dev *isa_bridge; 1016struct pci_dev *isa_bridge;
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 08d58fc78ee1..6bf327db5c5e 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -42,7 +42,7 @@ extern void pci_remove_legacy_files(struct pci_bus *bus);
42/* Lock for read/write access to pci device and bus lists */ 42/* Lock for read/write access to pci device and bus lists */
43extern struct rw_semaphore pci_bus_sem; 43extern struct rw_semaphore pci_bus_sem;
44 44
45#ifdef CONFIG_X86_IO_APIC 45#ifdef CONFIG_PCI_MSI
46extern int pci_msi_quirk; 46extern int pci_msi_quirk;
47#else 47#else
48#define pci_msi_quirk 0 48#define pci_msi_quirk 0
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
index 1012db8b8b2c..0ad92a8ad8b1 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -34,3 +34,4 @@ config HOTPLUG_PCI_PCIE_POLL_EVENT_MODE
34 34
35 When in doubt, say N. 35 When in doubt, say N.
36 36
37source "drivers/pci/pcie/aer/Kconfig"
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile
index 984fa87283e3..e00fb99acf44 100644
--- a/drivers/pci/pcie/Makefile
+++ b/drivers/pci/pcie/Makefile
@@ -5,3 +5,6 @@
5pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o 5pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o
6 6
7obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o 7obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
8
9# Build PCI Express AER if needed
10obj-$(CONFIG_PCIEAER) += aer/
diff --git a/drivers/pci/pcie/aer/Kconfig b/drivers/pci/pcie/aer/Kconfig
new file mode 100644
index 000000000000..3f37a60a6438
--- /dev/null
+++ b/drivers/pci/pcie/aer/Kconfig
@@ -0,0 +1,12 @@
1#
2# PCI Express Root Port Device AER Configuration
3#
4
5config PCIEAER
6 boolean "Root Port Advanced Error Reporting support"
7 depends on PCIEPORTBUS && ACPI
8 default y
9 help
10 This enables PCI Express Root Port Advanced Error Reporting
11 (AER) driver support. Error reporting messages sent to Root
12 Port will be handled by PCI Express AER driver.
diff --git a/drivers/pci/pcie/aer/Makefile b/drivers/pci/pcie/aer/Makefile
new file mode 100644
index 000000000000..15a4f40d520b
--- /dev/null
+++ b/drivers/pci/pcie/aer/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for PCI-Express Root Port Advanced Error Reporting Driver
3#
4
5obj-$(CONFIG_PCIEAER) += aerdriver.o
6
7aerdriver-objs := aerdrv_errprint.o aerdrv_core.o aerdrv.o aerdrv_acpi.o
8
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
new file mode 100644
index 000000000000..0d4ac027d53e
--- /dev/null
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -0,0 +1,346 @@
1/*
2 * drivers/pci/pcie/aer/aerdrv.c
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * This file implements the AER root port service driver. The driver will
9 * register an irq handler. When root port triggers an AER interrupt, the irq
10 * handler will collect root port status and schedule a work.
11 *
12 * Copyright (C) 2006 Intel Corp.
13 * Tom Long Nguyen (tom.l.nguyen@intel.com)
14 * Zhang Yanmin (yanmin.zhang@intel.com)
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/pci.h>
20#include <linux/kernel.h>
21#include <linux/errno.h>
22#include <linux/pm.h>
23#include <linux/init.h>
24#include <linux/interrupt.h>
25#include <linux/delay.h>
26#include <linux/pcieport_if.h>
27
28#include "aerdrv.h"
29
30/*
31 * Version Information
32 */
33#define DRIVER_VERSION "v1.0"
34#define DRIVER_AUTHOR "tom.l.nguyen@intel.com"
35#define DRIVER_DESC "Root Port Advanced Error Reporting Driver"
36MODULE_AUTHOR(DRIVER_AUTHOR);
37MODULE_DESCRIPTION(DRIVER_DESC);
38MODULE_LICENSE("GPL");
39
40static int __devinit aer_probe (struct pcie_device *dev,
41 const struct pcie_port_service_id *id );
42static void aer_remove(struct pcie_device *dev);
43static int aer_suspend(struct pcie_device *dev, pm_message_t state)
44{return 0;}
45static int aer_resume(struct pcie_device *dev) {return 0;}
46static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
47 enum pci_channel_state error);
48static void aer_error_resume(struct pci_dev *dev);
49static pci_ers_result_t aer_root_reset(struct pci_dev *dev);
50
51/*
52 * PCI Express bus's AER Root service driver data structure
53 */
54static struct pcie_port_service_id aer_id[] = {
55 {
56 .vendor = PCI_ANY_ID,
57 .device = PCI_ANY_ID,
58 .port_type = PCIE_RC_PORT,
59 .service_type = PCIE_PORT_SERVICE_AER,
60 },
61 { /* end: all zeroes */ }
62};
63
64static struct pci_error_handlers aer_error_handlers = {
65 .error_detected = aer_error_detected,
66 .resume = aer_error_resume,
67};
68
69static struct pcie_port_service_driver aerdrv = {
70 .name = "aer",
71 .id_table = &aer_id[0],
72
73 .probe = aer_probe,
74 .remove = aer_remove,
75
76 .suspend = aer_suspend,
77 .resume = aer_resume,
78
79 .err_handler = &aer_error_handlers,
80
81 .reset_link = aer_root_reset,
82};
83
84/**
85 * aer_irq - Root Port's ISR
86 * @irq: IRQ assigned to Root Port
87 * @context: pointer to Root Port data structure
88 * @r: pointer struct pt_regs
89 *
90 * Invoked when Root Port detects AER messages.
91 **/
92static irqreturn_t aer_irq(int irq, void *context, struct pt_regs * r)
93{
94 unsigned int status, id;
95 struct pcie_device *pdev = (struct pcie_device *)context;
96 struct aer_rpc *rpc = get_service_data(pdev);
97 int next_prod_idx;
98 unsigned long flags;
99 int pos;
100
101 pos = pci_find_aer_capability(pdev->port);
102 /*
103 * Must lock access to Root Error Status Reg, Root Error ID Reg,
104 * and Root error producer/consumer index
105 */
106 spin_lock_irqsave(&rpc->e_lock, flags);
107
108 /* Read error status */
109 pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status);
110 if (!(status & ROOT_ERR_STATUS_MASKS)) {
111 spin_unlock_irqrestore(&rpc->e_lock, flags);
112 return IRQ_NONE;
113 }
114
115 /* Read error source and clear error status */
116 pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_COR_SRC, &id);
117 pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status);
118
119 /* Store error source for later DPC handler */
120 next_prod_idx = rpc->prod_idx + 1;
121 if (next_prod_idx == AER_ERROR_SOURCES_MAX)
122 next_prod_idx = 0;
123 if (next_prod_idx == rpc->cons_idx) {
124 /*
125 * Error Storm Condition - possibly the same error occurred.
126 * Drop the error.
127 */
128 spin_unlock_irqrestore(&rpc->e_lock, flags);
129 return IRQ_HANDLED;
130 }
131 rpc->e_sources[rpc->prod_idx].status = status;
132 rpc->e_sources[rpc->prod_idx].id = id;
133 rpc->prod_idx = next_prod_idx;
134 spin_unlock_irqrestore(&rpc->e_lock, flags);
135
136 /* Invoke DPC handler */
137 schedule_work(&rpc->dpc_handler);
138
139 return IRQ_HANDLED;
140}
141
142/**
143 * aer_alloc_rpc - allocate Root Port data structure
144 * @dev: pointer to the pcie_dev data structure
145 *
146 * Invoked when Root Port's AER service is loaded.
147 **/
148static struct aer_rpc* aer_alloc_rpc(struct pcie_device *dev)
149{
150 struct aer_rpc *rpc;
151
152 if (!(rpc = (struct aer_rpc *)kmalloc(sizeof(struct aer_rpc),
153 GFP_KERNEL)))
154 return NULL;
155
156 memset(rpc, 0, sizeof(struct aer_rpc));
157 /*
158 * Initialize Root lock access, e_lock, to Root Error Status Reg,
159 * Root Error ID Reg, and Root error producer/consumer index.
160 */
161 rpc->e_lock = SPIN_LOCK_UNLOCKED;
162
163 rpc->rpd = dev;
164 INIT_WORK(&rpc->dpc_handler, aer_isr, (void *)dev);
165 rpc->prod_idx = rpc->cons_idx = 0;
166 mutex_init(&rpc->rpc_mutex);
167 init_waitqueue_head(&rpc->wait_release);
168
169 /* Use PCIE bus function to store rpc into PCIE device */
170 set_service_data(dev, rpc);
171
172 return rpc;
173}
174
175/**
176 * aer_remove - clean up resources
177 * @dev: pointer to the pcie_dev data structure
178 *
179 * Invoked when PCI Express bus unloads or AER probe fails.
180 **/
181static void aer_remove(struct pcie_device *dev)
182{
183 struct aer_rpc *rpc = get_service_data(dev);
184
185 if (rpc) {
186 /* If register interrupt service, it must be free. */
187 if (rpc->isr)
188 free_irq(dev->irq, dev);
189
190 wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx);
191
192 aer_delete_rootport(rpc);
193 set_service_data(dev, NULL);
194 }
195}
196
197/**
198 * aer_probe - initialize resources
199 * @dev: pointer to the pcie_dev data structure
200 * @id: pointer to the service id data structure
201 *
202 * Invoked when PCI Express bus loads AER service driver.
203 **/
204static int __devinit aer_probe (struct pcie_device *dev,
205 const struct pcie_port_service_id *id )
206{
207 int status;
208 struct aer_rpc *rpc;
209 struct device *device = &dev->device;
210
211 /* Init */
212 if ((status = aer_init(dev)))
213 return status;
214
215 /* Alloc rpc data structure */
216 if (!(rpc = aer_alloc_rpc(dev))) {
217 printk(KERN_DEBUG "%s: Alloc rpc fails on PCIE device[%s]\n",
218 __FUNCTION__, device->bus_id);
219 aer_remove(dev);
220 return -ENOMEM;
221 }
222
223 /* Request IRQ ISR */
224 if ((status = request_irq(dev->irq, aer_irq, SA_SHIRQ, "aerdrv",
225 dev))) {
226 printk(KERN_DEBUG "%s: Request ISR fails on PCIE device[%s]\n",
227 __FUNCTION__, device->bus_id);
228 aer_remove(dev);
229 return status;
230 }
231
232 rpc->isr = 1;
233
234 aer_enable_rootport(rpc);
235
236 return status;
237}
238
239/**
240 * aer_root_reset - reset link on Root Port
241 * @dev: pointer to Root Port's pci_dev data structure
242 *
243 * Invoked by Port Bus driver when performing link reset at Root Port.
244 **/
245static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
246{
247 u16 p2p_ctrl;
248 u32 status;
249 int pos;
250
251 pos = pci_find_aer_capability(dev);
252
253 /* Disable Root's interrupt in response to error messages */
254 pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, 0);
255
256 /* Assert Secondary Bus Reset */
257 pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &p2p_ctrl);
258 p2p_ctrl |= PCI_CB_BRIDGE_CTL_CB_RESET;
259 pci_write_config_word(dev, PCI_BRIDGE_CONTROL, p2p_ctrl);
260
261 /* De-assert Secondary Bus Reset */
262 p2p_ctrl &= ~PCI_CB_BRIDGE_CTL_CB_RESET;
263 pci_write_config_word(dev, PCI_BRIDGE_CONTROL, p2p_ctrl);
264
265 /*
266 * System software must wait for at least 100ms from the end
267 * of a reset of one or more device before it is permitted
268 * to issue Configuration Requests to those devices.
269 */
270 msleep(200);
271 printk(KERN_DEBUG "Complete link reset at Root[%s]\n", dev->dev.bus_id);
272
273 /* Enable Root Port's interrupt in response to error messages */
274 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &status);
275 pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, status);
276 pci_write_config_dword(dev,
277 pos + PCI_ERR_ROOT_COMMAND,
278 ROOT_PORT_INTR_ON_MESG_MASK);
279
280 return PCI_ERS_RESULT_RECOVERED;
281}
282
283/**
284 * aer_error_detected - update severity status
285 * @dev: pointer to Root Port's pci_dev data structure
286 * @error: error severity being notified by port bus
287 *
288 * Invoked by Port Bus driver during error recovery.
289 **/
290static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
291 enum pci_channel_state error)
292{
293 /* Root Port has no impact. Always recovers. */
294 return PCI_ERS_RESULT_CAN_RECOVER;
295}
296
297/**
298 * aer_error_resume - clean up corresponding error status bits
299 * @dev: pointer to Root Port's pci_dev data structure
300 *
301 * Invoked by Port Bus driver during nonfatal recovery.
302 **/
303static void aer_error_resume(struct pci_dev *dev)
304{
305 int pos;
306 u32 status, mask;
307 u16 reg16;
308
309 /* Clean up Root device status */
310 pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
311 pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &reg16);
312 pci_write_config_word(dev, pos + PCI_EXP_DEVSTA, reg16);
313
314 /* Clean AER Root Error Status */
315 pos = pci_find_aer_capability(dev);
316 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
317 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
318 if (dev->error_state == pci_channel_io_normal)
319 status &= ~mask; /* Clear corresponding nonfatal bits */
320 else
321 status &= mask; /* Clear corresponding fatal bits */
322 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
323}
324
325/**
326 * aer_service_init - register AER root service driver
327 *
328 * Invoked when AER root service driver is loaded.
329 **/
330static int __init aer_service_init(void)
331{
332 return pcie_port_service_register(&aerdrv);
333}
334
335/**
336 * aer_service_exit - unregister AER root service driver
337 *
338 * Invoked when AER root service driver is unloaded.
339 **/
340static void __exit aer_service_exit(void)
341{
342 pcie_port_service_unregister(&aerdrv);
343}
344
345module_init(aer_service_init);
346module_exit(aer_service_exit);
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
new file mode 100644
index 000000000000..daf0cad88fc8
--- /dev/null
+++ b/drivers/pci/pcie/aer/aerdrv.h
@@ -0,0 +1,125 @@
1/*
2 * Copyright (C) 2006 Intel Corp.
3 * Tom Long Nguyen (tom.l.nguyen@intel.com)
4 * Zhang Yanmin (yanmin.zhang@intel.com)
5 *
6 */
7
8#ifndef _AERDRV_H_
9#define _AERDRV_H_
10
11#include <linux/pcieport_if.h>
12#include <linux/aer.h>
13
14#define AER_NONFATAL 0
15#define AER_FATAL 1
16#define AER_CORRECTABLE 2
17#define AER_UNCORRECTABLE 4
18#define AER_ERROR_MASK 0x001fffff
19#define AER_ERROR(d) (d & AER_ERROR_MASK)
20
21#define OSC_METHOD_RUN_SUCCESS 0
22#define OSC_METHOD_NOT_SUPPORTED 1
23#define OSC_METHOD_RUN_FAILURE 2
24
25/* Root Error Status Register Bits */
26#define ROOT_ERR_STATUS_MASKS 0x0f
27
28#define SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE| \
29 PCI_EXP_RTCTL_SENFEE| \
30 PCI_EXP_RTCTL_SEFEE)
31#define ROOT_PORT_INTR_ON_MESG_MASK (PCI_ERR_ROOT_CMD_COR_EN| \
32 PCI_ERR_ROOT_CMD_NONFATAL_EN| \
33 PCI_ERR_ROOT_CMD_FATAL_EN)
34#define ERR_COR_ID(d) (d & 0xffff)
35#define ERR_UNCOR_ID(d) (d >> 16)
36
37#define AER_SUCCESS 0
38#define AER_UNSUCCESS 1
39#define AER_ERROR_SOURCES_MAX 100
40
41#define AER_LOG_TLP_MASKS (PCI_ERR_UNC_POISON_TLP| \
42 PCI_ERR_UNC_ECRC| \
43 PCI_ERR_UNC_UNSUP| \
44 PCI_ERR_UNC_COMP_ABORT| \
45 PCI_ERR_UNC_UNX_COMP| \
46 PCI_ERR_UNC_MALF_TLP)
47
48/* AER Error Info Flags */
49#define AER_TLP_HEADER_VALID_FLAG 0x00000001
50#define AER_MULTI_ERROR_VALID_FLAG 0x00000002
51
52#define ERR_CORRECTABLE_ERROR_MASK 0x000031c1
53#define ERR_UNCORRECTABLE_ERROR_MASK 0x001ff010
54
55struct header_log_regs {
56 unsigned int dw0;
57 unsigned int dw1;
58 unsigned int dw2;
59 unsigned int dw3;
60};
61
62struct aer_err_info {
63 int severity; /* 0:NONFATAL | 1:FATAL | 2:COR */
64 int flags;
65 unsigned int status; /* COR/UNCOR Error Status */
66 struct header_log_regs tlp; /* TLP Header */
67};
68
69struct aer_err_source {
70 unsigned int status;
71 unsigned int id;
72};
73
74struct aer_rpc {
75 struct pcie_device *rpd; /* Root Port device */
76 struct work_struct dpc_handler;
77 struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX];
78 unsigned short prod_idx; /* Error Producer Index */
79 unsigned short cons_idx; /* Error Consumer Index */
80 int isr;
81 spinlock_t e_lock; /*
82 * Lock access to Error Status/ID Regs
83 * and error producer/consumer index
84 */
85 struct mutex rpc_mutex; /*
86 * only one thread could do
87 * recovery on the same
88 * root port hierachy
89 */
90 wait_queue_head_t wait_release;
91};
92
93struct aer_broadcast_data {
94 enum pci_channel_state state;
95 enum pci_ers_result result;
96};
97
98static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
99 enum pci_ers_result new)
100{
101 switch (orig) {
102 case PCI_ERS_RESULT_CAN_RECOVER:
103 case PCI_ERS_RESULT_RECOVERED:
104 orig = new;
105 break;
106 case PCI_ERS_RESULT_DISCONNECT:
107 if (new == PCI_ERS_RESULT_NEED_RESET)
108 orig = new;
109 break;
110 default:
111 break;
112 }
113
114 return orig;
115}
116
117extern struct bus_type pcie_port_bus_type;
118extern void aer_enable_rootport(struct aer_rpc *rpc);
119extern void aer_delete_rootport(struct aer_rpc *rpc);
120extern int aer_init(struct pcie_device *dev);
121extern void aer_isr(void *context);
122extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
123extern int aer_osc_setup(struct pci_dev *dev);
124
125#endif //_AERDRV_H_
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
new file mode 100644
index 000000000000..fa68e89ebec9
--- /dev/null
+++ b/drivers/pci/pcie/aer/aerdrv_acpi.c
@@ -0,0 +1,68 @@
1/*
2 * Access ACPI _OSC method
3 *
4 * Copyright (C) 2006 Intel Corp.
5 * Tom Long Nguyen (tom.l.nguyen@intel.com)
6 * Zhang Yanmin (yanmin.zhang@intel.com)
7 *
8 */
9
10#include <linux/module.h>
11#include <linux/pci.h>
12#include <linux/kernel.h>
13#include <linux/errno.h>
14#include <linux/pm.h>
15#include <linux/suspend.h>
16#include <linux/acpi.h>
17#include <linux/pci-acpi.h>
18#include <linux/delay.h>
19#include "aerdrv.h"
20
21/**
22 * aer_osc_setup - run ACPI _OSC method
23 *
24 * Return:
25 * Zero if success. Nonzero for otherwise.
26 *
27 * Invoked when PCIE bus loads AER service driver. To avoid conflict with
28 * BIOS AER support requires BIOS to yield AER control to OS native driver.
29 **/
30int aer_osc_setup(struct pci_dev *dev)
31{
32 int retval = OSC_METHOD_RUN_SUCCESS;
33 acpi_status status;
34 acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
35 struct pci_dev *pdev = dev;
36 struct pci_bus *parent;
37
38 while (!handle) {
39 if (!pdev || !pdev->bus->parent)
40 break;
41 parent = pdev->bus->parent;
42 if (!parent->self)
43 /* Parent must be a host bridge */
44 handle = acpi_get_pci_rootbridge_handle(
45 pci_domain_nr(parent),
46 parent->number);
47 else
48 handle = DEVICE_ACPI_HANDLE(
49 &(parent->self->dev));
50 pdev = parent->self;
51 }
52
53 if (!handle)
54 return OSC_METHOD_NOT_SUPPORTED;
55
56 pci_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
57 status = pci_osc_control_set(handle, OSC_PCI_EXPRESS_AER_CONTROL |
58 OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
59 if (ACPI_FAILURE(status)) {
60 if (status == AE_SUPPORT)
61 retval = OSC_METHOD_NOT_SUPPORTED;
62 else
63 retval = OSC_METHOD_RUN_FAILURE;
64 }
65
66 return retval;
67}
68
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
new file mode 100644
index 000000000000..1c7e660d6535
--- /dev/null
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -0,0 +1,758 @@
1/*
2 * drivers/pci/pcie/aer/aerdrv_core.c
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * This file implements the core part of PCI-Express AER. When an pci-express
9 * error is delivered, an error message will be collected and printed to
10 * console, then, an error recovery procedure will be executed by following
11 * the pci error recovery rules.
12 *
13 * Copyright (C) 2006 Intel Corp.
14 * Tom Long Nguyen (tom.l.nguyen@intel.com)
15 * Zhang Yanmin (yanmin.zhang@intel.com)
16 *
17 */
18
19#include <linux/module.h>
20#include <linux/pci.h>
21#include <linux/kernel.h>
22#include <linux/errno.h>
23#include <linux/pm.h>
24#include <linux/suspend.h>
25#include <linux/acpi.h>
26#include <linux/pci-acpi.h>
27#include <linux/delay.h>
28#include "aerdrv.h"
29
30static int forceload;
31module_param(forceload, bool, 0);
32
33#define PCI_CFG_SPACE_SIZE (0x100)
34int pci_find_aer_capability(struct pci_dev *dev)
35{
36 int pos;
37 u32 reg32 = 0;
38
39 /* Check if it's a pci-express device */
40 pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
41 if (!pos)
42 return 0;
43
44 /* Check if it supports pci-express AER */
45 pos = PCI_CFG_SPACE_SIZE;
46 while (pos) {
47 if (pci_read_config_dword(dev, pos, &reg32))
48 return 0;
49
50 /* some broken boards return ~0 */
51 if (reg32 == 0xffffffff)
52 return 0;
53
54 if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR)
55 break;
56
57 pos = reg32 >> 20;
58 }
59
60 return pos;
61}
62
63int pci_enable_pcie_error_reporting(struct pci_dev *dev)
64{
65 u16 reg16 = 0;
66 int pos;
67
68 pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
69 if (!pos)
70 return -EIO;
71
72 pci_read_config_word(dev, pos+PCI_EXP_DEVCTL, &reg16);
73 reg16 = reg16 |
74 PCI_EXP_DEVCTL_CERE |
75 PCI_EXP_DEVCTL_NFERE |
76 PCI_EXP_DEVCTL_FERE |
77 PCI_EXP_DEVCTL_URRE;
78 pci_write_config_word(dev, pos+PCI_EXP_DEVCTL,
79 reg16);
80 return 0;
81}
82
83int pci_disable_pcie_error_reporting(struct pci_dev *dev)
84{
85 u16 reg16 = 0;
86 int pos;
87
88 pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
89 if (!pos)
90 return -EIO;
91
92 pci_read_config_word(dev, pos+PCI_EXP_DEVCTL, &reg16);
93 reg16 = reg16 & ~(PCI_EXP_DEVCTL_CERE |
94 PCI_EXP_DEVCTL_NFERE |
95 PCI_EXP_DEVCTL_FERE |
96 PCI_EXP_DEVCTL_URRE);
97 pci_write_config_word(dev, pos+PCI_EXP_DEVCTL,
98 reg16);
99 return 0;
100}
101
102int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
103{
104 int pos;
105 u32 status, mask;
106
107 pos = pci_find_aer_capability(dev);
108 if (!pos)
109 return -EIO;
110
111 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
112 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
113 if (dev->error_state == pci_channel_io_normal)
114 status &= ~mask; /* Clear corresponding nonfatal bits */
115 else
116 status &= mask; /* Clear corresponding fatal bits */
117 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
118
119 return 0;
120}
121
122static int find_device_iter(struct device *device, void *data)
123{
124 struct pci_dev *dev;
125 u16 id = *(unsigned long *)data;
126 u8 secondary, subordinate, d_bus = id >> 8;
127
128 if (device->bus == &pci_bus_type) {
129 dev = to_pci_dev(device);
130 if (id == ((dev->bus->number << 8) | dev->devfn)) {
131 /*
132 * Device ID match
133 */
134 *(unsigned long*)data = (unsigned long)device;
135 return 1;
136 }
137
138 /*
139 * If device is P2P, check if it is an upstream?
140 */
141 if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) {
142 pci_read_config_byte(dev, PCI_SECONDARY_BUS,
143 &secondary);
144 pci_read_config_byte(dev, PCI_SUBORDINATE_BUS,
145 &subordinate);
146 if (d_bus >= secondary && d_bus <= subordinate) {
147 *(unsigned long*)data = (unsigned long)device;
148 return 1;
149 }
150 }
151 }
152
153 return 0;
154}
155
156/**
157 * find_source_device - search through device hierarchy for source device
158 * @p_dev: pointer to Root Port pci_dev data structure
159 * @id: device ID of agent who sends an error message to this Root Port
160 *
161 * Invoked when error is detected at the Root Port.
162 **/
163static struct device* find_source_device(struct pci_dev *parent, u16 id)
164{
165 struct pci_dev *dev = parent;
166 struct device *device;
167 unsigned long device_addr;
168 int status;
169
170 /* Is Root Port an agent that sends error message? */
171 if (id == ((dev->bus->number << 8) | dev->devfn))
172 return &dev->dev;
173
174 do {
175 device_addr = id;
176 if ((status = device_for_each_child(&dev->dev,
177 &device_addr, find_device_iter))) {
178 device = (struct device*)device_addr;
179 dev = to_pci_dev(device);
180 if (id == ((dev->bus->number << 8) | dev->devfn))
181 return device;
182 }
183 }while (status);
184
185 return NULL;
186}
187
188static void report_error_detected(struct pci_dev *dev, void *data)
189{
190 pci_ers_result_t vote;
191 struct pci_error_handlers *err_handler;
192 struct aer_broadcast_data *result_data;
193 result_data = (struct aer_broadcast_data *) data;
194
195 dev->error_state = result_data->state;
196
197 if (!dev->driver ||
198 !dev->driver->err_handler ||
199 !dev->driver->err_handler->error_detected) {
200 if (result_data->state == pci_channel_io_frozen &&
201 !(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)) {
202 /*
203 * In case of fatal recovery, if one of down-
204 * stream device has no driver. We might be
205 * unable to recover because a later insmod
206 * of a driver for this device is unaware of
207 * its hw state.
208 */
209 printk(KERN_DEBUG "Device ID[%s] has %s\n",
210 dev->dev.bus_id, (dev->driver) ?
211 "no AER-aware driver" : "no driver");
212 }
213 return;
214 }
215
216 err_handler = dev->driver->err_handler;
217 vote = err_handler->error_detected(dev, result_data->state);
218 result_data->result = merge_result(result_data->result, vote);
219 return;
220}
221
222static void report_mmio_enabled(struct pci_dev *dev, void *data)
223{
224 pci_ers_result_t vote;
225 struct pci_error_handlers *err_handler;
226 struct aer_broadcast_data *result_data;
227 result_data = (struct aer_broadcast_data *) data;
228
229 if (!dev->driver ||
230 !dev->driver->err_handler ||
231 !dev->driver->err_handler->mmio_enabled)
232 return;
233
234 err_handler = dev->driver->err_handler;
235 vote = err_handler->mmio_enabled(dev);
236 result_data->result = merge_result(result_data->result, vote);
237 return;
238}
239
240static void report_slot_reset(struct pci_dev *dev, void *data)
241{
242 pci_ers_result_t vote;
243 struct pci_error_handlers *err_handler;
244 struct aer_broadcast_data *result_data;
245 result_data = (struct aer_broadcast_data *) data;
246
247 if (!dev->driver ||
248 !dev->driver->err_handler ||
249 !dev->driver->err_handler->slot_reset)
250 return;
251
252 err_handler = dev->driver->err_handler;
253 vote = err_handler->slot_reset(dev);
254 result_data->result = merge_result(result_data->result, vote);
255 return;
256}
257
258static void report_resume(struct pci_dev *dev, void *data)
259{
260 struct pci_error_handlers *err_handler;
261
262 dev->error_state = pci_channel_io_normal;
263
264 if (!dev->driver ||
265 !dev->driver->err_handler ||
266 !dev->driver->err_handler->slot_reset)
267 return;
268
269 err_handler = dev->driver->err_handler;
270 err_handler->resume(dev);
271 return;
272}
273
274/**
275 * broadcast_error_message - handle message broadcast to downstream drivers
276 * @device: pointer to from where in a hierarchy message is broadcasted down
277 * @api: callback to be broadcasted
278 * @state: error state
279 *
280 * Invoked during error recovery process. Once being invoked, the content
281 * of error severity will be broadcasted to all downstream drivers in a
282 * hierarchy in question.
283 **/
284static pci_ers_result_t broadcast_error_message(struct pci_dev *dev,
285 enum pci_channel_state state,
286 char *error_mesg,
287 void (*cb)(struct pci_dev *, void *))
288{
289 struct aer_broadcast_data result_data;
290
291 printk(KERN_DEBUG "Broadcast %s message\n", error_mesg);
292 result_data.state = state;
293 if (cb == report_error_detected)
294 result_data.result = PCI_ERS_RESULT_CAN_RECOVER;
295 else
296 result_data.result = PCI_ERS_RESULT_RECOVERED;
297
298 if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) {
299 /*
300 * If the error is reported by a bridge, we think this error
301 * is related to the downstream link of the bridge, so we
302 * do error recovery on all subordinates of the bridge instead
303 * of the bridge and clear the error status of the bridge.
304 */
305 if (cb == report_error_detected)
306 dev->error_state = state;
307 pci_walk_bus(dev->subordinate, cb, &result_data);
308 if (cb == report_resume) {
309 pci_cleanup_aer_uncorrect_error_status(dev);
310 dev->error_state = pci_channel_io_normal;
311 }
312 }
313 else {
314 /*
315 * If the error is reported by an end point, we think this
316 * error is related to the upstream link of the end point.
317 */
318 pci_walk_bus(dev->bus, cb, &result_data);
319 }
320
321 return result_data.result;
322}
323
324struct find_aer_service_data {
325 struct pcie_port_service_driver *aer_driver;
326 int is_downstream;
327};
328
329static int find_aer_service_iter(struct device *device, void *data)
330{
331 struct device_driver *driver;
332 struct pcie_port_service_driver *service_driver;
333 struct pcie_device *pcie_dev;
334 struct find_aer_service_data *result;
335
336 result = (struct find_aer_service_data *) data;
337
338 if (device->bus == &pcie_port_bus_type) {
339 pcie_dev = to_pcie_device(device);
340 if (pcie_dev->id.port_type == PCIE_SW_DOWNSTREAM_PORT)
341 result->is_downstream = 1;
342
343 driver = device->driver;
344 if (driver) {
345 service_driver = to_service_driver(driver);
346 if (service_driver->id_table->service_type ==
347 PCIE_PORT_SERVICE_AER) {
348 result->aer_driver = service_driver;
349 return 1;
350 }
351 }
352 }
353
354 return 0;
355}
356
357static void find_aer_service(struct pci_dev *dev,
358 struct find_aer_service_data *data)
359{
360 int retval;
361 retval = device_for_each_child(&dev->dev, data, find_aer_service_iter);
362}
363
364static pci_ers_result_t reset_link(struct pcie_device *aerdev,
365 struct pci_dev *dev)
366{
367 struct pci_dev *udev;
368 pci_ers_result_t status;
369 struct find_aer_service_data data;
370
371 if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)
372 udev = dev;
373 else
374 udev= dev->bus->self;
375
376 data.is_downstream = 0;
377 data.aer_driver = NULL;
378 find_aer_service(udev, &data);
379
380 /*
381 * Use the aer driver of the error agent firstly.
382 * If it hasn't the aer driver, use the root port's
383 */
384 if (!data.aer_driver || !data.aer_driver->reset_link) {
385 if (data.is_downstream &&
386 aerdev->device.driver &&
387 to_service_driver(aerdev->device.driver)->reset_link) {
388 data.aer_driver =
389 to_service_driver(aerdev->device.driver);
390 } else {
391 printk(KERN_DEBUG "No link-reset support to Device ID"
392 "[%s]\n",
393 dev->dev.bus_id);
394 return PCI_ERS_RESULT_DISCONNECT;
395 }
396 }
397
398 status = data.aer_driver->reset_link(udev);
399 if (status != PCI_ERS_RESULT_RECOVERED) {
400 printk(KERN_DEBUG "Link reset at upstream Device ID"
401 "[%s] failed\n",
402 udev->dev.bus_id);
403 return PCI_ERS_RESULT_DISCONNECT;
404 }
405
406 return status;
407}
408
409/**
410 * do_recovery - handle nonfatal/fatal error recovery process
411 * @aerdev: pointer to a pcie_device data structure of root port
412 * @dev: pointer to a pci_dev data structure of agent detecting an error
413 * @severity: error severity type
414 *
415 * Invoked when an error is nonfatal/fatal. Once being invoked, broadcast
416 * error detected message to all downstream drivers within a hierarchy in
417 * question and return the returned code.
418 **/
419static pci_ers_result_t do_recovery(struct pcie_device *aerdev,
420 struct pci_dev *dev,
421 int severity)
422{
423 pci_ers_result_t status, result = PCI_ERS_RESULT_RECOVERED;
424 enum pci_channel_state state;
425
426 if (severity == AER_FATAL)
427 state = pci_channel_io_frozen;
428 else
429 state = pci_channel_io_normal;
430
431 status = broadcast_error_message(dev,
432 state,
433 "error_detected",
434 report_error_detected);
435
436 if (severity == AER_FATAL) {
437 result = reset_link(aerdev, dev);
438 if (result != PCI_ERS_RESULT_RECOVERED) {
439 /* TODO: Should panic here? */
440 return result;
441 }
442 }
443
444 if (status == PCI_ERS_RESULT_CAN_RECOVER)
445 status = broadcast_error_message(dev,
446 state,
447 "mmio_enabled",
448 report_mmio_enabled);
449
450 if (status == PCI_ERS_RESULT_NEED_RESET) {
451 /*
452 * TODO: Should call platform-specific
453 * functions to reset slot before calling
454 * drivers' slot_reset callbacks?
455 */
456 status = broadcast_error_message(dev,
457 state,
458 "slot_reset",
459 report_slot_reset);
460 }
461
462 if (status == PCI_ERS_RESULT_RECOVERED)
463 broadcast_error_message(dev,
464 state,
465 "resume",
466 report_resume);
467
468 return status;
469}
470
471/**
472 * handle_error_source - handle logging error into an event log
473 * @aerdev: pointer to pcie_device data structure of the root port
474 * @dev: pointer to pci_dev data structure of error source device
475 * @info: comprehensive error information
476 *
477 * Invoked when an error being detected by Root Port.
478 **/
479static void handle_error_source(struct pcie_device * aerdev,
480 struct pci_dev *dev,
481 struct aer_err_info info)
482{
483 pci_ers_result_t status = 0;
484 int pos;
485
486 if (info.severity == AER_CORRECTABLE) {
487 /*
488 * Correctable error does not need software intevention.
489 * No need to go through error recovery process.
490 */
491 pos = pci_find_aer_capability(dev);
492 if (pos)
493 pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS,
494 info.status);
495 } else {
496 status = do_recovery(aerdev, dev, info.severity);
497 if (status == PCI_ERS_RESULT_RECOVERED) {
498 printk(KERN_DEBUG "AER driver successfully recovered\n");
499 } else {
500 /* TODO: Should kernel panic here? */
501 printk(KERN_DEBUG "AER driver didn't recover\n");
502 }
503 }
504}
505
506/**
507 * aer_enable_rootport - enable Root Port's interrupts when receiving messages
508 * @rpc: pointer to a Root Port data structure
509 *
510 * Invoked when PCIE bus loads AER service driver.
511 **/
512void aer_enable_rootport(struct aer_rpc *rpc)
513{
514 struct pci_dev *pdev = rpc->rpd->port;
515 int pos, aer_pos;
516 u16 reg16;
517 u32 reg32;
518
519 pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
520 /* Clear PCIE Capability's Device Status */
521 pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, &reg16);
522 pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16);
523
524 /* Disable system error generation in response to error messages */
525 pci_read_config_word(pdev, pos + PCI_EXP_RTCTL, &reg16);
526 reg16 &= ~(SYSTEM_ERROR_INTR_ON_MESG_MASK);
527 pci_write_config_word(pdev, pos + PCI_EXP_RTCTL, reg16);
528
529 aer_pos = pci_find_aer_capability(pdev);
530 /* Clear error status */
531 pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32);
532 pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32);
533 pci_read_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, &reg32);
534 pci_write_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, reg32);
535 pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, &reg32);
536 pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32);
537
538 /* Enable Root Port device reporting error itself */
539 pci_read_config_word(pdev, pos+PCI_EXP_DEVCTL, &reg16);
540 reg16 = reg16 |
541 PCI_EXP_DEVCTL_CERE |
542 PCI_EXP_DEVCTL_NFERE |
543 PCI_EXP_DEVCTL_FERE |
544 PCI_EXP_DEVCTL_URRE;
545 pci_write_config_word(pdev, pos+PCI_EXP_DEVCTL,
546 reg16);
547
548 /* Enable Root Port's interrupt in response to error messages */
549 pci_write_config_dword(pdev,
550 aer_pos + PCI_ERR_ROOT_COMMAND,
551 ROOT_PORT_INTR_ON_MESG_MASK);
552}
553
554/**
555 * disable_root_aer - disable Root Port's interrupts when receiving messages
556 * @rpc: pointer to a Root Port data structure
557 *
558 * Invoked when PCIE bus unloads AER service driver.
559 **/
560static void disable_root_aer(struct aer_rpc *rpc)
561{
562 struct pci_dev *pdev = rpc->rpd->port;
563 u32 reg32;
564 int pos;
565
566 pos = pci_find_aer_capability(pdev);
567 /* Disable Root's interrupt in response to error messages */
568 pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, 0);
569
570 /* Clear Root's error status reg */
571 pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, &reg32);
572 pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32);
573}
574
575/**
576 * get_e_source - retrieve an error source
577 * @rpc: pointer to the root port which holds an error
578 *
579 * Invoked by DPC handler to consume an error.
580 **/
581static struct aer_err_source* get_e_source(struct aer_rpc *rpc)
582{
583 struct aer_err_source *e_source;
584 unsigned long flags;
585
586 /* Lock access to Root error producer/consumer index */
587 spin_lock_irqsave(&rpc->e_lock, flags);
588 if (rpc->prod_idx == rpc->cons_idx) {
589 spin_unlock_irqrestore(&rpc->e_lock, flags);
590 return NULL;
591 }
592 e_source = &rpc->e_sources[rpc->cons_idx];
593 rpc->cons_idx++;
594 if (rpc->cons_idx == AER_ERROR_SOURCES_MAX)
595 rpc->cons_idx = 0;
596 spin_unlock_irqrestore(&rpc->e_lock, flags);
597
598 return e_source;
599}
600
601static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
602{
603 int pos;
604
605 pos = pci_find_aer_capability(dev);
606
607 /* The device might not support AER */
608 if (!pos)
609 return AER_SUCCESS;
610
611 if (info->severity == AER_CORRECTABLE) {
612 pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS,
613 &info->status);
614 if (!(info->status & ERR_CORRECTABLE_ERROR_MASK))
615 return AER_UNSUCCESS;
616 } else if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE ||
617 info->severity == AER_NONFATAL) {
618
619 /* Link is still healthy for IO reads */
620 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
621 &info->status);
622 if (!(info->status & ERR_UNCORRECTABLE_ERROR_MASK))
623 return AER_UNSUCCESS;
624
625 if (info->status & AER_LOG_TLP_MASKS) {
626 info->flags |= AER_TLP_HEADER_VALID_FLAG;
627 pci_read_config_dword(dev,
628 pos + PCI_ERR_HEADER_LOG, &info->tlp.dw0);
629 pci_read_config_dword(dev,
630 pos + PCI_ERR_HEADER_LOG + 4, &info->tlp.dw1);
631 pci_read_config_dword(dev,
632 pos + PCI_ERR_HEADER_LOG + 8, &info->tlp.dw2);
633 pci_read_config_dword(dev,
634 pos + PCI_ERR_HEADER_LOG + 12, &info->tlp.dw3);
635 }
636 }
637
638 return AER_SUCCESS;
639}
640
641/**
642 * aer_isr_one_error - consume an error detected by root port
643 * @p_device: pointer to error root port service device
644 * @e_src: pointer to an error source
645 **/
646static void aer_isr_one_error(struct pcie_device *p_device,
647 struct aer_err_source *e_src)
648{
649 struct device *s_device;
650 struct aer_err_info e_info = {0, 0, 0,};
651 int i;
652 u16 id;
653
654 /*
655 * There is a possibility that both correctable error and
656 * uncorrectable error being logged. Report correctable error first.
657 */
658 for (i = 1; i & ROOT_ERR_STATUS_MASKS ; i <<= 2) {
659 if (i > 4)
660 break;
661 if (!(e_src->status & i))
662 continue;
663
664 /* Init comprehensive error information */
665 if (i & PCI_ERR_ROOT_COR_RCV) {
666 id = ERR_COR_ID(e_src->id);
667 e_info.severity = AER_CORRECTABLE;
668 } else {
669 id = ERR_UNCOR_ID(e_src->id);
670 e_info.severity = ((e_src->status >> 6) & 1);
671 }
672 if (e_src->status &
673 (PCI_ERR_ROOT_MULTI_COR_RCV |
674 PCI_ERR_ROOT_MULTI_UNCOR_RCV))
675 e_info.flags |= AER_MULTI_ERROR_VALID_FLAG;
676 if (!(s_device = find_source_device(p_device->port, id))) {
677 printk(KERN_DEBUG "%s->can't find device of ID%04x\n",
678 __FUNCTION__, id);
679 continue;
680 }
681 if (get_device_error_info(to_pci_dev(s_device), &e_info) ==
682 AER_SUCCESS) {
683 aer_print_error(to_pci_dev(s_device), &e_info);
684 handle_error_source(p_device,
685 to_pci_dev(s_device),
686 e_info);
687 }
688 }
689}
690
691/**
692 * aer_isr - consume errors detected by root port
693 * @context: pointer to a private data of pcie device
694 *
695 * Invoked, as DPC, when root port records new detected error
696 **/
697void aer_isr(void *context)
698{
699 struct pcie_device *p_device = (struct pcie_device *) context;
700 struct aer_rpc *rpc = get_service_data(p_device);
701 struct aer_err_source *e_src;
702
703 mutex_lock(&rpc->rpc_mutex);
704 e_src = get_e_source(rpc);
705 while (e_src) {
706 aer_isr_one_error(p_device, e_src);
707 e_src = get_e_source(rpc);
708 }
709 mutex_unlock(&rpc->rpc_mutex);
710
711 wake_up(&rpc->wait_release);
712}
713
714/**
715 * aer_delete_rootport - disable root port aer and delete service data
716 * @rpc: pointer to a root port device being deleted
717 *
718 * Invoked when AER service unloaded on a specific Root Port
719 **/
720void aer_delete_rootport(struct aer_rpc *rpc)
721{
722 /* Disable root port AER itself */
723 disable_root_aer(rpc);
724
725 kfree(rpc);
726}
727
728/**
729 * aer_init - provide AER initialization
730 * @dev: pointer to AER pcie device
731 *
732 * Invoked when AER service driver is loaded.
733 **/
734int aer_init(struct pcie_device *dev)
735{
736 int status;
737
738 /* Run _OSC Method */
739 status = aer_osc_setup(dev->port);
740
741 if(status != OSC_METHOD_RUN_SUCCESS) {
742 printk(KERN_DEBUG "%s: AER service init fails - %s\n",
743 __FUNCTION__,
744 (status == OSC_METHOD_NOT_SUPPORTED) ?
745 "No ACPI _OSC support" : "Run ACPI _OSC fails");
746
747 if (!forceload)
748 return status;
749 }
750
751 return AER_SUCCESS;
752}
753
754EXPORT_SYMBOL_GPL(pci_find_aer_capability);
755EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
756EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
757EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
758
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c
new file mode 100644
index 000000000000..3933d4f30e8c
--- /dev/null
+++ b/drivers/pci/pcie/aer/aerdrv_errprint.c
@@ -0,0 +1,248 @@
1/*
2 * drivers/pci/pcie/aer/aerdrv_errprint.c
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Format error messages and print them to console.
9 *
10 * Copyright (C) 2006 Intel Corp.
11 * Tom Long Nguyen (tom.l.nguyen@intel.com)
12 * Zhang Yanmin (yanmin.zhang@intel.com)
13 *
14 */
15
16#include <linux/module.h>
17#include <linux/pci.h>
18#include <linux/kernel.h>
19#include <linux/errno.h>
20#include <linux/pm.h>
21#include <linux/suspend.h>
22
23#include "aerdrv.h"
24
25#define AER_AGENT_RECEIVER 0
26#define AER_AGENT_REQUESTER 1
27#define AER_AGENT_COMPLETER 2
28#define AER_AGENT_TRANSMITTER 3
29
30#define AER_AGENT_REQUESTER_MASK (PCI_ERR_UNC_COMP_TIME| \
31 PCI_ERR_UNC_UNSUP)
32
33#define AER_AGENT_COMPLETER_MASK PCI_ERR_UNC_COMP_ABORT
34
35#define AER_AGENT_TRANSMITTER_MASK(t, e) (e & (PCI_ERR_COR_REP_ROLL| \
36 ((t == AER_CORRECTABLE) ? PCI_ERR_COR_REP_TIMER: 0)))
37
38#define AER_GET_AGENT(t, e) \
39 ((e & AER_AGENT_COMPLETER_MASK) ? AER_AGENT_COMPLETER : \
40 (e & AER_AGENT_REQUESTER_MASK) ? AER_AGENT_REQUESTER : \
41 (AER_AGENT_TRANSMITTER_MASK(t, e)) ? AER_AGENT_TRANSMITTER : \
42 AER_AGENT_RECEIVER)
43
44#define AER_PHYSICAL_LAYER_ERROR_MASK PCI_ERR_COR_RCVR
45#define AER_DATA_LINK_LAYER_ERROR_MASK(t, e) \
46 (PCI_ERR_UNC_DLP| \
47 PCI_ERR_COR_BAD_TLP| \
48 PCI_ERR_COR_BAD_DLLP| \
49 PCI_ERR_COR_REP_ROLL| \
50 ((t == AER_CORRECTABLE) ? \
51 PCI_ERR_COR_REP_TIMER: 0))
52
53#define AER_PHYSICAL_LAYER_ERROR 0
54#define AER_DATA_LINK_LAYER_ERROR 1
55#define AER_TRANSACTION_LAYER_ERROR 2
56
57#define AER_GET_LAYER_ERROR(t, e) \
58 ((e & AER_PHYSICAL_LAYER_ERROR_MASK) ? \
59 AER_PHYSICAL_LAYER_ERROR : \
60 (e & AER_DATA_LINK_LAYER_ERROR_MASK(t, e)) ? \
61 AER_DATA_LINK_LAYER_ERROR : \
62 AER_TRANSACTION_LAYER_ERROR)
63
64/*
65 * AER error strings
66 */
67static char* aer_error_severity_string[] = {
68 "Uncorrected (Non-Fatal)",
69 "Uncorrected (Fatal)",
70 "Corrected"
71};
72
73static char* aer_error_layer[] = {
74 "Physical Layer",
75 "Data Link Layer",
76 "Transaction Layer"
77};
78static char* aer_correctable_error_string[] = {
79 "Receiver Error ", /* Bit Position 0 */
80 NULL,
81 NULL,
82 NULL,
83 NULL,
84 NULL,
85 "Bad TLP ", /* Bit Position 6 */
86 "Bad DLLP ", /* Bit Position 7 */
87 "RELAY_NUM Rollover ", /* Bit Position 8 */
88 NULL,
89 NULL,
90 NULL,
91 "Replay Timer Timeout ", /* Bit Position 12 */
92 "Advisory Non-Fatal ", /* Bit Position 13 */
93 NULL,
94 NULL,
95 NULL,
96 NULL,
97 NULL,
98 NULL,
99 NULL,
100 NULL,
101 NULL,
102 NULL,
103 NULL,
104 NULL,
105 NULL,
106 NULL,
107 NULL,
108 NULL,
109 NULL,
110 NULL,
111};
112
113static char* aer_uncorrectable_error_string[] = {
114 NULL,
115 NULL,
116 NULL,
117 NULL,
118 "Data Link Protocol ", /* Bit Position 4 */
119 NULL,
120 NULL,
121 NULL,
122 NULL,
123 NULL,
124 NULL,
125 NULL,
126 "Poisoned TLP ", /* Bit Position 12 */
127 "Flow Control Protocol ", /* Bit Position 13 */
128 "Completion Timeout ", /* Bit Position 14 */
129 "Completer Abort ", /* Bit Position 15 */
130 "Unexpected Completion ", /* Bit Position 16 */
131 "Receiver Overflow ", /* Bit Position 17 */
132 "Malformed TLP ", /* Bit Position 18 */
133 "ECRC ", /* Bit Position 19 */
134 "Unsupported Request ", /* Bit Position 20 */
135 NULL,
136 NULL,
137 NULL,
138 NULL,
139 NULL,
140 NULL,
141 NULL,
142 NULL,
143 NULL,
144 NULL,
145 NULL,
146};
147
148static char* aer_agent_string[] = {
149 "Receiver ID",
150 "Requester ID",
151 "Completer ID",
152 "Transmitter ID"
153};
154
155static char * aer_get_error_source_name(int severity,
156 unsigned int status,
157 char errmsg_buff[])
158{
159 int i;
160 char * errmsg = NULL;
161
162 for (i = 0; i < 32; i++) {
163 if (!(status & (1 << i)))
164 continue;
165
166 if (severity == AER_CORRECTABLE)
167 errmsg = aer_correctable_error_string[i];
168 else
169 errmsg = aer_uncorrectable_error_string[i];
170
171 if (!errmsg) {
172 sprintf(errmsg_buff, "Unknown Error Bit %2d ", i);
173 errmsg = errmsg_buff;
174 }
175
176 break;
177 }
178
179 return errmsg;
180}
181
182static DEFINE_SPINLOCK(logbuf_lock);
183static char errmsg_buff[100];
184void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
185{
186 char * errmsg;
187 int err_layer, agent;
188 char * loglevel;
189
190 if (info->severity == AER_CORRECTABLE)
191 loglevel = KERN_WARNING;
192 else
193 loglevel = KERN_ERR;
194
195 printk("%s+------ PCI-Express Device Error ------+\n", loglevel);
196 printk("%sError Severity\t\t: %s\n", loglevel,
197 aer_error_severity_string[info->severity]);
198
199 if ( info->status == 0) {
200 printk("%sPCIE Bus Error type\t: (Unaccessible)\n", loglevel);
201 printk("%sUnaccessible Received\t: %s\n", loglevel,
202 info->flags & AER_MULTI_ERROR_VALID_FLAG ?
203 "Multiple" : "First");
204 printk("%sUnregistered Agent ID\t: %04x\n", loglevel,
205 (dev->bus->number << 8) | dev->devfn);
206 } else {
207 err_layer = AER_GET_LAYER_ERROR(info->severity, info->status);
208 printk("%sPCIE Bus Error type\t: %s\n", loglevel,
209 aer_error_layer[err_layer]);
210
211 spin_lock(&logbuf_lock);
212 errmsg = aer_get_error_source_name(info->severity,
213 info->status,
214 errmsg_buff);
215 printk("%s%s\t: %s\n", loglevel, errmsg,
216 info->flags & AER_MULTI_ERROR_VALID_FLAG ?
217 "Multiple" : "First");
218 spin_unlock(&logbuf_lock);
219
220 agent = AER_GET_AGENT(info->severity, info->status);
221 printk("%s%s\t\t: %04x\n", loglevel,
222 aer_agent_string[agent],
223 (dev->bus->number << 8) | dev->devfn);
224
225 printk("%sVendorID=%04xh, DeviceID=%04xh,"
226 " Bus=%02xh, Device=%02xh, Function=%02xh\n",
227 loglevel,
228 dev->vendor,
229 dev->device,
230 dev->bus->number,
231 PCI_SLOT(dev->devfn),
232 PCI_FUNC(dev->devfn));
233
234 if (info->flags & AER_TLP_HEADER_VALID_FLAG) {
235 unsigned char *tlp = (unsigned char *) &info->tlp;
236 printk("%sTLB Header:\n", loglevel);
237 printk("%s%02x%02x%02x%02x %02x%02x%02x%02x"
238 " %02x%02x%02x%02x %02x%02x%02x%02x\n",
239 loglevel,
240 *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
241 *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
242 *(tlp + 11), *(tlp + 10), *(tlp + 9),
243 *(tlp + 8), *(tlp + 15), *(tlp + 14),
244 *(tlp + 13), *(tlp + 12));
245 }
246 }
247}
248
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h
index 1d317d22ee89..67fcd176babd 100644
--- a/drivers/pci/pcie/portdrv.h
+++ b/drivers/pci/pcie/portdrv.h
@@ -39,7 +39,7 @@ extern int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state);
39extern int pcie_port_device_resume(struct pci_dev *dev); 39extern int pcie_port_device_resume(struct pci_dev *dev);
40#endif 40#endif
41extern void pcie_port_device_remove(struct pci_dev *dev); 41extern void pcie_port_device_remove(struct pci_dev *dev);
42extern void pcie_port_bus_register(void); 42extern int pcie_port_bus_register(void);
43extern void pcie_port_bus_unregister(void); 43extern void pcie_port_bus_unregister(void);
44 44
45#endif /* _PORTDRV_H_ */ 45#endif /* _PORTDRV_H_ */
diff --git a/drivers/pci/pcie/portdrv_bus.c b/drivers/pci/pcie/portdrv_bus.c
index 3e84b501e6a4..3f0976868eda 100644
--- a/drivers/pci/pcie/portdrv_bus.c
+++ b/drivers/pci/pcie/portdrv_bus.c
@@ -24,6 +24,7 @@ struct bus_type pcie_port_bus_type = {
24 .suspend = pcie_port_bus_suspend, 24 .suspend = pcie_port_bus_suspend,
25 .resume = pcie_port_bus_resume, 25 .resume = pcie_port_bus_resume,
26}; 26};
27EXPORT_SYMBOL_GPL(pcie_port_bus_type);
27 28
28static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) 29static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
29{ 30{
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 55c662267868..bd6615b4d40e 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -6,6 +6,7 @@
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>
9#include <linux/module.h> 10#include <linux/module.h>
10#include <linux/pci.h> 11#include <linux/pci.h>
11#include <linux/kernel.h> 12#include <linux/kernel.h>
@@ -339,8 +340,7 @@ static int suspend_iter(struct device *dev, void *data)
339 340
340int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state) 341int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state)
341{ 342{
342 device_for_each_child(&dev->dev, &state, suspend_iter); 343 return device_for_each_child(&dev->dev, &state, suspend_iter);
343 return 0;
344} 344}
345 345
346static int resume_iter(struct device *dev, void *data) 346static int resume_iter(struct device *dev, void *data)
@@ -358,8 +358,7 @@ static int resume_iter(struct device *dev, void *data)
358 358
359int pcie_port_device_resume(struct pci_dev *dev) 359int pcie_port_device_resume(struct pci_dev *dev)
360{ 360{
361 device_for_each_child(&dev->dev, NULL, resume_iter); 361 return device_for_each_child(&dev->dev, NULL, resume_iter);
362 return 0;
363} 362}
364#endif 363#endif
365 364
@@ -402,9 +401,9 @@ void pcie_port_device_remove(struct pci_dev *dev)
402 pci_disable_msi(dev); 401 pci_disable_msi(dev);
403} 402}
404 403
405void pcie_port_bus_register(void) 404int __must_check pcie_port_bus_register(void)
406{ 405{
407 bus_register(&pcie_port_bus_type); 406 return bus_register(&pcie_port_bus_type);
408} 407}
409 408
410void pcie_port_bus_unregister(void) 409void pcie_port_bus_unregister(void)
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 478d0d28f7ad..037690e08f5f 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -14,8 +14,10 @@
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/pcieport_if.h> 16#include <linux/pcieport_if.h>
17#include <linux/aer.h>
17 18
18#include "portdrv.h" 19#include "portdrv.h"
20#include "aer/aerdrv.h"
19 21
20/* 22/*
21 * Version Information 23 * Version Information
@@ -30,6 +32,43 @@ MODULE_LICENSE("GPL");
30/* global data */ 32/* global data */
31static const char device_name[] = "pcieport-driver"; 33static const char device_name[] = "pcieport-driver";
32 34
35static int pcie_portdrv_save_config(struct pci_dev *dev)
36{
37 return pci_save_state(dev);
38}
39
40#ifdef CONFIG_PM
41static int pcie_portdrv_restore_config(struct pci_dev *dev)
42{
43 int retval;
44
45 pci_restore_state(dev);
46 retval = pci_enable_device(dev);
47 if (retval)
48 return retval;
49 pci_set_master(dev);
50 return 0;
51}
52
53static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state)
54{
55 int ret = pcie_port_device_suspend(dev, state);
56
57 if (!ret)
58 ret = pcie_portdrv_save_config(dev);
59 return ret;
60}
61
62static int pcie_portdrv_resume(struct pci_dev *dev)
63{
64 pcie_portdrv_restore_config(dev);
65 return pcie_port_device_resume(dev);
66}
67#else
68#define pcie_portdrv_suspend NULL
69#define pcie_portdrv_resume NULL
70#endif
71
33/* 72/*
34 * pcie_portdrv_probe - Probe PCI-Express port devices 73 * pcie_portdrv_probe - Probe PCI-Express port devices
35 * @dev: PCI-Express port device being probed 74 * @dev: PCI-Express port device being probed
@@ -61,6 +100,10 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
61 return -ENOMEM; 100 return -ENOMEM;
62 } 101 }
63 102
103 pcie_portdrv_save_config(dev);
104
105 pci_enable_pcie_error_reporting(dev);
106
64 return 0; 107 return 0;
65} 108}
66 109
@@ -70,39 +113,151 @@ static void pcie_portdrv_remove (struct pci_dev *dev)
70 kfree(pci_get_drvdata(dev)); 113 kfree(pci_get_drvdata(dev));
71} 114}
72 115
73#ifdef CONFIG_PM 116static int error_detected_iter(struct device *device, void *data)
74static int pcie_portdrv_save_config(struct pci_dev *dev)
75{ 117{
76 return pci_save_state(dev); 118 struct pcie_device *pcie_device;
119 struct pcie_port_service_driver *driver;
120 struct aer_broadcast_data *result_data;
121 pci_ers_result_t status;
122
123 result_data = (struct aer_broadcast_data *) data;
124
125 if (device->bus == &pcie_port_bus_type && device->driver) {
126 driver = to_service_driver(device->driver);
127 if (!driver ||
128 !driver->err_handler ||
129 !driver->err_handler->error_detected)
130 return 0;
131
132 pcie_device = to_pcie_device(device);
133
134 /* Forward error detected message to service drivers */
135 status = driver->err_handler->error_detected(
136 pcie_device->port,
137 result_data->state);
138 result_data->result =
139 merge_result(result_data->result, status);
140 }
141
142 return 0;
77} 143}
78 144
79static int pcie_portdrv_restore_config(struct pci_dev *dev) 145static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev,
146 enum pci_channel_state error)
80{ 147{
148 struct aer_broadcast_data result_data =
149 {error, PCI_ERS_RESULT_CAN_RECOVER};
81 int retval; 150 int retval;
82 151
83 pci_restore_state(dev); 152 /* can not fail */
84 retval = pci_enable_device(dev); 153 retval = device_for_each_child(&dev->dev, &result_data, error_detected_iter);
85 if (retval) 154
86 return retval; 155 return result_data.result;
87 pci_set_master(dev); 156}
157
158static int mmio_enabled_iter(struct device *device, void *data)
159{
160 struct pcie_device *pcie_device;
161 struct pcie_port_service_driver *driver;
162 pci_ers_result_t status, *result;
163
164 result = (pci_ers_result_t *) data;
165
166 if (device->bus == &pcie_port_bus_type && device->driver) {
167 driver = to_service_driver(device->driver);
168 if (driver &&
169 driver->err_handler &&
170 driver->err_handler->mmio_enabled) {
171 pcie_device = to_pcie_device(device);
172
173 /* Forward error message to service drivers */
174 status = driver->err_handler->mmio_enabled(
175 pcie_device->port);
176 *result = merge_result(*result, status);
177 }
178 }
179
88 return 0; 180 return 0;
89} 181}
90 182
91static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state) 183static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev)
92{ 184{
93 int ret = pcie_port_device_suspend(dev, state); 185 pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
186 int retval;
94 187
95 if (!ret) 188 /* get true return value from &status */
96 ret = pcie_portdrv_save_config(dev); 189 retval = device_for_each_child(&dev->dev, &status, mmio_enabled_iter);
97 return ret; 190 return status;
98} 191}
99 192
100static int pcie_portdrv_resume (struct pci_dev *dev) 193static int slot_reset_iter(struct device *device, void *data)
101{ 194{
102 pcie_portdrv_restore_config(dev); 195 struct pcie_device *pcie_device;
103 return pcie_port_device_resume(dev); 196 struct pcie_port_service_driver *driver;
197 pci_ers_result_t status, *result;
198
199 result = (pci_ers_result_t *) data;
200
201 if (device->bus == &pcie_port_bus_type && device->driver) {
202 driver = to_service_driver(device->driver);
203 if (driver &&
204 driver->err_handler &&
205 driver->err_handler->slot_reset) {
206 pcie_device = to_pcie_device(device);
207
208 /* Forward error message to service drivers */
209 status = driver->err_handler->slot_reset(
210 pcie_device->port);
211 *result = merge_result(*result, status);
212 }
213 }
214
215 return 0;
216}
217
218static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
219{
220 pci_ers_result_t status;
221 int retval;
222
223 /* If fatal, restore cfg space for possible link reset at upstream */
224 if (dev->error_state == pci_channel_io_frozen) {
225 pcie_portdrv_restore_config(dev);
226 pci_enable_pcie_error_reporting(dev);
227 }
228
229 /* get true return value from &status */
230 retval = device_for_each_child(&dev->dev, &status, slot_reset_iter);
231
232 return status;
233}
234
235static int resume_iter(struct device *device, void *data)
236{
237 struct pcie_device *pcie_device;
238 struct pcie_port_service_driver *driver;
239
240 if (device->bus == &pcie_port_bus_type && device->driver) {
241 driver = to_service_driver(device->driver);
242 if (driver &&
243 driver->err_handler &&
244 driver->err_handler->resume) {
245 pcie_device = to_pcie_device(device);
246
247 /* Forward error message to service drivers */
248 driver->err_handler->resume(pcie_device->port);
249 }
250 }
251
252 return 0;
253}
254
255static void pcie_portdrv_err_resume(struct pci_dev *dev)
256{
257 int retval;
258 /* nothing to do with error value, if it ever happens */
259 retval = device_for_each_child(&dev->dev, NULL, resume_iter);
104} 260}
105#endif
106 261
107/* 262/*
108 * LINUX Device Driver Model 263 * LINUX Device Driver Model
@@ -114,6 +269,13 @@ static const struct pci_device_id port_pci_ids[] = { {
114}; 269};
115MODULE_DEVICE_TABLE(pci, port_pci_ids); 270MODULE_DEVICE_TABLE(pci, port_pci_ids);
116 271
272static struct pci_error_handlers pcie_portdrv_err_handler = {
273 .error_detected = pcie_portdrv_error_detected,
274 .mmio_enabled = pcie_portdrv_mmio_enabled,
275 .slot_reset = pcie_portdrv_slot_reset,
276 .resume = pcie_portdrv_err_resume,
277};
278
117static struct pci_driver pcie_portdrv = { 279static struct pci_driver pcie_portdrv = {
118 .name = (char *)device_name, 280 .name = (char *)device_name,
119 .id_table = &port_pci_ids[0], 281 .id_table = &port_pci_ids[0],
@@ -121,20 +283,25 @@ static struct pci_driver pcie_portdrv = {
121 .probe = pcie_portdrv_probe, 283 .probe = pcie_portdrv_probe,
122 .remove = pcie_portdrv_remove, 284 .remove = pcie_portdrv_remove,
123 285
124#ifdef CONFIG_PM
125 .suspend = pcie_portdrv_suspend, 286 .suspend = pcie_portdrv_suspend,
126 .resume = pcie_portdrv_resume, 287 .resume = pcie_portdrv_resume,
127#endif /* PM */ 288
289 .err_handler = &pcie_portdrv_err_handler,
128}; 290};
129 291
130static int __init pcie_portdrv_init(void) 292static int __init pcie_portdrv_init(void)
131{ 293{
132 int retval = 0; 294 int retval;
133 295
134 pcie_port_bus_register(); 296 retval = pcie_port_bus_register();
297 if (retval) {
298 printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval);
299 goto out;
300 }
135 retval = pci_register_driver(&pcie_portdrv); 301 retval = pci_register_driver(&pcie_portdrv);
136 if (retval) 302 if (retval)
137 pcie_port_bus_unregister(); 303 pcie_port_bus_unregister();
304 out:
138 return retval; 305 return retval;
139} 306}
140 307
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index c5a58d1c6c1c..a3b0a5eb5054 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -339,6 +339,7 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
339{ 339{
340 struct pci_bus *child; 340 struct pci_bus *child;
341 int i; 341 int i;
342 int retval;
342 343
343 /* 344 /*
344 * Allocate a new bus, and inherit stuff from the parent.. 345 * Allocate a new bus, and inherit stuff from the parent..
@@ -356,8 +357,13 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
356 357
357 child->class_dev.class = &pcibus_class; 358 child->class_dev.class = &pcibus_class;
358 sprintf(child->class_dev.class_id, "%04x:%02x", pci_domain_nr(child), busnr); 359 sprintf(child->class_dev.class_id, "%04x:%02x", pci_domain_nr(child), busnr);
359 class_device_register(&child->class_dev); 360 retval = class_device_register(&child->class_dev);
360 class_device_create_file(&child->class_dev, &class_device_attr_cpuaffinity); 361 if (retval)
362 goto error_register;
363 retval = class_device_create_file(&child->class_dev,
364 &class_device_attr_cpuaffinity);
365 if (retval)
366 goto error_file_create;
361 367
362 /* 368 /*
363 * Set up the primary, secondary and subordinate 369 * Set up the primary, secondary and subordinate
@@ -375,6 +381,12 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
375 bridge->subordinate = child; 381 bridge->subordinate = child;
376 382
377 return child; 383 return child;
384
385error_file_create:
386 class_device_unregister(&child->class_dev);
387error_register:
388 kfree(child);
389 return NULL;
378} 390}
379 391
380struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr) 392struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index def78a2a7c15..08cd86a6dd66 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -577,8 +577,6 @@ static void __init quirk_ioapic_rmw(struct pci_dev *dev)
577} 577}
578DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw ); 578DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw );
579 579
580int pci_msi_quirk;
581
582#define AMD8131_revA0 0x01 580#define AMD8131_revA0 0x01
583#define AMD8131_revB0 0x11 581#define AMD8131_revB0 0x11
584#define AMD8131_MISC 0x40 582#define AMD8131_MISC 0x40
@@ -587,12 +585,6 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
587{ 585{
588 unsigned char revid, tmp; 586 unsigned char revid, tmp;
589 587
590 if (dev->subordinate) {
591 printk(KERN_WARNING "PCI: MSI quirk detected. "
592 "PCI_BUS_FLAGS_NO_MSI set for subordinate bus.\n");
593 dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
594 }
595
596 if (nr_ioapics == 0) 588 if (nr_ioapics == 0)
597 return; 589 return;
598 590
@@ -605,13 +597,6 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
605 } 597 }
606} 598}
607DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic); 599DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic);
608
609static void __init quirk_svw_msi(struct pci_dev *dev)
610{
611 pci_msi_quirk = 1;
612 printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n");
613}
614DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_svw_msi );
615#endif /* CONFIG_X86_IO_APIC */ 600#endif /* CONFIG_X86_IO_APIC */
616 601
617 602
@@ -1690,6 +1675,95 @@ static void __devinit quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev)
1690DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, 1675DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
1691 quirk_nvidia_ck804_pcie_aer_ext_cap); 1676 quirk_nvidia_ck804_pcie_aer_ext_cap);
1692 1677
1678#ifdef CONFIG_PCI_MSI
1679/* To disable MSI globally */
1680int pci_msi_quirk;
1681
1682/* The Serverworks PCI-X chipset does not support MSI. We cannot easily rely
1683 * on setting PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually
1684 * some other busses controlled by the chipset even if Linux is not aware of it.
1685 * Instead of setting the flag on all busses in the machine, simply disable MSI
1686 * globally.
1687 */
1688static void __init quirk_svw_msi(struct pci_dev *dev)
1689{
1690 pci_msi_quirk = 1;
1691 printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n");
1692}
1693DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_svw_msi);
1694
1695/* Disable MSI on chipsets that are known to not support it */
1696static void __devinit quirk_disable_msi(struct pci_dev *dev)
1697{
1698 if (dev->subordinate) {
1699 printk(KERN_WARNING "PCI: MSI quirk detected. "
1700 "PCI_BUS_FLAGS_NO_MSI set for %s subordinate bus.\n",
1701 pci_name(dev));
1702 dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
1703 }
1704}
1705DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi);
1706
1707/* Go through the list of Hypertransport capabilities and
1708 * return 1 if a HT MSI capability is found and enabled */
1709static int __devinit msi_ht_cap_enabled(struct pci_dev *dev)
1710{
1711 u8 pos;
1712 int ttl;
1713 for (pos = pci_find_capability(dev, PCI_CAP_ID_HT), ttl = 48;
1714 pos && ttl;
1715 pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_HT), ttl--) {
1716 u32 cap_hdr;
1717 /* MSI mapping section according to Hypertransport spec */
1718 if (pci_read_config_dword(dev, pos, &cap_hdr) == 0
1719 && (cap_hdr & 0xf8000000) == 0xa8000000 /* MSI mapping */) {
1720 printk(KERN_INFO "PCI: Found HT MSI mapping on %s with capability %s\n",
1721 pci_name(dev), cap_hdr & 0x10000 ? "enabled" : "disabled");
1722 return (cap_hdr & 0x10000) != 0; /* MSI mapping cap enabled */
1723 }
1724 }
1725 return 0;
1726}
1727
1728/* Check the hypertransport MSI mapping to know whether MSI is enabled or not */
1729static void __devinit quirk_msi_ht_cap(struct pci_dev *dev)
1730{
1731 if (dev->subordinate && !msi_ht_cap_enabled(dev)) {
1732 printk(KERN_WARNING "PCI: MSI quirk detected. "
1733 "MSI disabled on chipset %s.\n",
1734 pci_name(dev));
1735 dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
1736 }
1737}
1738DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE,
1739 quirk_msi_ht_cap);
1740
1741/* The nVidia CK804 chipset may have 2 HT MSI mappings.
1742 * MSI are supported if the MSI capability set in any of these mappings.
1743 */
1744static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev)
1745{
1746 struct pci_dev *pdev;
1747
1748 if (!dev->subordinate)
1749 return;
1750
1751 /* check HT MSI cap on this chipset and the root one.
1752 * a single one having MSI is enough to be sure that MSI are supported.
1753 */
1754 pdev = pci_find_slot(dev->bus->number, 0);
1755 if (dev->subordinate && !msi_ht_cap_enabled(dev)
1756 && !msi_ht_cap_enabled(pdev)) {
1757 printk(KERN_WARNING "PCI: MSI quirk detected. "
1758 "MSI disabled on chipset %s.\n",
1759 pci_name(dev));
1760 dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
1761 }
1762}
1763DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
1764 quirk_nvidia_ck804_msi_ht_cap);
1765#endif /* CONFIG_PCI_MSI */
1766
1693EXPORT_SYMBOL(pcie_mch_quirk); 1767EXPORT_SYMBOL(pcie_mch_quirk);
1694#ifdef CONFIG_HOTPLUG 1768#ifdef CONFIG_HOTPLUG
1695EXPORT_SYMBOL(pci_fixup_device); 1769EXPORT_SYMBOL(pci_fixup_device);
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 99ffbd478b29..430281b2e921 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -16,8 +16,11 @@ static void pci_free_resources(struct pci_dev *dev)
16 } 16 }
17} 17}
18 18
19static void pci_destroy_dev(struct pci_dev *dev) 19static void pci_stop_dev(struct pci_dev *dev)
20{ 20{
21 if (!dev->global_list.next)
22 return;
23
21 if (!list_empty(&dev->global_list)) { 24 if (!list_empty(&dev->global_list)) {
22 pci_proc_detach_device(dev); 25 pci_proc_detach_device(dev);
23 pci_remove_sysfs_dev_files(dev); 26 pci_remove_sysfs_dev_files(dev);
@@ -27,6 +30,11 @@ static void pci_destroy_dev(struct pci_dev *dev)
27 dev->global_list.next = dev->global_list.prev = NULL; 30 dev->global_list.next = dev->global_list.prev = NULL;
28 up_write(&pci_bus_sem); 31 up_write(&pci_bus_sem);
29 } 32 }
33}
34
35static void pci_destroy_dev(struct pci_dev *dev)
36{
37 pci_stop_dev(dev);
30 38
31 /* Remove the device from the device lists, and prevent any further 39 /* Remove the device from the device lists, and prevent any further
32 * list accesses from this device */ 40 * list accesses from this device */
@@ -119,5 +127,32 @@ void pci_remove_behind_bridge(struct pci_dev *dev)
119 } 127 }
120} 128}
121 129
130static void pci_stop_bus_devices(struct pci_bus *bus)
131{
132 struct list_head *l, *n;
133
134 list_for_each_safe(l, n, &bus->devices) {
135 struct pci_dev *dev = pci_dev_b(l);
136 pci_stop_bus_device(dev);
137 }
138}
139
140/**
141 * pci_stop_bus_device - stop a PCI device and any children
142 * @dev: the device to stop
143 *
144 * Stop a PCI device (detach the driver, remove from the global list
145 * and so on). This also stop any subordinate buses and children in a
146 * depth-first manner.
147 */
148void pci_stop_bus_device(struct pci_dev *dev)
149{
150 if (dev->subordinate)
151 pci_stop_bus_devices(dev->subordinate);
152
153 pci_stop_dev(dev);
154}
155
122EXPORT_SYMBOL(pci_remove_bus_device); 156EXPORT_SYMBOL(pci_remove_bus_device);
123EXPORT_SYMBOL(pci_remove_behind_bridge); 157EXPORT_SYMBOL(pci_remove_behind_bridge);
158EXPORT_SYMBOL_GPL(pci_stop_bus_device);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 47c1071ad84e..54404917be9a 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -55,12 +55,19 @@ pbus_assign_resources_sorted(struct pci_bus *bus)
55 list_for_each_entry(dev, &bus->devices, bus_list) { 55 list_for_each_entry(dev, &bus->devices, bus_list) {
56 u16 class = dev->class >> 8; 56 u16 class = dev->class >> 8;
57 57
58 /* Don't touch classless devices or host bridges or ioapics. */ 58 /* Don't touch classless devices or host bridges. */
59 if (class == PCI_CLASS_NOT_DEFINED || 59 if (class == PCI_CLASS_NOT_DEFINED ||
60 class == PCI_CLASS_BRIDGE_HOST || 60 class == PCI_CLASS_BRIDGE_HOST)
61 class == PCI_CLASS_SYSTEM_PIC)
62 continue; 61 continue;
63 62
63 /* Don't touch ioapics if it has the assigned resources. */
64 if (class == PCI_CLASS_SYSTEM_PIC) {
65 res = &dev->resource[0];
66 if (res[0].start || res[1].start || res[2].start ||
67 res[3].start || res[4].start || res[5].start)
68 continue;
69 }
70
64 pdev_sort_resources(dev, &head); 71 pdev_sort_resources(dev, &head);
65 } 72 }
66 73