Commit 5e19196c authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branch 'pci/aspm'

- Re-enable LTR in Downstream Ports after it has been disabled by reset or
  hotplug to allow use of ASPM L1.2 again and prevent Unsupported Request
  errors when Endpoint sends LTR messages (Mingchuang Qiao)

* pci/aspm:
  PCI: Re-enable Downstream Port LTR after reset or hotplug
parents 8d55770b e1b0d0bb
......@@ -1477,6 +1477,24 @@ static int pci_save_pcie_state(struct pci_dev *dev)
return 0;
}
void pci_bridge_reconfigure_ltr(struct pci_dev *dev)
{
#ifdef CONFIG_PCIEASPM
struct pci_dev *bridge;
u32 ctl;
bridge = pci_upstream_bridge(dev);
if (bridge && bridge->ltr_path) {
pcie_capability_read_dword(bridge, PCI_EXP_DEVCTL2, &ctl);
if (!(ctl & PCI_EXP_DEVCTL2_LTR_EN)) {
pci_dbg(bridge, "re-enabling LTR\n");
pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2,
PCI_EXP_DEVCTL2_LTR_EN);
}
}
#endif
}
static void pci_restore_pcie_state(struct pci_dev *dev)
{
int i = 0;
......@@ -1487,6 +1505,13 @@ static void pci_restore_pcie_state(struct pci_dev *dev)
if (!save_state)
return;
/*
* Downstream ports reset the LTR enable bit when link goes down.
* Check and re-configure the bit here before restoring device.
* PCIe r5.0, sec 7.5.3.16.
*/
pci_bridge_reconfigure_ltr(dev);
cap = (u16 *)&save_state->cap.data[0];
pcie_capability_write_word(dev, PCI_EXP_DEVCTL, cap[i++]);
pcie_capability_write_word(dev, PCI_EXP_LNKCTL, cap[i++]);
......
......@@ -125,6 +125,7 @@ void pci_msix_init(struct pci_dev *dev);
bool pci_bridge_d3_possible(struct pci_dev *dev);
void pci_bridge_d3_update(struct pci_dev *dev);
void pci_bridge_wait_for_secondary_bus(struct pci_dev *dev);
void pci_bridge_reconfigure_ltr(struct pci_dev *dev);
static inline void pci_wakeup_event(struct pci_dev *dev)
{
......
......@@ -2168,9 +2168,21 @@ static void pci_configure_ltr(struct pci_dev *dev)
* Complex and all intermediate Switches indicate support for LTR.
* PCIe r4.0, sec 6.18.
*/
if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT ||
((bridge = pci_upstream_bridge(dev)) &&
bridge->ltr_path)) {
if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) {
pcie_capability_set_word(dev, PCI_EXP_DEVCTL2,
PCI_EXP_DEVCTL2_LTR_EN);
dev->ltr_path = 1;
return;
}
/*
* If we're configuring a hot-added device, LTR was likely
* disabled in the upstream bridge, so re-enable it before enabling
* it in the new device.
*/
bridge = pci_upstream_bridge(dev);
if (bridge && bridge->ltr_path) {
pci_bridge_reconfigure_ltr(dev);
pcie_capability_set_word(dev, PCI_EXP_DEVCTL2,
PCI_EXP_DEVCTL2_LTR_EN);
dev->ltr_path = 1;
......
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