diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/acpiphp.h | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_core.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 4 | ||||
-rw-r--r-- | drivers/pci/hotplug/ibmphp_core.c | 5 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_core.c | 23 | ||||
-rw-r--r-- | drivers/pci/intr_remapping.c | 77 | ||||
-rw-r--r-- | drivers/pci/msi.c | 55 | ||||
-rw-r--r-- | drivers/pci/pci.c | 2 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv_core.c | 2 | ||||
-rw-r--r-- | drivers/pci/pcie/aspm.c | 29 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 17 | ||||
-rw-r--r-- | drivers/pci/slot.c | 1 |
12 files changed, 175 insertions, 44 deletions
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index f9e244da30ae..9bcb6cbd5aa9 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
@@ -113,7 +113,7 @@ struct acpiphp_slot { | |||
113 | 113 | ||
114 | u8 device; /* pci device# */ | 114 | u8 device; /* pci device# */ |
115 | 115 | ||
116 | u32 sun; /* ACPI _SUN (slot unique number) */ | 116 | unsigned long long sun; /* ACPI _SUN (slot unique number) */ |
117 | u32 flags; /* see below */ | 117 | u32 flags; /* see below */ |
118 | }; | 118 | }; |
119 | 119 | ||
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index 95b536a23d25..43c10bd261b4 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c | |||
@@ -337,7 +337,7 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) | |||
337 | slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; | 337 | slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; |
338 | 338 | ||
339 | acpiphp_slot->slot = slot; | 339 | acpiphp_slot->slot = slot; |
340 | snprintf(name, SLOT_NAME_SIZE, "%u", slot->acpi_slot->sun); | 340 | snprintf(name, SLOT_NAME_SIZE, "%llu", slot->acpi_slot->sun); |
341 | 341 | ||
342 | retval = pci_hp_register(slot->hotplug_slot, | 342 | retval = pci_hp_register(slot->hotplug_slot, |
343 | acpiphp_slot->bridge->pci_bus, | 343 | acpiphp_slot->bridge->pci_bus, |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 955aae4071f7..3affc6472e65 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -255,13 +255,13 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
255 | 255 | ||
256 | bridge->nr_slots++; | 256 | bridge->nr_slots++; |
257 | 257 | ||
258 | dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n", | 258 | dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", |
259 | slot->sun, pci_domain_nr(bridge->pci_bus), | 259 | slot->sun, pci_domain_nr(bridge->pci_bus), |
260 | bridge->pci_bus->number, slot->device); | 260 | bridge->pci_bus->number, slot->device); |
261 | retval = acpiphp_register_hotplug_slot(slot); | 261 | retval = acpiphp_register_hotplug_slot(slot); |
262 | if (retval) { | 262 | if (retval) { |
263 | if (retval == -EBUSY) | 263 | if (retval == -EBUSY) |
264 | warn("Slot %d already registered by another " | 264 | warn("Slot %llu already registered by another " |
265 | "hotplug driver\n", slot->sun); | 265 | "hotplug driver\n", slot->sun); |
266 | else | 266 | else |
267 | warn("acpiphp_register_hotplug_slot failed " | 267 | warn("acpiphp_register_hotplug_slot failed " |
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index c892daae74d6..633e743442ac 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c | |||
@@ -1402,10 +1402,6 @@ static int __init ibmphp_init(void) | |||
1402 | goto error; | 1402 | goto error; |
1403 | } | 1403 | } |
1404 | 1404 | ||
1405 | /* lock ourselves into memory with a module | ||
1406 | * count of -1 so that no one can unload us. */ | ||
1407 | module_put(THIS_MODULE); | ||
1408 | |||
1409 | exit: | 1405 | exit: |
1410 | return rc; | 1406 | return rc; |
1411 | 1407 | ||
@@ -1423,4 +1419,3 @@ static void __exit ibmphp_exit(void) | |||
1423 | } | 1419 | } |
1424 | 1420 | ||
1425 | module_init(ibmphp_init); | 1421 | module_init(ibmphp_init); |
1426 | module_exit(ibmphp_exit); | ||
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 4b23bc39b11e..39cf248d24e3 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -432,18 +432,19 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
432 | goto err_out_release_ctlr; | 432 | goto err_out_release_ctlr; |
433 | } | 433 | } |
434 | 434 | ||
435 | /* Check if slot is occupied */ | ||
435 | t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); | 436 | t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); |
436 | 437 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); | |
437 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ | 438 | if (value) { |
438 | if (value && pciehp_force) { | 439 | if (pciehp_force) |
439 | rc = pciehp_enable_slot(t_slot); | 440 | pciehp_enable_slot(t_slot); |
440 | if (rc) /* -ENODEV: shouldn't happen, but deal with it */ | 441 | } else { |
441 | value = 0; | 442 | /* Power off slot if not occupied */ |
442 | } | 443 | if (POWER_CTRL(ctrl)) { |
443 | if ((POWER_CTRL(ctrl)) && !value) { | 444 | rc = t_slot->hpc_ops->power_off_slot(t_slot); |
444 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ | 445 | if (rc) |
445 | if (rc) | 446 | goto err_out_free_ctrl_slot; |
446 | goto err_out_free_ctrl_slot; | 447 | } |
447 | } | 448 | } |
448 | 449 | ||
449 | return 0; | 450 | return 0; |
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index 2de5a3238c94..f78371b22529 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/pci.h> | 5 | #include <linux/pci.h> |
6 | #include <linux/irq.h> | 6 | #include <linux/irq.h> |
7 | #include <asm/io_apic.h> | 7 | #include <asm/io_apic.h> |
8 | #include <asm/smp.h> | ||
8 | #include <linux/intel-iommu.h> | 9 | #include <linux/intel-iommu.h> |
9 | #include "intr_remapping.h" | 10 | #include "intr_remapping.h" |
10 | 11 | ||
@@ -19,17 +20,75 @@ struct irq_2_iommu { | |||
19 | u8 irte_mask; | 20 | u8 irte_mask; |
20 | }; | 21 | }; |
21 | 22 | ||
22 | static struct irq_2_iommu irq_2_iommuX[NR_IRQS]; | 23 | #ifdef CONFIG_SPARSE_IRQ |
24 | static struct irq_2_iommu *get_one_free_irq_2_iommu(int cpu) | ||
25 | { | ||
26 | struct irq_2_iommu *iommu; | ||
27 | int node; | ||
28 | |||
29 | node = cpu_to_node(cpu); | ||
30 | |||
31 | iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node); | ||
32 | printk(KERN_DEBUG "alloc irq_2_iommu on cpu %d node %d\n", cpu, node); | ||
33 | |||
34 | return iommu; | ||
35 | } | ||
23 | 36 | ||
24 | static struct irq_2_iommu *irq_2_iommu(unsigned int irq) | 37 | static struct irq_2_iommu *irq_2_iommu(unsigned int irq) |
25 | { | 38 | { |
26 | return (irq < nr_irqs) ? irq_2_iommuX + irq : NULL; | 39 | struct irq_desc *desc; |
40 | |||
41 | desc = irq_to_desc(irq); | ||
42 | |||
43 | if (WARN_ON_ONCE(!desc)) | ||
44 | return NULL; | ||
45 | |||
46 | return desc->irq_2_iommu; | ||
47 | } | ||
48 | |||
49 | static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu) | ||
50 | { | ||
51 | struct irq_desc *desc; | ||
52 | struct irq_2_iommu *irq_iommu; | ||
53 | |||
54 | /* | ||
55 | * alloc irq desc if not allocated already. | ||
56 | */ | ||
57 | desc = irq_to_desc_alloc_cpu(irq, cpu); | ||
58 | if (!desc) { | ||
59 | printk(KERN_INFO "can not get irq_desc for %d\n", irq); | ||
60 | return NULL; | ||
61 | } | ||
62 | |||
63 | irq_iommu = desc->irq_2_iommu; | ||
64 | |||
65 | if (!irq_iommu) | ||
66 | desc->irq_2_iommu = get_one_free_irq_2_iommu(cpu); | ||
67 | |||
68 | return desc->irq_2_iommu; | ||
27 | } | 69 | } |
28 | 70 | ||
29 | static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq) | 71 | static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq) |
30 | { | 72 | { |
73 | return irq_2_iommu_alloc_cpu(irq, boot_cpu_id); | ||
74 | } | ||
75 | |||
76 | #else /* !CONFIG_SPARSE_IRQ */ | ||
77 | |||
78 | static struct irq_2_iommu irq_2_iommuX[NR_IRQS]; | ||
79 | |||
80 | static struct irq_2_iommu *irq_2_iommu(unsigned int irq) | ||
81 | { | ||
82 | if (irq < nr_irqs) | ||
83 | return &irq_2_iommuX[irq]; | ||
84 | |||
85 | return NULL; | ||
86 | } | ||
87 | static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq) | ||
88 | { | ||
31 | return irq_2_iommu(irq); | 89 | return irq_2_iommu(irq); |
32 | } | 90 | } |
91 | #endif | ||
33 | 92 | ||
34 | static DEFINE_SPINLOCK(irq_2_ir_lock); | 93 | static DEFINE_SPINLOCK(irq_2_ir_lock); |
35 | 94 | ||
@@ -86,9 +145,11 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) | |||
86 | if (!count) | 145 | if (!count) |
87 | return -1; | 146 | return -1; |
88 | 147 | ||
148 | #ifndef CONFIG_SPARSE_IRQ | ||
89 | /* protect irq_2_iommu_alloc later */ | 149 | /* protect irq_2_iommu_alloc later */ |
90 | if (irq >= nr_irqs) | 150 | if (irq >= nr_irqs) |
91 | return -1; | 151 | return -1; |
152 | #endif | ||
92 | 153 | ||
93 | /* | 154 | /* |
94 | * start the IRTE search from index 0. | 155 | * start the IRTE search from index 0. |
@@ -130,6 +191,12 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) | |||
130 | table->base[i].present = 1; | 191 | table->base[i].present = 1; |
131 | 192 | ||
132 | irq_iommu = irq_2_iommu_alloc(irq); | 193 | irq_iommu = irq_2_iommu_alloc(irq); |
194 | if (!irq_iommu) { | ||
195 | spin_unlock(&irq_2_ir_lock); | ||
196 | printk(KERN_ERR "can't allocate irq_2_iommu\n"); | ||
197 | return -1; | ||
198 | } | ||
199 | |||
133 | irq_iommu->iommu = iommu; | 200 | irq_iommu->iommu = iommu; |
134 | irq_iommu->irte_index = index; | 201 | irq_iommu->irte_index = index; |
135 | irq_iommu->sub_handle = 0; | 202 | irq_iommu->sub_handle = 0; |
@@ -177,6 +244,12 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle) | |||
177 | 244 | ||
178 | irq_iommu = irq_2_iommu_alloc(irq); | 245 | irq_iommu = irq_2_iommu_alloc(irq); |
179 | 246 | ||
247 | if (!irq_iommu) { | ||
248 | spin_unlock(&irq_2_ir_lock); | ||
249 | printk(KERN_ERR "can't allocate irq_2_iommu\n"); | ||
250 | return -1; | ||
251 | } | ||
252 | |||
180 | irq_iommu->iommu = iommu; | 253 | irq_iommu->iommu = iommu; |
181 | irq_iommu->irte_index = index; | 254 | irq_iommu->irte_index = index; |
182 | irq_iommu->sub_handle = subhandle; | 255 | irq_iommu->sub_handle = subhandle; |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 74801f7df9c9..11a51f8ed3b3 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -103,11 +103,11 @@ static void msix_set_enable(struct pci_dev *dev, int enable) | |||
103 | } | 103 | } |
104 | } | 104 | } |
105 | 105 | ||
106 | static void msix_flush_writes(unsigned int irq) | 106 | static void msix_flush_writes(struct irq_desc *desc) |
107 | { | 107 | { |
108 | struct msi_desc *entry; | 108 | struct msi_desc *entry; |
109 | 109 | ||
110 | entry = get_irq_msi(irq); | 110 | entry = get_irq_desc_msi(desc); |
111 | BUG_ON(!entry || !entry->dev); | 111 | BUG_ON(!entry || !entry->dev); |
112 | switch (entry->msi_attrib.type) { | 112 | switch (entry->msi_attrib.type) { |
113 | case PCI_CAP_ID_MSI: | 113 | case PCI_CAP_ID_MSI: |
@@ -135,11 +135,11 @@ static void msix_flush_writes(unsigned int irq) | |||
135 | * Returns 1 if it succeeded in masking the interrupt and 0 if the device | 135 | * Returns 1 if it succeeded in masking the interrupt and 0 if the device |
136 | * doesn't support MSI masking. | 136 | * doesn't support MSI masking. |
137 | */ | 137 | */ |
138 | static int msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) | 138 | static int msi_set_mask_bits(struct irq_desc *desc, u32 mask, u32 flag) |
139 | { | 139 | { |
140 | struct msi_desc *entry; | 140 | struct msi_desc *entry; |
141 | 141 | ||
142 | entry = get_irq_msi(irq); | 142 | entry = get_irq_desc_msi(desc); |
143 | BUG_ON(!entry || !entry->dev); | 143 | BUG_ON(!entry || !entry->dev); |
144 | switch (entry->msi_attrib.type) { | 144 | switch (entry->msi_attrib.type) { |
145 | case PCI_CAP_ID_MSI: | 145 | case PCI_CAP_ID_MSI: |
@@ -172,9 +172,9 @@ static int msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) | |||
172 | return 1; | 172 | return 1; |
173 | } | 173 | } |
174 | 174 | ||
175 | void read_msi_msg(unsigned int irq, struct msi_msg *msg) | 175 | void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) |
176 | { | 176 | { |
177 | struct msi_desc *entry = get_irq_msi(irq); | 177 | struct msi_desc *entry = get_irq_desc_msi(desc); |
178 | switch(entry->msi_attrib.type) { | 178 | switch(entry->msi_attrib.type) { |
179 | case PCI_CAP_ID_MSI: | 179 | case PCI_CAP_ID_MSI: |
180 | { | 180 | { |
@@ -211,9 +211,16 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg) | |||
211 | } | 211 | } |
212 | } | 212 | } |
213 | 213 | ||
214 | void write_msi_msg(unsigned int irq, struct msi_msg *msg) | 214 | void read_msi_msg(unsigned int irq, struct msi_msg *msg) |
215 | { | 215 | { |
216 | struct msi_desc *entry = get_irq_msi(irq); | 216 | struct irq_desc *desc = irq_to_desc(irq); |
217 | |||
218 | read_msi_msg_desc(desc, msg); | ||
219 | } | ||
220 | |||
221 | void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | ||
222 | { | ||
223 | struct msi_desc *entry = get_irq_desc_msi(desc); | ||
217 | switch (entry->msi_attrib.type) { | 224 | switch (entry->msi_attrib.type) { |
218 | case PCI_CAP_ID_MSI: | 225 | case PCI_CAP_ID_MSI: |
219 | { | 226 | { |
@@ -252,21 +259,31 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg) | |||
252 | entry->msg = *msg; | 259 | entry->msg = *msg; |
253 | } | 260 | } |
254 | 261 | ||
262 | void write_msi_msg(unsigned int irq, struct msi_msg *msg) | ||
263 | { | ||
264 | struct irq_desc *desc = irq_to_desc(irq); | ||
265 | |||
266 | write_msi_msg_desc(desc, msg); | ||
267 | } | ||
268 | |||
255 | void mask_msi_irq(unsigned int irq) | 269 | void mask_msi_irq(unsigned int irq) |
256 | { | 270 | { |
257 | msi_set_mask_bits(irq, 1, 1); | 271 | struct irq_desc *desc = irq_to_desc(irq); |
258 | msix_flush_writes(irq); | 272 | |
273 | msi_set_mask_bits(desc, 1, 1); | ||
274 | msix_flush_writes(desc); | ||
259 | } | 275 | } |
260 | 276 | ||
261 | void unmask_msi_irq(unsigned int irq) | 277 | void unmask_msi_irq(unsigned int irq) |
262 | { | 278 | { |
263 | msi_set_mask_bits(irq, 1, 0); | 279 | struct irq_desc *desc = irq_to_desc(irq); |
264 | msix_flush_writes(irq); | 280 | |
281 | msi_set_mask_bits(desc, 1, 0); | ||
282 | msix_flush_writes(desc); | ||
265 | } | 283 | } |
266 | 284 | ||
267 | static int msi_free_irqs(struct pci_dev* dev); | 285 | static int msi_free_irqs(struct pci_dev* dev); |
268 | 286 | ||
269 | |||
270 | static struct msi_desc* alloc_msi_entry(void) | 287 | static struct msi_desc* alloc_msi_entry(void) |
271 | { | 288 | { |
272 | struct msi_desc *entry; | 289 | struct msi_desc *entry; |
@@ -303,9 +320,11 @@ static void __pci_restore_msi_state(struct pci_dev *dev) | |||
303 | pci_intx_for_msi(dev, 0); | 320 | pci_intx_for_msi(dev, 0); |
304 | msi_set_enable(dev, 0); | 321 | msi_set_enable(dev, 0); |
305 | write_msi_msg(dev->irq, &entry->msg); | 322 | write_msi_msg(dev->irq, &entry->msg); |
306 | if (entry->msi_attrib.maskbit) | 323 | if (entry->msi_attrib.maskbit) { |
307 | msi_set_mask_bits(dev->irq, entry->msi_attrib.maskbits_mask, | 324 | struct irq_desc *desc = irq_to_desc(dev->irq); |
325 | msi_set_mask_bits(desc, entry->msi_attrib.maskbits_mask, | ||
308 | entry->msi_attrib.masked); | 326 | entry->msi_attrib.masked); |
327 | } | ||
309 | 328 | ||
310 | pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); | 329 | pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); |
311 | control &= ~PCI_MSI_FLAGS_QSIZE; | 330 | control &= ~PCI_MSI_FLAGS_QSIZE; |
@@ -327,8 +346,9 @@ static void __pci_restore_msix_state(struct pci_dev *dev) | |||
327 | msix_set_enable(dev, 0); | 346 | msix_set_enable(dev, 0); |
328 | 347 | ||
329 | list_for_each_entry(entry, &dev->msi_list, list) { | 348 | list_for_each_entry(entry, &dev->msi_list, list) { |
349 | struct irq_desc *desc = irq_to_desc(entry->irq); | ||
330 | write_msi_msg(entry->irq, &entry->msg); | 350 | write_msi_msg(entry->irq, &entry->msg); |
331 | msi_set_mask_bits(entry->irq, 1, entry->msi_attrib.masked); | 351 | msi_set_mask_bits(desc, 1, entry->msi_attrib.masked); |
332 | } | 352 | } |
333 | 353 | ||
334 | BUG_ON(list_empty(&dev->msi_list)); | 354 | BUG_ON(list_empty(&dev->msi_list)); |
@@ -596,7 +616,8 @@ void pci_msi_shutdown(struct pci_dev* dev) | |||
596 | /* Return the the pci reset with msi irqs unmasked */ | 616 | /* Return the the pci reset with msi irqs unmasked */ |
597 | if (entry->msi_attrib.maskbit) { | 617 | if (entry->msi_attrib.maskbit) { |
598 | u32 mask = entry->msi_attrib.maskbits_mask; | 618 | u32 mask = entry->msi_attrib.maskbits_mask; |
599 | msi_set_mask_bits(dev->irq, mask, ~mask); | 619 | struct irq_desc *desc = irq_to_desc(dev->irq); |
620 | msi_set_mask_bits(desc, mask, ~mask); | ||
600 | } | 621 | } |
601 | if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) | 622 | if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) |
602 | return; | 623 | return; |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 28af496b441e..061d1ee0046a 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -2042,7 +2042,7 @@ static int __devinit pci_init(void) | |||
2042 | return 0; | 2042 | return 0; |
2043 | } | 2043 | } |
2044 | 2044 | ||
2045 | static int __devinit pci_setup(char *str) | 2045 | static int __init pci_setup(char *str) |
2046 | { | 2046 | { |
2047 | while (str) { | 2047 | while (str) { |
2048 | char *k = strchr(str, ','); | 2048 | char *k = strchr(str, ','); |
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index dfc63d01f20a..aac7006949f1 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
@@ -252,7 +252,7 @@ static void report_resume(struct pci_dev *dev, void *data) | |||
252 | 252 | ||
253 | if (!dev->driver || | 253 | if (!dev->driver || |
254 | !dev->driver->err_handler || | 254 | !dev->driver->err_handler || |
255 | !dev->driver->err_handler->slot_reset) | 255 | !dev->driver->err_handler->resume) |
256 | return; | 256 | return; |
257 | 257 | ||
258 | err_handler = dev->driver->err_handler; | 258 | err_handler = dev->driver->err_handler; |
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 8f63f4c6b85f..9aad608bcf3f 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/pm.h> | 16 | #include <linux/pm.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/jiffies.h> | ||
19 | #include <linux/pci-aspm.h> | 20 | #include <linux/pci-aspm.h> |
20 | #include "../pci.h" | 21 | #include "../pci.h" |
21 | 22 | ||
@@ -161,11 +162,12 @@ static void pcie_check_clock_pm(struct pci_dev *pdev) | |||
161 | */ | 162 | */ |
162 | static void pcie_aspm_configure_common_clock(struct pci_dev *pdev) | 163 | static void pcie_aspm_configure_common_clock(struct pci_dev *pdev) |
163 | { | 164 | { |
164 | int pos, child_pos; | 165 | int pos, child_pos, i = 0; |
165 | u16 reg16 = 0; | 166 | u16 reg16 = 0; |
166 | struct pci_dev *child_dev; | 167 | struct pci_dev *child_dev; |
167 | int same_clock = 1; | 168 | int same_clock = 1; |
168 | 169 | unsigned long start_jiffies; | |
170 | u16 child_regs[8], parent_reg; | ||
169 | /* | 171 | /* |
170 | * all functions of a slot should have the same Slot Clock | 172 | * all functions of a slot should have the same Slot Clock |
171 | * Configuration, so just check one function | 173 | * Configuration, so just check one function |
@@ -191,16 +193,19 @@ static void pcie_aspm_configure_common_clock(struct pci_dev *pdev) | |||
191 | child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP); | 193 | child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP); |
192 | pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKCTL, | 194 | pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKCTL, |
193 | ®16); | 195 | ®16); |
196 | child_regs[i] = reg16; | ||
194 | if (same_clock) | 197 | if (same_clock) |
195 | reg16 |= PCI_EXP_LNKCTL_CCC; | 198 | reg16 |= PCI_EXP_LNKCTL_CCC; |
196 | else | 199 | else |
197 | reg16 &= ~PCI_EXP_LNKCTL_CCC; | 200 | reg16 &= ~PCI_EXP_LNKCTL_CCC; |
198 | pci_write_config_word(child_dev, child_pos + PCI_EXP_LNKCTL, | 201 | pci_write_config_word(child_dev, child_pos + PCI_EXP_LNKCTL, |
199 | reg16); | 202 | reg16); |
203 | i++; | ||
200 | } | 204 | } |
201 | 205 | ||
202 | /* Configure upstream component */ | 206 | /* Configure upstream component */ |
203 | pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); | 207 | pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); |
208 | parent_reg = reg16; | ||
204 | if (same_clock) | 209 | if (same_clock) |
205 | reg16 |= PCI_EXP_LNKCTL_CCC; | 210 | reg16 |= PCI_EXP_LNKCTL_CCC; |
206 | else | 211 | else |
@@ -212,12 +217,30 @@ static void pcie_aspm_configure_common_clock(struct pci_dev *pdev) | |||
212 | pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); | 217 | pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); |
213 | 218 | ||
214 | /* Wait for link training end */ | 219 | /* Wait for link training end */ |
215 | while (1) { | 220 | /* break out after waiting for 1 second */ |
221 | start_jiffies = jiffies; | ||
222 | while ((jiffies - start_jiffies) < HZ) { | ||
216 | pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, ®16); | 223 | pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, ®16); |
217 | if (!(reg16 & PCI_EXP_LNKSTA_LT)) | 224 | if (!(reg16 & PCI_EXP_LNKSTA_LT)) |
218 | break; | 225 | break; |
219 | cpu_relax(); | 226 | cpu_relax(); |
220 | } | 227 | } |
228 | /* training failed -> recover */ | ||
229 | if ((jiffies - start_jiffies) >= HZ) { | ||
230 | dev_printk (KERN_ERR, &pdev->dev, "ASPM: Could not configure" | ||
231 | " common clock\n"); | ||
232 | i = 0; | ||
233 | list_for_each_entry(child_dev, &pdev->subordinate->devices, | ||
234 | bus_list) { | ||
235 | child_pos = pci_find_capability(child_dev, | ||
236 | PCI_CAP_ID_EXP); | ||
237 | pci_write_config_word(child_dev, | ||
238 | child_pos + PCI_EXP_LNKCTL, | ||
239 | child_regs[i]); | ||
240 | i++; | ||
241 | } | ||
242 | pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, parent_reg); | ||
243 | } | ||
221 | } | 244 | } |
222 | 245 | ||
223 | /* | 246 | /* |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 5049a47030ac..5f4f85f56cb7 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/acpi.h> | 23 | #include <linux/acpi.h> |
24 | #include <linux/kallsyms.h> | 24 | #include <linux/kallsyms.h> |
25 | #include <linux/dmi.h> | ||
25 | #include "pci.h" | 26 | #include "pci.h" |
26 | 27 | ||
27 | int isa_dma_bridge_buggy; | 28 | int isa_dma_bridge_buggy; |
@@ -1828,6 +1829,22 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, | |||
1828 | PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB, | 1829 | PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB, |
1829 | ht_enable_msi_mapping); | 1830 | ht_enable_msi_mapping); |
1830 | 1831 | ||
1832 | /* The P5N32-SLI Premium motherboard from Asus has a problem with msi | ||
1833 | * for the MCP55 NIC. It is not yet determined whether the msi problem | ||
1834 | * also affects other devices. As for now, turn off msi for this device. | ||
1835 | */ | ||
1836 | static void __devinit nvenet_msi_disable(struct pci_dev *dev) | ||
1837 | { | ||
1838 | if (dmi_name_in_vendors("P5N32-SLI PREMIUM")) { | ||
1839 | dev_info(&dev->dev, | ||
1840 | "Disabling msi for MCP55 NIC on P5N32-SLI Premium\n"); | ||
1841 | dev->no_msi = 1; | ||
1842 | } | ||
1843 | } | ||
1844 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, | ||
1845 | PCI_DEVICE_ID_NVIDIA_NVENET_15, | ||
1846 | nvenet_msi_disable); | ||
1847 | |||
1831 | static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) | 1848 | static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) |
1832 | { | 1849 | { |
1833 | struct pci_dev *host_bridge; | 1850 | struct pci_dev *host_bridge; |
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index 4dd1c3e157ae..5a8ccb4f604d 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c | |||
@@ -253,6 +253,7 @@ placeholder: | |||
253 | __func__, pci_domain_nr(parent), parent->number, slot_nr); | 253 | __func__, pci_domain_nr(parent), parent->number, slot_nr); |
254 | 254 | ||
255 | out: | 255 | out: |
256 | kfree(slot_name); | ||
256 | up_write(&pci_bus_sem); | 257 | up_write(&pci_bus_sem); |
257 | return slot; | 258 | return slot; |
258 | err: | 259 | err: |