aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r--drivers/pci/hotplug/Kconfig4
-rw-r--r--drivers/pci/hotplug/Makefile4
-rw-r--r--drivers/pci/hotplug/acpiphp.h1
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c5
-rw-r--r--drivers/pci/hotplug/fakephp.c39
-rw-r--r--drivers/pci/hotplug/ibmphp_core.c11
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c4
-rw-r--r--drivers/pci/hotplug/pciehp.h9
-rw-r--r--drivers/pci/hotplug/pciehp_core.c33
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c27
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c314
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c43
-rw-r--r--drivers/pci/hotplug/rpaphp.h1
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c14
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c47
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c2
16 files changed, 332 insertions, 226 deletions
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index a64449d489d6..2cdd8326f136 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -3,8 +3,8 @@
3# 3#
4 4
5menuconfig HOTPLUG_PCI 5menuconfig HOTPLUG_PCI
6 tristate "Support for PCI Hotplug (EXPERIMENTAL)" 6 tristate "Support for PCI Hotplug"
7 depends on PCI && EXPERIMENTAL && HOTPLUG 7 depends on PCI && HOTPLUG
8 ---help--- 8 ---help---
9 Say Y here if you have a motherboard with a PCI Hotplug controller. 9 Say Y here if you have a motherboard with a PCI Hotplug controller.
10 This allows you to add and remove PCI cards while the machine is 10 This allows you to add and remove PCI cards while the machine is
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
index 34a1891191fd..9bdbe1a6688f 100644
--- a/drivers/pci/hotplug/Makefile
+++ b/drivers/pci/hotplug/Makefile
@@ -3,7 +3,6 @@
3# 3#
4 4
5obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o 5obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o
6obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o
7obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o 6obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o
8obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o 7obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o
9obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o 8obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
@@ -16,6 +15,9 @@ obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o
16obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o 15obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o
17obj-$(CONFIG_HOTPLUG_PCI_SGI) += sgi_hotplug.o 16obj-$(CONFIG_HOTPLUG_PCI_SGI) += sgi_hotplug.o
18 17
18# Link this last so it doesn't claim devices that have a real hotplug driver
19obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o
20
19pci_hotplug-objs := pci_hotplug_core.o 21pci_hotplug-objs := pci_hotplug_core.o
20 22
21ifdef CONFIG_HOTPLUG_PCI_CPCI 23ifdef CONFIG_HOTPLUG_PCI_CPCI
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index 1ef417cca2db..7a29164d4b32 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -113,7 +113,6 @@ struct acpiphp_slot {
113 u8 device; /* pci device# */ 113 u8 device; /* pci device# */
114 114
115 u32 sun; /* ACPI _SUN (slot unique number) */ 115 u32 sun; /* ACPI _SUN (slot unique number) */
116 u32 slotno; /* slot number relative to bridge */
117 u32 flags; /* see below */ 116 u32 flags; /* see below */
118}; 117};
119 118
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index ff1b1c71291a..cf22f9e01e00 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -102,7 +102,7 @@ static int is_ejectable(acpi_handle handle)
102} 102}
103 103
104 104
105/* callback routine to check the existence of ejectable slots */ 105/* callback routine to check for the existence of ejectable slots */
106static acpi_status 106static acpi_status
107is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv) 107is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
108{ 108{
@@ -117,7 +117,7 @@ is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
117 } 117 }
118} 118}
119 119
120/* callback routine to check for the existance of a pci dock device */ 120/* callback routine to check for the existence of a pci dock device */
121static acpi_status 121static acpi_status
122is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv) 122is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
123{ 123{
@@ -1528,7 +1528,6 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
1528 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); 1528 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
1529 dbg("%s: re-enumerating slots under %s\n", 1529 dbg("%s: re-enumerating slots under %s\n",
1530 __FUNCTION__, objname); 1530 __FUNCTION__, objname);
1531 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
1532 acpiphp_check_bridge(bridge); 1531 acpiphp_check_bridge(bridge);
1533 } 1532 }
1534 return AE_OK ; 1533 return AE_OK ;
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index d7a293e3faf5..94b640146d44 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -39,6 +39,7 @@
39#include <linux/init.h> 39#include <linux/init.h>
40#include <linux/string.h> 40#include <linux/string.h>
41#include <linux/slab.h> 41#include <linux/slab.h>
42#include <linux/workqueue.h>
42#include "../pci.h" 43#include "../pci.h"
43 44
44#if !defined(MODULE) 45#if !defined(MODULE)
@@ -63,10 +64,16 @@ struct dummy_slot {
63 struct list_head node; 64 struct list_head node;
64 struct hotplug_slot *slot; 65 struct hotplug_slot *slot;
65 struct pci_dev *dev; 66 struct pci_dev *dev;
67 struct work_struct remove_work;
68 unsigned long removed;
66}; 69};
67 70
68static int debug; 71static int debug;
69static LIST_HEAD(slot_list); 72static LIST_HEAD(slot_list);
73static struct workqueue_struct *dummyphp_wq;
74
75static void pci_rescan_worker(struct work_struct *work);
76static DECLARE_WORK(pci_rescan_work, pci_rescan_worker);
70 77
71static int enable_slot (struct hotplug_slot *slot); 78static int enable_slot (struct hotplug_slot *slot);
72static int disable_slot (struct hotplug_slot *slot); 79static int disable_slot (struct hotplug_slot *slot);
@@ -109,7 +116,7 @@ static int add_slot(struct pci_dev *dev)
109 slot->name = &dev->dev.bus_id[0]; 116 slot->name = &dev->dev.bus_id[0];
110 dbg("slot->name = %s\n", slot->name); 117 dbg("slot->name = %s\n", slot->name);
111 118
112 dslot = kmalloc(sizeof(struct dummy_slot), GFP_KERNEL); 119 dslot = kzalloc(sizeof(struct dummy_slot), GFP_KERNEL);
113 if (!dslot) 120 if (!dslot)
114 goto error_info; 121 goto error_info;
115 122
@@ -164,6 +171,14 @@ static void remove_slot(struct dummy_slot *dslot)
164 err("Problem unregistering a slot %s\n", dslot->slot->name); 171 err("Problem unregistering a slot %s\n", dslot->slot->name);
165} 172}
166 173
174/* called from the single-threaded workqueue handler to remove a slot */
175static void remove_slot_worker(struct work_struct *work)
176{
177 struct dummy_slot *dslot =
178 container_of(work, struct dummy_slot, remove_work);
179 remove_slot(dslot);
180}
181
167/** 182/**
168 * pci_rescan_slot - Rescan slot 183 * pci_rescan_slot - Rescan slot
169 * @temp: Device template. Should be set: bus and devfn. 184 * @temp: Device template. Should be set: bus and devfn.
@@ -267,11 +282,17 @@ static inline void pci_rescan(void) {
267 pci_rescan_buses(&pci_root_buses); 282 pci_rescan_buses(&pci_root_buses);
268} 283}
269 284
285/* called from the single-threaded workqueue handler to rescan all pci buses */
286static void pci_rescan_worker(struct work_struct *work)
287{
288 pci_rescan();
289}
270 290
271static int enable_slot(struct hotplug_slot *hotplug_slot) 291static int enable_slot(struct hotplug_slot *hotplug_slot)
272{ 292{
273 /* mis-use enable_slot for rescanning of the pci bus */ 293 /* mis-use enable_slot for rescanning of the pci bus */
274 pci_rescan(); 294 cancel_work_sync(&pci_rescan_work);
295 queue_work(dummyphp_wq, &pci_rescan_work);
275 return -ENODEV; 296 return -ENODEV;
276} 297}
277 298
@@ -306,6 +327,10 @@ static int disable_slot(struct hotplug_slot *slot)
306 err("Can't remove PCI devices with other PCI devices behind it yet.\n"); 327 err("Can't remove PCI devices with other PCI devices behind it yet.\n");
307 return -ENODEV; 328 return -ENODEV;
308 } 329 }
330 if (test_and_set_bit(0, &dslot->removed)) {
331 dbg("Slot already scheduled for removal\n");
332 return -ENODEV;
333 }
309 /* search for subfunctions and disable them first */ 334 /* search for subfunctions and disable them first */
310 if (!(dslot->dev->devfn & 7)) { 335 if (!(dslot->dev->devfn & 7)) {
311 for (func = 1; func < 8; func++) { 336 for (func = 1; func < 8; func++) {
@@ -328,8 +353,9 @@ static int disable_slot(struct hotplug_slot *slot)
328 /* remove the device from the pci core */ 353 /* remove the device from the pci core */
329 pci_remove_bus_device(dslot->dev); 354 pci_remove_bus_device(dslot->dev);
330 355
331 /* blow away this sysfs entry and other parts. */ 356 /* queue work item to blow away this sysfs entry and other parts. */
332 remove_slot(dslot); 357 INIT_WORK(&dslot->remove_work, remove_slot_worker);
358 queue_work(dummyphp_wq, &dslot->remove_work);
333 359
334 return 0; 360 return 0;
335} 361}
@@ -340,6 +366,7 @@ static void cleanup_slots (void)
340 struct list_head *next; 366 struct list_head *next;
341 struct dummy_slot *dslot; 367 struct dummy_slot *dslot;
342 368
369 destroy_workqueue(dummyphp_wq);
343 list_for_each_safe (tmp, next, &slot_list) { 370 list_for_each_safe (tmp, next, &slot_list) {
344 dslot = list_entry (tmp, struct dummy_slot, node); 371 dslot = list_entry (tmp, struct dummy_slot, node);
345 remove_slot(dslot); 372 remove_slot(dslot);
@@ -351,6 +378,10 @@ static int __init dummyphp_init(void)
351{ 378{
352 info(DRIVER_DESC "\n"); 379 info(DRIVER_DESC "\n");
353 380
381 dummyphp_wq = create_singlethread_workqueue(MY_NAME);
382 if (!dummyphp_wq)
383 return -ENOMEM;
384
354 return pci_scan_buses(); 385 return pci_scan_buses();
355} 386}
356 387
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index a90c28d0c69d..87b6b8b280e6 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -761,10 +761,13 @@ static void ibm_unconfigure_device(struct pci_func *func)
761 debug("func->device << 3 | 0x0 = %x\n", func->device << 3 | 0x0); 761 debug("func->device << 3 | 0x0 = %x\n", func->device << 3 | 0x0);
762 762
763 for (j = 0; j < 0x08; j++) { 763 for (j = 0; j < 0x08; j++) {
764 temp = pci_find_slot(func->busno, (func->device << 3) | j); 764 temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j);
765 if (temp) 765 if (temp) {
766 pci_remove_bus_device(temp); 766 pci_remove_bus_device(temp);
767 pci_dev_put(temp);
768 }
767 } 769 }
770 pci_dev_put(func->dev);
768} 771}
769 772
770/* 773/*
@@ -823,7 +826,7 @@ static int ibm_configure_device(struct pci_func *func)
823 if (!(bus_structure_fixup(func->busno))) 826 if (!(bus_structure_fixup(func->busno)))
824 flag = 1; 827 flag = 1;
825 if (func->dev == NULL) 828 if (func->dev == NULL)
826 func->dev = pci_find_slot(func->busno, 829 func->dev = pci_get_bus_and_slot(func->busno,
827 PCI_DEVFN(func->device, func->function)); 830 PCI_DEVFN(func->device, func->function));
828 831
829 if (func->dev == NULL) { 832 if (func->dev == NULL) {
@@ -836,7 +839,7 @@ static int ibm_configure_device(struct pci_func *func)
836 if (num) 839 if (num)
837 pci_bus_add_devices(bus); 840 pci_bus_add_devices(bus);
838 841
839 func->dev = pci_find_slot(func->busno, 842 func->dev = pci_get_bus_and_slot(func->busno,
840 PCI_DEVFN(func->device, func->function)); 843 PCI_DEVFN(func->device, func->function));
841 if (func->dev == NULL) { 844 if (func->dev == NULL) {
842 err("ERROR... : pci_dev still NULL\n"); 845 err("ERROR... : pci_dev still NULL\n");
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index 47bb0e1ff3fa..dd59a050260f 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -137,7 +137,7 @@ static int get_##name (struct hotplug_slot *slot, type *value) \
137 int retval = 0; \ 137 int retval = 0; \
138 if (try_module_get(ops->owner)) { \ 138 if (try_module_get(ops->owner)) { \
139 if (ops->get_##name) \ 139 if (ops->get_##name) \
140 retval = ops->get_##name (slot, value); \ 140 retval = ops->get_##name(slot, value); \
141 else \ 141 else \
142 *value = slot->info->name; \ 142 *value = slot->info->name; \
143 module_put(ops->owner); \ 143 module_put(ops->owner); \
@@ -625,7 +625,7 @@ int pci_hp_register (struct hotplug_slot *slot)
625 if ((slot->info == NULL) || (slot->ops == NULL)) 625 if ((slot->info == NULL) || (slot->ops == NULL))
626 return -EINVAL; 626 return -EINVAL;
627 if (slot->release == NULL) { 627 if (slot->release == NULL) {
628 dbg("Why are you trying to register a hotplug slot" 628 dbg("Why are you trying to register a hotplug slot "
629 "without a proper release function?\n"); 629 "without a proper release function?\n");
630 return -EINVAL; 630 return -EINVAL;
631 } 631 }
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 7959c222dc24..ca656b27a500 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -82,24 +82,18 @@ struct event_info {
82}; 82};
83 83
84struct controller { 84struct controller {
85 struct controller *next;
86 struct mutex crit_sect; /* critical section mutex */ 85 struct mutex crit_sect; /* critical section mutex */
87 struct mutex ctrl_lock; /* controller lock */ 86 struct mutex ctrl_lock; /* controller lock */
88 int num_slots; /* Number of slots on ctlr */ 87 int num_slots; /* Number of slots on ctlr */
89 int slot_num_inc; /* 1 or -1 */ 88 int slot_num_inc; /* 1 or -1 */
90 struct pci_dev *pci_dev; 89 struct pci_dev *pci_dev;
91 struct list_head slot_list; 90 struct list_head slot_list;
92 struct slot *slot;
93 struct hpc_ops *hpc_ops; 91 struct hpc_ops *hpc_ops;
94 wait_queue_head_t queue; /* sleep & wake process */ 92 wait_queue_head_t queue; /* sleep & wake process */
95 u8 bus;
96 u8 device;
97 u8 function;
98 u8 slot_device_offset; 93 u8 slot_device_offset;
99 u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */ 94 u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */
100 u8 slot_bus; /* Bus where the slots handled by this controller sit */ 95 u8 slot_bus; /* Bus where the slots handled by this controller sit */
101 u8 ctrlcap; 96 u8 ctrlcap;
102 u16 vendor_id;
103 u8 cap_base; 97 u8 cap_base;
104 struct timer_list poll_timer; 98 struct timer_list poll_timer;
105 volatile int cmd_busy; 99 volatile int cmd_busy;
@@ -161,6 +155,9 @@ extern int pciehp_configure_device(struct slot *p_slot);
161extern int pciehp_unconfigure_device(struct slot *p_slot); 155extern int pciehp_unconfigure_device(struct slot *p_slot);
162extern void pciehp_queue_pushbutton_work(struct work_struct *work); 156extern void pciehp_queue_pushbutton_work(struct work_struct *work);
163int pcie_init(struct controller *ctrl, struct pcie_device *dev); 157int pcie_init(struct controller *ctrl, struct pcie_device *dev);
158int pciehp_enable_slot(struct slot *p_slot);
159int pciehp_disable_slot(struct slot *p_slot);
160int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev);
164 161
165static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) 162static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
166{ 163{
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 6462ac3b405f..7f4836b8e71e 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -453,13 +453,9 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
453 453
454 pci_set_drvdata(pdev, ctrl); 454 pci_set_drvdata(pdev, ctrl);
455 455
456 ctrl->bus = pdev->bus->number; /* ctrl bus */ 456 dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
457 ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */ 457 __FUNCTION__, pdev->bus->number, PCI_SLOT(pdev->devfn),
458 458 PCI_FUNC(pdev->devfn), pdev->irq);
459 ctrl->device = PCI_SLOT(pdev->devfn);
460 ctrl->function = PCI_FUNC(pdev->devfn);
461 dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", __FUNCTION__,
462 ctrl->bus, ctrl->device, ctrl->function, pdev->irq);
463 459
464 /* Setup the slot information structures */ 460 /* Setup the slot information structures */
465 rc = init_slots(ctrl); 461 rc = init_slots(ctrl);
@@ -471,6 +467,11 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
471 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); 467 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
472 468
473 t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ 469 t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
470 if (value) {
471 rc = pciehp_enable_slot(t_slot);
472 if (rc) /* -ENODEV: shouldn't happen, but deal with it */
473 value = 0;
474 }
474 if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { 475 if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
475 rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ 476 rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
476 if (rc) 477 if (rc)
@@ -509,6 +510,24 @@ static int pciehp_suspend (struct pcie_device *dev, pm_message_t state)
509static int pciehp_resume (struct pcie_device *dev) 510static int pciehp_resume (struct pcie_device *dev)
510{ 511{
511 printk("%s ENTRY\n", __FUNCTION__); 512 printk("%s ENTRY\n", __FUNCTION__);
513 if (pciehp_force) {
514 struct pci_dev *pdev = dev->port;
515 struct controller *ctrl = pci_get_drvdata(pdev);
516 struct slot *t_slot;
517 u8 status;
518
519 /* reinitialize the chipset's event detection logic */
520 pcie_init_hardware_part2(ctrl, dev);
521
522 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
523
524 /* Check if slot is occupied */
525 t_slot->hpc_ops->get_adapter_status(t_slot, &status);
526 if (status)
527 pciehp_enable_slot(t_slot);
528 else
529 pciehp_disable_slot(t_slot);
530 }
512 return 0; 531 return 0;
513} 532}
514#endif 533#endif
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index f1e0966cee95..b23061c56115 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -37,8 +37,6 @@
37#include "pciehp.h" 37#include "pciehp.h"
38 38
39static void interrupt_event_handler(struct work_struct *work); 39static void interrupt_event_handler(struct work_struct *work);
40static int pciehp_enable_slot(struct slot *p_slot);
41static int pciehp_disable_slot(struct slot *p_slot);
42 40
43static int queue_interrupt_event(struct slot *p_slot, u32 event_type) 41static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
44{ 42{
@@ -197,12 +195,6 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
197 __FUNCTION__); 195 __FUNCTION__);
198 return; 196 return;
199 } 197 }
200 /*
201 * After turning power off, we must wait for at least
202 * 1 second before taking any action that relies on
203 * power having been removed from the slot/adapter.
204 */
205 msleep(1000);
206 } 198 }
207} 199}
208 200
@@ -215,15 +207,12 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
215 */ 207 */
216static int board_added(struct slot *p_slot) 208static int board_added(struct slot *p_slot)
217{ 209{
218 u8 hp_slot;
219 int retval = 0; 210 int retval = 0;
220 struct controller *ctrl = p_slot->ctrl; 211 struct controller *ctrl = p_slot->ctrl;
221 212
222 hp_slot = p_slot->device - ctrl->slot_device_offset;
223
224 dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n", 213 dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n",
225 __FUNCTION__, p_slot->device, 214 __FUNCTION__, p_slot->device,
226 ctrl->slot_device_offset, hp_slot); 215 ctrl->slot_device_offset, p_slot->hp_slot);
227 216
228 if (POWER_CTRL(ctrl->ctrlcap)) { 217 if (POWER_CTRL(ctrl->ctrlcap)) {
229 /* Power on slot */ 218 /* Power on slot */
@@ -281,8 +270,6 @@ err_exit:
281 */ 270 */
282static int remove_board(struct slot *p_slot) 271static int remove_board(struct slot *p_slot)
283{ 272{
284 u8 device;
285 u8 hp_slot;
286 int retval = 0; 273 int retval = 0;
287 struct controller *ctrl = p_slot->ctrl; 274 struct controller *ctrl = p_slot->ctrl;
288 275
@@ -290,11 +277,7 @@ static int remove_board(struct slot *p_slot)
290 if (retval) 277 if (retval)
291 return retval; 278 return retval;
292 279
293 device = p_slot->device; 280 dbg("In %s, hp_slot = %d\n", __FUNCTION__, p_slot->hp_slot);
294 hp_slot = p_slot->device - ctrl->slot_device_offset;
295 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
296
297 dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
298 281
299 if (POWER_CTRL(ctrl->ctrlcap)) { 282 if (POWER_CTRL(ctrl->ctrlcap)) {
300 /* power off slot */ 283 /* power off slot */
@@ -621,12 +604,6 @@ int pciehp_disable_slot(struct slot *p_slot)
621 mutex_unlock(&p_slot->ctrl->crit_sect); 604 mutex_unlock(&p_slot->ctrl->crit_sect);
622 return -EINVAL; 605 return -EINVAL;
623 } 606 }
624 /*
625 * After turning power off, we must wait for at least
626 * 1 second before taking any action that relies on
627 * power having been removed from the slot/adapter.
628 */
629 msleep(1000);
630 } 607 }
631 608
632 ret = remove_board(p_slot); 609 ret = remove_board(p_slot);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 06d025b8b13f..6eba9b2cfb90 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -636,15 +636,57 @@ static int hpc_power_on_slot(struct slot * slot)
636 return retval; 636 return retval;
637} 637}
638 638
639static inline int pcie_mask_bad_dllp(struct controller *ctrl)
640{
641 struct pci_dev *dev = ctrl->pci_dev;
642 int pos;
643 u32 reg;
644
645 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
646 if (!pos)
647 return 0;
648 pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
649 if (reg & PCI_ERR_COR_BAD_DLLP)
650 return 0;
651 reg |= PCI_ERR_COR_BAD_DLLP;
652 pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
653 return 1;
654}
655
656static inline void pcie_unmask_bad_dllp(struct controller *ctrl)
657{
658 struct pci_dev *dev = ctrl->pci_dev;
659 u32 reg;
660 int pos;
661
662 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
663 if (!pos)
664 return;
665 pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
666 if (!(reg & PCI_ERR_COR_BAD_DLLP))
667 return;
668 reg &= ~PCI_ERR_COR_BAD_DLLP;
669 pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
670}
671
639static int hpc_power_off_slot(struct slot * slot) 672static int hpc_power_off_slot(struct slot * slot)
640{ 673{
641 struct controller *ctrl = slot->ctrl; 674 struct controller *ctrl = slot->ctrl;
642 u16 slot_cmd; 675 u16 slot_cmd;
643 u16 cmd_mask; 676 u16 cmd_mask;
644 int retval = 0; 677 int retval = 0;
678 int changed;
645 679
646 dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); 680 dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
647 681
682 /*
683 * Set Bad DLLP Mask bit in Correctable Error Mask
684 * Register. This is the workaround against Bad DLLP error
685 * that sometimes happens during turning power off the slot
686 * which conforms to PCI Express 1.0a spec.
687 */
688 changed = pcie_mask_bad_dllp(ctrl);
689
648 slot_cmd = POWER_OFF; 690 slot_cmd = POWER_OFF;
649 cmd_mask = PWR_CTRL; 691 cmd_mask = PWR_CTRL;
650 /* 692 /*
@@ -674,6 +716,16 @@ static int hpc_power_off_slot(struct slot * slot)
674 dbg("%s: SLOTCTRL %x write cmd %x\n", 716 dbg("%s: SLOTCTRL %x write cmd %x\n",
675 __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); 717 __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
676 718
719 /*
720 * After turning power off, we must wait for at least 1 second
721 * before taking any action that relies on power having been
722 * removed from the slot/adapter.
723 */
724 msleep(1000);
725
726 if (changed)
727 pcie_unmask_bad_dllp(ctrl);
728
677 return retval; 729 return retval;
678} 730}
679 731
@@ -1067,13 +1119,143 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
1067} 1119}
1068#endif 1120#endif
1069 1121
1070int pcie_init(struct controller * ctrl, struct pcie_device *dev) 1122static int pcie_init_hardware_part1(struct controller *ctrl,
1123 struct pcie_device *dev)
1124{
1125 int rc;
1126 u16 temp_word;
1127 u32 slot_cap;
1128 u16 slot_status;
1129
1130 rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
1131 if (rc) {
1132 err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
1133 return -1;
1134 }
1135
1136 /* Mask Hot-plug Interrupt Enable */
1137 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
1138 if (rc) {
1139 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
1140 return -1;
1141 }
1142
1143 dbg("%s: SLOTCTRL %x value read %x\n",
1144 __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
1145 temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
1146 0x00;
1147
1148 rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
1149 if (rc) {
1150 err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
1151 return -1;
1152 }
1153
1154 rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
1155 if (rc) {
1156 err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
1157 return -1;
1158 }
1159
1160 temp_word = 0x1F; /* Clear all events */
1161 rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
1162 if (rc) {
1163 err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
1164 return -1;
1165 }
1166 return 0;
1167}
1168
1169int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
1071{ 1170{
1072 int rc; 1171 int rc;
1073 u16 temp_word; 1172 u16 temp_word;
1074 u16 cap_reg;
1075 u16 intr_enable = 0; 1173 u16 intr_enable = 0;
1076 u32 slot_cap; 1174 u32 slot_cap;
1175 u16 slot_status;
1176
1177 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
1178 if (rc) {
1179 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
1180 goto abort;
1181 }
1182
1183 intr_enable = intr_enable | PRSN_DETECT_ENABLE;
1184
1185 rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
1186 if (rc) {
1187 err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
1188 goto abort;
1189 }
1190
1191 if (ATTN_BUTTN(slot_cap))
1192 intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
1193
1194 if (POWER_CTRL(slot_cap))
1195 intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
1196
1197 if (MRL_SENS(slot_cap))
1198 intr_enable = intr_enable | MRL_DETECT_ENABLE;
1199
1200 temp_word = (temp_word & ~intr_enable) | intr_enable;
1201
1202 if (pciehp_poll_mode) {
1203 temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
1204 } else {
1205 temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
1206 }
1207
1208 /*
1209 * Unmask Hot-plug Interrupt Enable for the interrupt
1210 * notification mechanism case.
1211 */
1212 rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
1213 if (rc) {
1214 err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
1215 goto abort;
1216 }
1217 rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
1218 if (rc) {
1219 err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
1220 goto abort_disable_intr;
1221 }
1222
1223 temp_word = 0x1F; /* Clear all events */
1224 rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
1225 if (rc) {
1226 err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
1227 goto abort_disable_intr;
1228 }
1229
1230 if (pciehp_force) {
1231 dbg("Bypassing BIOS check for pciehp use on %s\n",
1232 pci_name(ctrl->pci_dev));
1233 } else {
1234 rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
1235 if (rc)
1236 goto abort_disable_intr;
1237 }
1238
1239 return 0;
1240
1241 /* We end up here for the many possible ways to fail this API. */
1242abort_disable_intr:
1243 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
1244 if (!rc) {
1245 temp_word &= ~(intr_enable | HP_INTR_ENABLE);
1246 rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
1247 }
1248 if (rc)
1249 err("%s : disabling interrupts failed\n", __FUNCTION__);
1250abort:
1251 return -1;
1252}
1253
1254int pcie_init(struct controller *ctrl, struct pcie_device *dev)
1255{
1256 int rc;
1257 u16 cap_reg;
1258 u32 slot_cap;
1077 int cap_base; 1259 int cap_base;
1078 u16 slot_status, slot_ctrl; 1260 u16 slot_status, slot_ctrl;
1079 struct pci_dev *pdev; 1261 struct pci_dev *pdev;
@@ -1084,9 +1266,10 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1084 dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n", 1266 dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
1085 __FUNCTION__, pdev->vendor, pdev->device); 1267 __FUNCTION__, pdev->vendor, pdev->device);
1086 1268
1087 if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) { 1269 cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
1270 if (cap_base == 0) {
1088 dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__); 1271 dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__);
1089 goto abort_free_ctlr; 1272 goto abort;
1090 } 1273 }
1091 1274
1092 ctrl->cap_base = cap_base; 1275 ctrl->cap_base = cap_base;
@@ -1096,7 +1279,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1096 rc = pciehp_readw(ctrl, CAPREG, &cap_reg); 1279 rc = pciehp_readw(ctrl, CAPREG, &cap_reg);
1097 if (rc) { 1280 if (rc) {
1098 err("%s: Cannot read CAPREG register\n", __FUNCTION__); 1281 err("%s: Cannot read CAPREG register\n", __FUNCTION__);
1099 goto abort_free_ctlr; 1282 goto abort;
1100 } 1283 }
1101 dbg("%s: CAPREG offset %x cap_reg %x\n", 1284 dbg("%s: CAPREG offset %x cap_reg %x\n",
1102 __FUNCTION__, ctrl->cap_base + CAPREG, cap_reg); 1285 __FUNCTION__, ctrl->cap_base + CAPREG, cap_reg);
@@ -1106,26 +1289,26 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1106 && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) { 1289 && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
1107 dbg("%s : This is not a root port or the port is not " 1290 dbg("%s : This is not a root port or the port is not "
1108 "connected to a slot\n", __FUNCTION__); 1291 "connected to a slot\n", __FUNCTION__);
1109 goto abort_free_ctlr; 1292 goto abort;
1110 } 1293 }
1111 1294
1112 rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap); 1295 rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
1113 if (rc) { 1296 if (rc) {
1114 err("%s: Cannot read SLOTCAP register\n", __FUNCTION__); 1297 err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
1115 goto abort_free_ctlr; 1298 goto abort;
1116 } 1299 }
1117 dbg("%s: SLOTCAP offset %x slot_cap %x\n", 1300 dbg("%s: SLOTCAP offset %x slot_cap %x\n",
1118 __FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap); 1301 __FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap);
1119 1302
1120 if (!(slot_cap & HP_CAP)) { 1303 if (!(slot_cap & HP_CAP)) {
1121 dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__); 1304 dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
1122 goto abort_free_ctlr; 1305 goto abort;
1123 } 1306 }
1124 /* For debugging purpose */ 1307 /* For debugging purpose */
1125 rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); 1308 rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
1126 if (rc) { 1309 if (rc) {
1127 err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); 1310 err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
1128 goto abort_free_ctlr; 1311 goto abort;
1129 } 1312 }
1130 dbg("%s: SLOTSTATUS offset %x slot_status %x\n", 1313 dbg("%s: SLOTSTATUS offset %x slot_status %x\n",
1131 __FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status); 1314 __FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status);
@@ -1133,7 +1316,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1133 rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); 1316 rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
1134 if (rc) { 1317 if (rc) {
1135 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); 1318 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
1136 goto abort_free_ctlr; 1319 goto abort;
1137 } 1320 }
1138 dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n", 1321 dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
1139 __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl); 1322 __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
@@ -1161,36 +1344,9 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1161 ctrl->first_slot = slot_cap >> 19; 1344 ctrl->first_slot = slot_cap >> 19;
1162 ctrl->ctrlcap = slot_cap & 0x0000007f; 1345 ctrl->ctrlcap = slot_cap & 0x0000007f;
1163 1346
1164 /* Mask Hot-plug Interrupt Enable */ 1347 rc = pcie_init_hardware_part1(ctrl, dev);
1165 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); 1348 if (rc)
1166 if (rc) { 1349 goto abort;
1167 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
1168 goto abort_free_ctlr;
1169 }
1170
1171 dbg("%s: SLOTCTRL %x value read %x\n",
1172 __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
1173 temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
1174 0x00;
1175
1176 rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
1177 if (rc) {
1178 err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
1179 goto abort_free_ctlr;
1180 }
1181
1182 rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
1183 if (rc) {
1184 err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
1185 goto abort_free_ctlr;
1186 }
1187
1188 temp_word = 0x1F; /* Clear all events */
1189 rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
1190 if (rc) {
1191 err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
1192 goto abort_free_ctlr;
1193 }
1194 1350
1195 if (pciehp_poll_mode) { 1351 if (pciehp_poll_mode) {
1196 /* Install interrupt polling timer. Start with 10 sec delay */ 1352 /* Install interrupt polling timer. Start with 10 sec delay */
@@ -1206,7 +1362,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1206 if (rc) { 1362 if (rc) {
1207 err("Can't get irq %d for the hotplug controller\n", 1363 err("Can't get irq %d for the hotplug controller\n",
1208 ctrl->pci_dev->irq); 1364 ctrl->pci_dev->irq);
1209 goto abort_free_ctlr; 1365 goto abort;
1210 } 1366 }
1211 } 1367 }
1212 dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number, 1368 dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
@@ -1224,82 +1380,16 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1224 } 1380 }
1225 } 1381 }
1226 1382
1227 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); 1383 rc = pcie_init_hardware_part2(ctrl, dev);
1228 if (rc) { 1384 if (rc == 0) {
1229 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); 1385 ctrl->hpc_ops = &pciehp_hpc_ops;
1230 goto abort_free_irq; 1386 return 0;
1231 } 1387 }
1232
1233 intr_enable = intr_enable | PRSN_DETECT_ENABLE;
1234
1235 if (ATTN_BUTTN(slot_cap))
1236 intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
1237
1238 if (POWER_CTRL(slot_cap))
1239 intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
1240
1241 if (MRL_SENS(slot_cap))
1242 intr_enable = intr_enable | MRL_DETECT_ENABLE;
1243
1244 temp_word = (temp_word & ~intr_enable) | intr_enable;
1245
1246 if (pciehp_poll_mode) {
1247 temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
1248 } else {
1249 temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
1250 }
1251
1252 /*
1253 * Unmask Hot-plug Interrupt Enable for the interrupt
1254 * notification mechanism case.
1255 */
1256 rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
1257 if (rc) {
1258 err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
1259 goto abort_free_irq;
1260 }
1261 rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
1262 if (rc) {
1263 err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
1264 goto abort_disable_intr;
1265 }
1266
1267 temp_word = 0x1F; /* Clear all events */
1268 rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
1269 if (rc) {
1270 err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
1271 goto abort_disable_intr;
1272 }
1273
1274 if (pciehp_force) {
1275 dbg("Bypassing BIOS check for pciehp use on %s\n",
1276 pci_name(ctrl->pci_dev));
1277 } else {
1278 rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
1279 if (rc)
1280 goto abort_disable_intr;
1281 }
1282
1283 ctrl->hpc_ops = &pciehp_hpc_ops;
1284
1285 return 0;
1286
1287 /* We end up here for the many possible ways to fail this API. */
1288abort_disable_intr:
1289 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
1290 if (!rc) {
1291 temp_word &= ~(intr_enable | HP_INTR_ENABLE);
1292 rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
1293 }
1294 if (rc)
1295 err("%s : disabling interrupts failed\n", __FUNCTION__);
1296
1297abort_free_irq: 1388abort_free_irq:
1298 if (pciehp_poll_mode) 1389 if (pciehp_poll_mode)
1299 del_timer_sync(&ctrl->poll_timer); 1390 del_timer_sync(&ctrl->poll_timer);
1300 else 1391 else
1301 free_irq(ctrl->pci_dev->irq, ctrl); 1392 free_irq(ctrl->pci_dev->irq, ctrl);
1302 1393abort:
1303abort_free_ctlr:
1304 return -1; 1394 return -1;
1305} 1395}
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index c424aded13fb..dd50713966d1 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -105,12 +105,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
105 } 105 }
106 106
107 /* Find Advanced Error Reporting Enhanced Capability */ 107 /* Find Advanced Error Reporting Enhanced Capability */
108 pos = 256; 108 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
109 do {
110 pci_read_config_dword(dev, pos, &reg32);
111 if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR)
112 break;
113 } while ((pos = PCI_EXT_CAP_NEXT(reg32)));
114 if (!pos) 109 if (!pos)
115 return; 110 return;
116 111
@@ -248,11 +243,15 @@ int pciehp_unconfigure_device(struct slot *p_slot)
248 u8 bctl = 0; 243 u8 bctl = 0;
249 u8 presence = 0; 244 u8 presence = 0;
250 struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; 245 struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
246 u16 command;
251 247
252 dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, 248 dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
253 p_slot->device); 249 p_slot->device);
250 ret = p_slot->hpc_ops->get_adapter_status(p_slot, &presence);
251 if (ret)
252 presence = 0;
254 253
255 for (j=0; j<8 ; j++) { 254 for (j = 0; j < 8; j++) {
256 struct pci_dev* temp = pci_get_slot(parent, 255 struct pci_dev* temp = pci_get_slot(parent,
257 (p_slot->device << 3) | j); 256 (p_slot->device << 3) | j);
258 if (!temp) 257 if (!temp)
@@ -263,21 +262,26 @@ int pciehp_unconfigure_device(struct slot *p_slot)
263 pci_dev_put(temp); 262 pci_dev_put(temp);
264 continue; 263 continue;
265 } 264 }
266 if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { 265 if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
267 ret = p_slot->hpc_ops->get_adapter_status(p_slot, 266 pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
268 &presence); 267 if (bctl & PCI_BRIDGE_CTL_VGA) {
269 if (!ret && presence) { 268 err("Cannot remove display device %s\n",
270 pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, 269 pci_name(temp));
271 &bctl); 270 pci_dev_put(temp);
272 if (bctl & PCI_BRIDGE_CTL_VGA) { 271 continue;
273 err("Cannot remove display device %s\n",
274 pci_name(temp));
275 pci_dev_put(temp);
276 continue;
277 }
278 } 272 }
279 } 273 }
280 pci_remove_bus_device(temp); 274 pci_remove_bus_device(temp);
275 /*
276 * Ensure that no new Requests will be generated from
277 * the device.
278 */
279 if (presence) {
280 pci_read_config_word(temp, PCI_COMMAND, &command);
281 command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
282 command |= PCI_COMMAND_INTX_DISABLE;
283 pci_write_config_word(temp, PCI_COMMAND, command);
284 }
281 pci_dev_put(temp); 285 pci_dev_put(temp);
282 } 286 }
283 /* 287 /*
@@ -288,4 +292,3 @@ int pciehp_unconfigure_device(struct slot *p_slot)
288 292
289 return rc; 293 return rc;
290} 294}
291
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index c822a779653f..7d5921b1ee78 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -74,7 +74,6 @@ struct slot {
74 u32 type; 74 u32 type;
75 u32 power_domain; 75 u32 power_domain;
76 char *name; 76 char *name;
77 char *location;
78 struct device_node *dn; 77 struct device_node *dn;
79 struct pci_bus *bus; 78 struct pci_bus *bus;
80 struct list_head *pci_devs; 79 struct list_head *pci_devs;
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 0de84533cd80..6571e9b4c2ec 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -64,19 +64,6 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state)
64 return rc; 64 return rc;
65} 65}
66 66
67static void set_slot_name(struct slot *slot)
68{
69 struct pci_bus *bus = slot->bus;
70 struct pci_dev *bridge;
71
72 bridge = bus->self;
73 if (bridge)
74 strcpy(slot->name, pci_name(bridge));
75 else
76 sprintf(slot->name, "%04x:%02x:00.0", pci_domain_nr(bus),
77 bus->number);
78}
79
80/** 67/**
81 * rpaphp_enable_slot - record slot state, config pci device 68 * rpaphp_enable_slot - record slot state, config pci device
82 * @slot: target &slot 69 * @slot: target &slot
@@ -115,7 +102,6 @@ int rpaphp_enable_slot(struct slot *slot)
115 info->adapter_status = EMPTY; 102 info->adapter_status = EMPTY;
116 slot->bus = bus; 103 slot->bus = bus;
117 slot->pci_devs = &bus->devices; 104 slot->pci_devs = &bus->devices;
118 set_slot_name(slot);
119 105
120 /* if there's an adapter in the slot, go add the pci devices */ 106 /* if there's an adapter in the slot, go add the pci devices */
121 if (state == PRESENT) { 107 if (state == PRESENT) {
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index d4ee8723fcb3..8ad3debb3794 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -33,23 +33,31 @@
33#include <asm/rtas.h> 33#include <asm/rtas.h>
34#include "rpaphp.h" 34#include "rpaphp.h"
35 35
36static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf) 36static ssize_t address_read_file (struct hotplug_slot *php_slot, char *buf)
37{ 37{
38 char *value; 38 int retval;
39 int retval = -ENOENT;
40 struct slot *slot = (struct slot *)php_slot->private; 39 struct slot *slot = (struct slot *)php_slot->private;
40 struct pci_bus *bus;
41 41
42 if (!slot) 42 if (!slot)
43 return retval; 43 return -ENOENT;
44
45 bus = slot->bus;
46 if (!bus)
47 return -ENOENT;
48
49 if (bus->self)
50 retval = sprintf(buf, pci_name(bus->self));
51 else
52 retval = sprintf(buf, "%04x:%02x:00.0",
53 pci_domain_nr(bus), bus->number);
44 54
45 value = slot->location;
46 retval = sprintf (buf, "%s\n", value);
47 return retval; 55 return retval;
48} 56}
49 57
50static struct hotplug_slot_attribute php_attr_location = { 58static struct hotplug_slot_attribute php_attr_address = {
51 .attr = {.name = "phy_location", .mode = S_IFREG | S_IRUGO}, 59 .attr = {.name = "address", .mode = S_IFREG | S_IRUGO},
52 .show = location_read_file, 60 .show = address_read_file,
53}; 61};
54 62
55/* free up the memory used by a slot */ 63/* free up the memory used by a slot */
@@ -64,7 +72,6 @@ void dealloc_slot_struct(struct slot *slot)
64 kfree(slot->hotplug_slot->info); 72 kfree(slot->hotplug_slot->info);
65 kfree(slot->hotplug_slot->name); 73 kfree(slot->hotplug_slot->name);
66 kfree(slot->hotplug_slot); 74 kfree(slot->hotplug_slot);
67 kfree(slot->location);
68 kfree(slot); 75 kfree(slot);
69} 76}
70 77
@@ -83,16 +90,13 @@ struct slot *alloc_slot_struct(struct device_node *dn,
83 GFP_KERNEL); 90 GFP_KERNEL);
84 if (!slot->hotplug_slot->info) 91 if (!slot->hotplug_slot->info)
85 goto error_hpslot; 92 goto error_hpslot;
86 slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL); 93 slot->hotplug_slot->name = kmalloc(strlen(drc_name) + 1, GFP_KERNEL);
87 if (!slot->hotplug_slot->name) 94 if (!slot->hotplug_slot->name)
88 goto error_info; 95 goto error_info;
89 slot->location = kmalloc(strlen(drc_name) + 1, GFP_KERNEL);
90 if (!slot->location)
91 goto error_name;
92 slot->name = slot->hotplug_slot->name; 96 slot->name = slot->hotplug_slot->name;
97 strcpy(slot->name, drc_name);
93 slot->dn = dn; 98 slot->dn = dn;
94 slot->index = drc_index; 99 slot->index = drc_index;
95 strcpy(slot->location, drc_name);
96 slot->power_domain = power_domain; 100 slot->power_domain = power_domain;
97 slot->hotplug_slot->private = slot; 101 slot->hotplug_slot->private = slot;
98 slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops; 102 slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops;
@@ -100,8 +104,6 @@ struct slot *alloc_slot_struct(struct device_node *dn,
100 104
101 return (slot); 105 return (slot);
102 106
103error_name:
104 kfree(slot->hotplug_slot->name);
105error_info: 107error_info:
106 kfree(slot->hotplug_slot->info); 108 kfree(slot->hotplug_slot->info);
107error_hpslot: 109error_hpslot:
@@ -133,8 +135,8 @@ int rpaphp_deregister_slot(struct slot *slot)
133 135
134 list_del(&slot->rpaphp_slot_list); 136 list_del(&slot->rpaphp_slot_list);
135 137
136 /* remove "phy_location" file */ 138 /* remove "address" file */
137 sysfs_remove_file(&php_slot->kobj, &php_attr_location.attr); 139 sysfs_remove_file(&php_slot->kobj, &php_attr_address.attr);
138 140
139 retval = pci_hp_deregister(php_slot); 141 retval = pci_hp_deregister(php_slot);
140 if (retval) 142 if (retval)
@@ -166,8 +168,8 @@ int rpaphp_register_slot(struct slot *slot)
166 return retval; 168 return retval;
167 } 169 }
168 170
169 /* create "phy_location" file */ 171 /* create "address" file */
170 retval = sysfs_create_file(&php_slot->kobj, &php_attr_location.attr); 172 retval = sysfs_create_file(&php_slot->kobj, &php_attr_address.attr);
171 if (retval) { 173 if (retval) {
172 err("sysfs_create_file failed with error %d\n", retval); 174 err("sysfs_create_file failed with error %d\n", retval);
173 goto sysfs_fail; 175 goto sysfs_fail;
@@ -175,8 +177,7 @@ int rpaphp_register_slot(struct slot *slot)
175 177
176 /* add slot to our internal list */ 178 /* add slot to our internal list */
177 list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head); 179 list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
178 info("Slot [%s](PCI location=%s) registered\n", slot->name, 180 info("Slot [%s] registered\n", slot->name);
179 slot->location);
180 return 0; 181 return 0;
181 182
182sysfs_fail: 183sysfs_fail:
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 5183a45d45b5..e8aa138128ce 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -597,7 +597,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
597 cleanup_slots(ctrl); 597 cleanup_slots(ctrl);
598 598
599 /* 599 /*
600 * Mask SERR and System Interrut generation 600 * Mask SERR and System Interrupt generation
601 */ 601 */
602 serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); 602 serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
603 serr_int |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK | 603 serr_int |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK |