aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c33
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_pci.c2
-rw-r--r--drivers/pci/hotplug/cpcihp_generic.c2
-rw-r--r--drivers/pci/hotplug/cpqphp_pci.c2
-rw-r--r--drivers/pci/hotplug/fakephp.c2
-rw-r--r--drivers/pci/hotplug/ibmphp_core.c2
-rw-r--r--drivers/pci/hotplug/ibmphp_ebda.c6
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c133
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c2
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c2
-rw-r--r--drivers/pci/hotplug/sgi_hotplug.c2
-rw-r--r--drivers/pci/hotplug/shpchp_pci.c2
12 files changed, 137 insertions, 53 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 9ddf69e3bbef..806c44fa645a 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -800,20 +800,10 @@ static int __ref enable_device(struct acpiphp_slot *slot)
800 if (slot->flags & SLOT_ENABLED) 800 if (slot->flags & SLOT_ENABLED)
801 goto err_exit; 801 goto err_exit;
802 802
803 /* sanity check: dev should be NULL when hot-plugged in */
804 dev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0));
805 if (dev) {
806 /* This case shouldn't happen */
807 err("pci_dev structure already exists.\n");
808 pci_dev_put(dev);
809 retval = -1;
810 goto err_exit;
811 }
812
813 num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0)); 803 num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0));
814 if (num == 0) { 804 if (num == 0) {
815 err("No new device found\n"); 805 /* Maybe only part of funcs are added. */
816 retval = -1; 806 dbg("No new device found\n");
817 goto err_exit; 807 goto err_exit;
818 } 808 }
819 809
@@ -848,11 +838,16 @@ static int __ref enable_device(struct acpiphp_slot *slot)
848 838
849 pci_bus_add_devices(bus); 839 pci_bus_add_devices(bus);
850 840
841 slot->flags |= SLOT_ENABLED;
851 list_for_each_entry(func, &slot->funcs, sibling) { 842 list_for_each_entry(func, &slot->funcs, sibling) {
852 dev = pci_get_slot(bus, PCI_DEVFN(slot->device, 843 dev = pci_get_slot(bus, PCI_DEVFN(slot->device,
853 func->function)); 844 func->function));
854 if (!dev) 845 if (!dev) {
846 /* Do not set SLOT_ENABLED flag if some funcs
847 are not added. */
848 slot->flags &= (~SLOT_ENABLED);
855 continue; 849 continue;
850 }
856 851
857 if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE && 852 if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE &&
858 dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) { 853 dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) {
@@ -867,7 +862,6 @@ static int __ref enable_device(struct acpiphp_slot *slot)
867 pci_dev_put(dev); 862 pci_dev_put(dev);
868 } 863 }
869 864
870 slot->flags |= SLOT_ENABLED;
871 865
872 err_exit: 866 err_exit:
873 return retval; 867 return retval;
@@ -892,9 +886,12 @@ static int disable_device(struct acpiphp_slot *slot)
892{ 886{
893 struct acpiphp_func *func; 887 struct acpiphp_func *func;
894 struct pci_dev *pdev; 888 struct pci_dev *pdev;
889 struct pci_bus *bus = slot->bridge->pci_bus;
895 890
896 /* is this slot already disabled? */ 891 /* The slot will be enabled when func 0 is added, so check
897 if (!(slot->flags & SLOT_ENABLED)) 892 func 0 before disable the slot. */
893 pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0));
894 if (!pdev)
898 goto err_exit; 895 goto err_exit;
899 896
900 list_for_each_entry(func, &slot->funcs, sibling) { 897 list_for_each_entry(func, &slot->funcs, sibling) {
@@ -913,7 +910,7 @@ static int disable_device(struct acpiphp_slot *slot)
913 disable_bridges(pdev->subordinate); 910 disable_bridges(pdev->subordinate);
914 pci_disable_device(pdev); 911 pci_disable_device(pdev);
915 } 912 }
916 pci_remove_bus_device(pdev); 913 __pci_remove_bus_device(pdev);
917 pci_dev_put(pdev); 914 pci_dev_put(pdev);
918 } 915 }
919 } 916 }
@@ -1070,7 +1067,7 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
1070 res->end) { 1067 res->end) {
1071 /* Could not assign a required resources 1068 /* Could not assign a required resources
1072 * for this device, remove it */ 1069 * for this device, remove it */
1073 pci_remove_bus_device(dev); 1070 pci_stop_and_remove_bus_device(dev);
1074 break; 1071 break;
1075 } 1072 }
1076 } 1073 }
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
index 829c327cfb5e..ae853ccd0cd5 100644
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
@@ -341,7 +341,7 @@ int cpci_unconfigure_slot(struct slot* slot)
341 dev = pci_get_slot(slot->bus, 341 dev = pci_get_slot(slot->bus,
342 PCI_DEVFN(PCI_SLOT(slot->devfn), i)); 342 PCI_DEVFN(PCI_SLOT(slot->devfn), i));
343 if (dev) { 343 if (dev) {
344 pci_remove_bus_device(dev); 344 pci_stop_and_remove_bus_device(dev);
345 pci_dev_put(dev); 345 pci_dev_put(dev);
346 } 346 }
347 } 347 }
diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c
index fb3f84661bdc..81af764c629b 100644
--- a/drivers/pci/hotplug/cpcihp_generic.c
+++ b/drivers/pci/hotplug/cpcihp_generic.c
@@ -62,7 +62,7 @@
62#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) 62#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
63 63
64/* local variables */ 64/* local variables */
65static int debug; 65static bool debug;
66static char *bridge; 66static char *bridge;
67static u8 bridge_busnr; 67static u8 bridge_busnr;
68static u8 bridge_slot; 68static u8 bridge_slot;
diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c
index 6173b9a4544e..1c8494021a42 100644
--- a/drivers/pci/hotplug/cpqphp_pci.c
+++ b/drivers/pci/hotplug/cpqphp_pci.c
@@ -127,7 +127,7 @@ int cpqhp_unconfigure_device(struct pci_func* func)
127 struct pci_dev* temp = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, j)); 127 struct pci_dev* temp = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, j));
128 if (temp) { 128 if (temp) {
129 pci_dev_put(temp); 129 pci_dev_put(temp);
130 pci_remove_bus_device(temp); 130 pci_stop_and_remove_bus_device(temp);
131 } 131 }
132 } 132 }
133 return 0; 133 return 0;
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index 17d10e2e8fb6..a019c9a712be 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -40,7 +40,7 @@ static ssize_t legacy_show(struct kobject *kobj, struct attribute *attr,
40 40
41static void remove_callback(void *data) 41static void remove_callback(void *data)
42{ 42{
43 pci_remove_bus_device((struct pci_dev *)data); 43 pci_stop_and_remove_bus_device((struct pci_dev *)data);
44} 44}
45 45
46static ssize_t legacy_store(struct kobject *kobj, struct attribute *attr, 46static ssize_t legacy_store(struct kobject *kobj, struct attribute *attr,
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index 5506e0e8fbc0..4fda7e6a86a7 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -721,7 +721,7 @@ static void ibm_unconfigure_device(struct pci_func *func)
721 for (j = 0; j < 0x08; j++) { 721 for (j = 0; j < 0x08; j++) {
722 temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j); 722 temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j);
723 if (temp) { 723 if (temp) {
724 pci_remove_bus_device(temp); 724 pci_stop_and_remove_bus_device(temp);
725 pci_dev_put(temp); 725 pci_dev_put(temp);
726 } 726 }
727 } 727 }
diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c
index 2850e64dedae..714ca5c4ed50 100644
--- a/drivers/pci/hotplug/ibmphp_ebda.c
+++ b/drivers/pci/hotplug/ibmphp_ebda.c
@@ -368,8 +368,10 @@ int __init ibmphp_access_ebda (void)
368 debug ("rio blk id: %x\n", blk_id); 368 debug ("rio blk id: %x\n", blk_id);
369 369
370 rio_table_ptr = kzalloc(sizeof(struct rio_table_hdr), GFP_KERNEL); 370 rio_table_ptr = kzalloc(sizeof(struct rio_table_hdr), GFP_KERNEL);
371 if (!rio_table_ptr) 371 if (!rio_table_ptr) {
372 return -ENOMEM; 372 rc = -ENOMEM;
373 goto out;
374 }
373 rio_table_ptr->ver_num = readb (io_mem + offset); 375 rio_table_ptr->ver_num = readb (io_mem + offset);
374 rio_table_ptr->scal_count = readb (io_mem + offset + 1); 376 rio_table_ptr->scal_count = readb (io_mem + offset + 1);
375 rio_table_ptr->riodev_count = readb (io_mem + offset + 2); 377 rio_table_ptr->riodev_count = readb (io_mem + offset + 2);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index bcdbb1643621..a960faec1021 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -241,34 +241,79 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
241 return retval; 241 return retval;
242} 242}
243 243
244static inline int check_link_active(struct controller *ctrl) 244static bool check_link_active(struct controller *ctrl)
245{ 245{
246 u16 link_status; 246 bool ret = false;
247 u16 lnk_status;
247 248
248 if (pciehp_readw(ctrl, PCI_EXP_LNKSTA, &link_status)) 249 if (pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status))
249 return 0; 250 return ret;
250 return !!(link_status & PCI_EXP_LNKSTA_DLLLA); 251
252 ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA);
253
254 if (ret)
255 ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status);
256
257 return ret;
251} 258}
252 259
253static void pcie_wait_link_active(struct controller *ctrl) 260static void __pcie_wait_link_active(struct controller *ctrl, bool active)
254{ 261{
255 int timeout = 1000; 262 int timeout = 1000;
256 263
257 if (check_link_active(ctrl)) 264 if (check_link_active(ctrl) == active)
258 return; 265 return;
259 while (timeout > 0) { 266 while (timeout > 0) {
260 msleep(10); 267 msleep(10);
261 timeout -= 10; 268 timeout -= 10;
262 if (check_link_active(ctrl)) 269 if (check_link_active(ctrl) == active)
263 return; 270 return;
264 } 271 }
265 ctrl_dbg(ctrl, "Data Link Layer Link Active not set in 1000 msec\n"); 272 ctrl_dbg(ctrl, "Data Link Layer Link Active not %s in 1000 msec\n",
273 active ? "set" : "cleared");
274}
275
276static void pcie_wait_link_active(struct controller *ctrl)
277{
278 __pcie_wait_link_active(ctrl, true);
279}
280
281static void pcie_wait_link_not_active(struct controller *ctrl)
282{
283 __pcie_wait_link_active(ctrl, false);
284}
285
286static bool pci_bus_check_dev(struct pci_bus *bus, int devfn)
287{
288 u32 l;
289 int count = 0;
290 int delay = 1000, step = 20;
291 bool found = false;
292
293 do {
294 found = pci_bus_read_dev_vendor_id(bus, devfn, &l, 0);
295 count++;
296
297 if (found)
298 break;
299
300 msleep(step);
301 delay -= step;
302 } while (delay > 0);
303
304 if (count > 1 && pciehp_debug)
305 printk(KERN_DEBUG "pci %04x:%02x:%02x.%d id reading try %d times with interval %d ms to get %08x\n",
306 pci_domain_nr(bus), bus->number, PCI_SLOT(devfn),
307 PCI_FUNC(devfn), count, step, l);
308
309 return found;
266} 310}
267 311
268int pciehp_check_link_status(struct controller *ctrl) 312int pciehp_check_link_status(struct controller *ctrl)
269{ 313{
270 u16 lnk_status; 314 u16 lnk_status;
271 int retval = 0; 315 int retval = 0;
316 bool found = false;
272 317
273 /* 318 /*
274 * Data Link Layer Link Active Reporting must be capable for 319 * Data Link Layer Link Active Reporting must be capable for
@@ -280,13 +325,10 @@ int pciehp_check_link_status(struct controller *ctrl)
280 else 325 else
281 msleep(1000); 326 msleep(1000);
282 327
283 /* 328 /* wait 100ms before read pci conf, and try in 1s */
284 * Need to wait for 1000 ms after Data Link Layer Link Active 329 msleep(100);
285 * (DLLLA) bit reads 1b before sending configuration request. 330 found = pci_bus_check_dev(ctrl->pcie->port->subordinate,
286 * We need it before checking Link Training (LT) bit becuase 331 PCI_DEVFN(0, 0));
287 * LT is still set even after DLLLA bit is set on some platform.
288 */
289 msleep(1000);
290 332
291 retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); 333 retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
292 if (retval) { 334 if (retval) {
@@ -302,19 +344,50 @@ int pciehp_check_link_status(struct controller *ctrl)
302 return retval; 344 return retval;
303 } 345 }
304 346
305 /*
306 * If the port supports Link speeds greater than 5.0 GT/s, we
307 * must wait for 100 ms after Link training completes before
308 * sending configuration request.
309 */
310 if (ctrl->pcie->port->subordinate->max_bus_speed > PCIE_SPEED_5_0GT)
311 msleep(100);
312
313 pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status); 347 pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
314 348
349 if (!found && !retval)
350 retval = -1;
351
315 return retval; 352 return retval;
316} 353}
317 354
355static int __pciehp_link_set(struct controller *ctrl, bool enable)
356{
357 u16 lnk_ctrl;
358 int retval = 0;
359
360 retval = pciehp_readw(ctrl, PCI_EXP_LNKCTL, &lnk_ctrl);
361 if (retval) {
362 ctrl_err(ctrl, "Cannot read LNKCTRL register\n");
363 return retval;
364 }
365
366 if (enable)
367 lnk_ctrl &= ~PCI_EXP_LNKCTL_LD;
368 else
369 lnk_ctrl |= PCI_EXP_LNKCTL_LD;
370
371 retval = pciehp_writew(ctrl, PCI_EXP_LNKCTL, lnk_ctrl);
372 if (retval) {
373 ctrl_err(ctrl, "Cannot write LNKCTRL register\n");
374 return retval;
375 }
376 ctrl_dbg(ctrl, "%s: lnk_ctrl = %x\n", __func__, lnk_ctrl);
377
378 return retval;
379}
380
381static int pciehp_link_enable(struct controller *ctrl)
382{
383 return __pciehp_link_set(ctrl, true);
384}
385
386static int pciehp_link_disable(struct controller *ctrl)
387{
388 return __pciehp_link_set(ctrl, false);
389}
390
318int pciehp_get_attention_status(struct slot *slot, u8 *status) 391int pciehp_get_attention_status(struct slot *slot, u8 *status)
319{ 392{
320 struct controller *ctrl = slot->ctrl; 393 struct controller *ctrl = slot->ctrl;
@@ -533,6 +606,10 @@ int pciehp_power_on_slot(struct slot * slot)
533 ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, 606 ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
534 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); 607 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
535 608
609 retval = pciehp_link_enable(ctrl);
610 if (retval)
611 ctrl_err(ctrl, "%s: Can not enable the link!\n", __func__);
612
536 return retval; 613 return retval;
537} 614}
538 615
@@ -543,6 +620,14 @@ int pciehp_power_off_slot(struct slot * slot)
543 u16 cmd_mask; 620 u16 cmd_mask;
544 int retval; 621 int retval;
545 622
623 /* Disable the link at first */
624 pciehp_link_disable(ctrl);
625 /* wait the link is down */
626 if (ctrl->link_active_reporting)
627 pcie_wait_link_not_active(ctrl);
628 else
629 msleep(1000);
630
546 slot_cmd = POWER_OFF; 631 slot_cmd = POWER_OFF;
547 cmd_mask = PCI_EXP_SLTCTL_PCC; 632 cmd_mask = PCI_EXP_SLTCTL_PCC;
548 retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); 633 retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index a4031dfe938e..47d9dc06b109 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -141,7 +141,7 @@ int pciehp_unconfigure_device(struct slot *p_slot)
141 break; 141 break;
142 } 142 }
143 } 143 }
144 pci_remove_bus_device(temp); 144 pci_stop_and_remove_bus_device(temp);
145 /* 145 /*
146 * Ensure that no new Requests will be generated from 146 * Ensure that no new Requests will be generated from
147 * the device. 147 * the device.
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index c56a9413e1af..1e117c2a3cad 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -389,7 +389,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
389 BUG_ON(!bus->self); 389 BUG_ON(!bus->self);
390 pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self)); 390 pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self));
391 eeh_remove_bus_device(bus->self); 391 eeh_remove_bus_device(bus->self);
392 pci_remove_bus_device(bus->self); 392 pci_stop_and_remove_bus_device(bus->self);
393 393
394 return 0; 394 return 0;
395} 395}
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
index 72d507b6a2aa..de573113c102 100644
--- a/drivers/pci/hotplug/sgi_hotplug.c
+++ b/drivers/pci/hotplug/sgi_hotplug.c
@@ -554,7 +554,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
554 PCI_FUNC(func))); 554 PCI_FUNC(func)));
555 if (dev) { 555 if (dev) {
556 sn_bus_free_data(dev); 556 sn_bus_free_data(dev);
557 pci_remove_bus_device(dev); 557 pci_stop_and_remove_bus_device(dev);
558 pci_dev_put(dev); 558 pci_dev_put(dev);
559 } 559 }
560 } 560 }
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
index a2ccfcd3c298..df7e4bfadae3 100644
--- a/drivers/pci/hotplug/shpchp_pci.c
+++ b/drivers/pci/hotplug/shpchp_pci.c
@@ -124,7 +124,7 @@ int shpchp_unconfigure_device(struct slot *p_slot)
124 break; 124 break;
125 } 125 }
126 } 126 }
127 pci_remove_bus_device(temp); 127 pci_stop_and_remove_bus_device(temp);
128 pci_dev_put(temp); 128 pci_dev_put(temp);
129 } 129 }
130 return rc; 130 return rc;