提交 37877b1e 编写于 作者: K Keith Busch 提交者: Yang Yingliang

Intel:PCI: Make link active reporting detection generic

mainline inclusion
from mainline-v4.20-rc1
commit f0157160
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I47H3V
CVE: NA

--------------------------------

commit f0157160 upstream.
Backport summary: for 4.19 kernel ICX PCIe Gen4 support.

The spec has timing requirements when waiting for a link to become active
after a conventional reset.  Implement those hard delays when waiting for
an active link so pciehp and dpc drivers don't need to duplicate this.

For devices that don't support data link layer active reporting, wait the
fixed time recommended by the PCIe spec.
Signed-off-by: NKeith Busch <keith.busch@intel.com>
[bhelgaas: changelog]
Signed-off-by: NBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: NSinan Kaya <okaya@kernel.org>
(cherry picked from commit f0157160)
Signed-off-by: NEthan Zhao <haifeng.zhao@intel.com>

Conflicts: drivers/pci/hotplug/pciehp.h
Signed-off-by: NJackie Liu <liuyun01@kylinos.cn>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
Reviewed-by: NXiongfeng Wang <wangxiongfeng2@huawei.com>
Reviewed-by: NXie XiuQi <xiexiuqi@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 2a7ed39e
...@@ -212,13 +212,6 @@ bool pciehp_check_link_active(struct controller *ctrl) ...@@ -212,13 +212,6 @@ bool pciehp_check_link_active(struct controller *ctrl)
return ret; return ret;
} }
static void pcie_wait_link_active(struct controller *ctrl)
{
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)
{ {
u32 l; u32 l;
...@@ -251,18 +244,9 @@ int pciehp_check_link_status(struct controller *ctrl) ...@@ -251,18 +244,9 @@ int pciehp_check_link_status(struct controller *ctrl)
bool found; bool found;
u16 lnk_status; u16 lnk_status;
/* if (!pcie_wait_for_link(pdev, true))
* Data Link Layer Link Active Reporting must be capable for return -1;
* 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, found = pci_bus_check_dev(ctrl->pcie->port->subordinate,
PCI_DEVFN(0, 0)); PCI_DEVFN(0, 0));
...@@ -972,8 +956,6 @@ struct controller *pcie_init(struct pcie_device *dev) ...@@ -972,8 +956,6 @@ struct controller *pcie_init(struct pcie_device *dev)
/* Check if Data Link Layer Link Active Reporting is implemented */ /* Check if Data Link Layer Link Active Reporting is implemented */
pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap); pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap);
if (link_cap & PCI_EXP_LNKCAP_DLLLARC)
ctrl->link_active_reporting = 1;
/* Clear all remaining event bits in Slot Status register. */ /* Clear all remaining event bits in Slot Status register. */
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
......
...@@ -4566,21 +4566,42 @@ bool pcie_wait_for_link(struct pci_dev *pdev, bool active) ...@@ -4566,21 +4566,42 @@ bool pcie_wait_for_link(struct pci_dev *pdev, bool active)
bool ret; bool ret;
u16 lnk_status; u16 lnk_status;
/*
* Some controllers might not implement link active reporting. In this
* case, we wait for 1000 + 100 ms.
*/
if (!pdev->link_active_reporting) {
msleep(1100);
return true;
}
/*
* PCIe r4.0 sec 6.6.1, a component must enter LTSSM Detect within 20ms,
* after which we should expect an link active if the reset was
* successful. If so, software must wait a minimum 100ms before sending
* configuration requests to devices downstream this port.
*
* If the link fails to activate, either the device was physically
* removed or the link is permanently failed.
*/
if (active)
msleep(20);
for (;;) { for (;;) {
pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);
ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA); ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA);
if (ret == active) if (ret == active)
return true; break;
if (timeout <= 0) if (timeout <= 0)
break; break;
msleep(10); msleep(10);
timeout -= 10; timeout -= 10;
} }
if (active && ret)
msleep(100);
else if (ret != active)
pci_info(pdev, "Data Link Layer Link Active not %s in 1000 msec\n", pci_info(pdev, "Data Link Layer Link Active not %s in 1000 msec\n",
active ? "set" : "cleared"); active ? "set" : "cleared");
return ret == active;
return false;
} }
void pci_reset_secondary_bus(struct pci_dev *dev) void pci_reset_secondary_bus(struct pci_dev *dev)
......
...@@ -140,10 +140,12 @@ static pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) ...@@ -140,10 +140,12 @@ static pci_ers_result_t dpc_reset_link(struct pci_dev *pdev)
pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS,
PCI_EXP_DPC_STATUS_TRIGGER); PCI_EXP_DPC_STATUS_TRIGGER);
if (!pcie_wait_for_link(pdev, true))
return PCI_ERS_RESULT_DISCONNECT;
return PCI_ERS_RESULT_RECOVERED; return PCI_ERS_RESULT_RECOVERED;
} }
static void dpc_process_rp_pio_error(struct dpc_dev *dpc) static void dpc_process_rp_pio_error(struct dpc_dev *dpc)
{ {
struct device *dev = &dpc->dev->device; struct device *dev = &dpc->dev->device;
......
...@@ -809,6 +809,7 @@ static void pci_set_bus_speed(struct pci_bus *bus) ...@@ -809,6 +809,7 @@ static void pci_set_bus_speed(struct pci_bus *bus)
pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap); pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap);
bus->max_bus_speed = pcie_link_speed[linkcap & PCI_EXP_LNKCAP_SLS]; bus->max_bus_speed = pcie_link_speed[linkcap & PCI_EXP_LNKCAP_SLS];
bridge->link_active_reporting = !!(linkcap & PCI_EXP_LNKCAP_DLLLARC);
pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta); pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta);
pcie_update_link_speed(bus, linksta); pcie_update_link_speed(bus, linksta);
......
...@@ -411,6 +411,7 @@ struct pci_dev { ...@@ -411,6 +411,7 @@ struct pci_dev {
unsigned int has_secondary_link:1; unsigned int has_secondary_link:1;
unsigned int non_compliant_bars:1; /* Broken BARs; ignore them */ unsigned int non_compliant_bars:1; /* Broken BARs; ignore them */
unsigned int is_probed:1; /* Device probing in progress */ unsigned int is_probed:1; /* Device probing in progress */
unsigned int link_active_reporting:1;/* Device capable of reporting link active */
pci_dev_flags_t dev_flags; pci_dev_flags_t dev_flags;
atomic_t enable_cnt; /* pci_enable_device has been called */ atomic_t enable_cnt; /* pci_enable_device has been called */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册