Commit 9f5a70f1 authored by Oza Pawandeep's avatar Oza Pawandeep Committed by Bjorn Helgaas

PCI: Add generic pcie_wait_for_link() interface

Clients such as hotplug and Downstream Port Containment (DPC) both need to
wait until a link becomes active or inactive.

Add a generic pcie_wait_link_active() interface and use it instead of
duplicating the code.
Signed-off-by: default avatarOza Pawandeep <poza@codeaurora.org>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarKeith Busch <keith.busch@intel.com>
parent 2af8641b
...@@ -231,25 +231,11 @@ bool pciehp_check_link_active(struct controller *ctrl) ...@@ -231,25 +231,11 @@ bool pciehp_check_link_active(struct controller *ctrl)
return ret; return ret;
} }
static void __pcie_wait_link_active(struct controller *ctrl, bool active)
{
int timeout = 1000;
if (pciehp_check_link_active(ctrl) == active)
return;
while (timeout > 0) {
msleep(10);
timeout -= 10;
if (pciehp_check_link_active(ctrl) == active)
return;
}
ctrl_dbg(ctrl, "Data Link Layer Link Active not %s in 1000 msec\n",
active ? "set" : "cleared");
}
static void pcie_wait_link_active(struct controller *ctrl) static void pcie_wait_link_active(struct controller *ctrl)
{ {
__pcie_wait_link_active(ctrl, true); struct pci_dev *pdev = ctrl_dev(ctrl);
pcie_wait_for_link(pdev, true);
} }
static bool pci_bus_check_dev(struct pci_bus *bus, int devfn) static bool pci_bus_check_dev(struct pci_bus *bus, int devfn)
......
...@@ -4138,6 +4138,35 @@ static int pci_pm_reset(struct pci_dev *dev, int probe) ...@@ -4138,6 +4138,35 @@ static int pci_pm_reset(struct pci_dev *dev, int probe)
return pci_dev_wait(dev, "PM D3->D0", PCIE_RESET_READY_POLL_MS); return pci_dev_wait(dev, "PM D3->D0", PCIE_RESET_READY_POLL_MS);
} }
/**
* pcie_wait_for_link - Wait until link is active or inactive
* @pdev: Bridge device
* @active: waiting for active or inactive?
*
* Use this to wait till link becomes active or inactive.
*/
bool pcie_wait_for_link(struct pci_dev *pdev, bool active)
{
int timeout = 1000;
bool ret;
u16 lnk_status;
for (;;) {
pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);
ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA);
if (ret == active)
return true;
if (timeout <= 0)
break;
msleep(10);
timeout -= 10;
}
pci_info(pdev, "Data Link Layer Link Active not %s in 1000 msec\n",
active ? "set" : "cleared");
return false;
}
void pci_reset_secondary_bus(struct pci_dev *dev) void pci_reset_secondary_bus(struct pci_dev *dev)
{ {
......
...@@ -353,6 +353,7 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev, ...@@ -353,6 +353,7 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
void pci_enable_acs(struct pci_dev *dev); void pci_enable_acs(struct pci_dev *dev);
bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
#ifdef CONFIG_PCIEASPM #ifdef CONFIG_PCIEASPM
void pcie_aspm_init_link_state(struct pci_dev *pdev); void pcie_aspm_init_link_state(struct pci_dev *pdev);
void pcie_aspm_exit_link_state(struct pci_dev *pdev); void pcie_aspm_exit_link_state(struct pci_dev *pdev);
......
...@@ -68,19 +68,9 @@ static int dpc_wait_rp_inactive(struct dpc_dev *dpc) ...@@ -68,19 +68,9 @@ static int dpc_wait_rp_inactive(struct dpc_dev *dpc)
static void dpc_wait_link_inactive(struct dpc_dev *dpc) static void dpc_wait_link_inactive(struct dpc_dev *dpc)
{ {
unsigned long timeout = jiffies + HZ;
struct pci_dev *pdev = dpc->dev->port; struct pci_dev *pdev = dpc->dev->port;
struct device *dev = &dpc->dev->device;
u16 lnk_status;
pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); pcie_wait_for_link(pdev, false);
while (lnk_status & PCI_EXP_LNKSTA_DLLLA &&
!time_after(jiffies, timeout)) {
msleep(10);
pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);
}
if (lnk_status & PCI_EXP_LNKSTA_DLLLA)
dev_warn(dev, "Link state not disabled for DPC event\n");
} }
static void dpc_work(struct work_struct *work) static void dpc_work(struct work_struct *work)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment