aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/pciehp_hpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug/pciehp_hpc.c')
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c133
1 files changed, 109 insertions, 24 deletions
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index bcdbb164362..a960faec102 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);