int pciehp_power_on_slot(struct slot * slot) { struct controller *ctrl = slot->ctrl; u16 slot_cmd; u16 cmd_mask; u16 slot_status; u16 lnk_status; int retval = 0; /* Clear sticky power-fault bit from previous power failures */ retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); if (retval) { ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", __func__); return retval; } slot_status &= PCI_EXP_SLTSTA_PFD; if (slot_status) { retval = pciehp_writew(ctrl, PCI_EXP_SLTSTA, slot_status); if (retval) { ctrl_err(ctrl, "%s: Cannot write to SLOTSTATUS register\n", __func__); return retval; } } ctrl->power_fault_detected = 0; slot_cmd = POWER_ON; cmd_mask = PCI_EXP_SLTCTL_PCC; retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); if (retval) { ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd); return retval; } ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); if (retval) { ctrl_err(ctrl, "%s: Cannot read LNKSTA register\n", __func__); return retval; } pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status); return retval; }
static irqreturn_t pcie_bw_notification_irq(int irq, void *context) { struct pcie_device *srv = context; struct pci_dev *port = srv->port; u16 link_status, events; int ret; ret = pcie_capability_read_word(port, PCI_EXP_LNKSTA, &link_status); events = link_status & PCI_EXP_LNKSTA_LBMS; if (ret != PCIBIOS_SUCCESSFUL || !events) return IRQ_NONE; pcie_capability_write_word(port, PCI_EXP_LNKSTA, events); pcie_update_link_speed(port->subordinate, link_status); return IRQ_WAKE_THREAD; }
int pciehp_check_link_status(struct controller *ctrl) { u16 lnk_status; int retval = 0; bool found = false; /* * Data Link Layer Link Active Reporting must be capable for * hot-plug capable downstream port. But old controller might * not implement it. In this case, we wait for 1000 ms. */ if (ctrl->link_active_reporting) pcie_wait_link_active(ctrl); else msleep(1000); /* wait 100ms before read pci conf, and try in 1s */ msleep(100); found = pci_bus_check_dev(ctrl->pcie->port->subordinate, PCI_DEVFN(0, 0)); retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); if (retval) { ctrl_err(ctrl, "Cannot read LNKSTATUS register\n"); return retval; } ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status); if ((lnk_status & PCI_EXP_LNKSTA_LT) || !(lnk_status & PCI_EXP_LNKSTA_NLW)) { ctrl_err(ctrl, "Link Training Error occurs \n"); retval = -1; return retval; } pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status); if (!found && !retval) retval = -1; return retval; }