[Skiboot] [PATCH 3/3] core/pci: Fix access non-existing registers on disabling cmpl timeout
Benjamin Herrenschmidt
benh at kernel.crashing.org
Thu Jun 15 15:46:41 AEST 2017
On Fri, 2017-05-26 at 11:53 +1000, Gavin Shan wrote:
> The PCIe transaction timeout is disabled if the capability is claimed
> in register PCIECAP_EXP_DCAP2, meaning we read it unconditionally.
> However, the reigster can be invalid if PCIe capability version isn't
> bigger than 1. It potentially causes pending (hanged) PCIe transaction.
>
> This fixes the issue by check the cached PCIe capability version. We
> won't touch register PCIECAP_EXP_DCAP2 and PCICAP_EXP_DCTL2 if PCIe
> capability version isn't bigger than 1. The limitation isn't applied
> to P7/P8/P9's root port as we clearly know those registers are valid
> there.
> Signed-off-by: Gavin Shan <gwshan at linux.vnet.ibm.com>
> ---
> core/pci.c | 16 +++++++++++-----
> 1 file changed, 11 insertions(+), 5 deletions(-)
>
> diff --git a/core/pci.c b/core/pci.c
> index 29c3df6..f173cc2 100644
> --- a/core/pci.c
> +++ b/core/pci.c
> @@ -162,8 +162,6 @@ static void pci_init_pcie_cap(struct phb *phb, struct pci_device *pd)
> return;
> }
>
> - pci_set_cap(pd, PCI_CFG_CAP_ID_EXP, ecap, 0ul, false);
> -
> /*
> * XXX We observe a problem on some PLX switches where one
> * of the downstream ports appears as an upstream port, we
> @@ -174,9 +172,15 @@ static void pci_init_pcie_cap(struct phb *phb, struct pci_device *pd)
> if (pd->parent && pd->parent->dev_type == PCIE_TYPE_SWITCH_UPPORT &&
> pd->vdid == 0x874810b5 && pd->dev_type == PCIE_TYPE_SWITCH_UPPORT) {
> PCIDBG(phb, pd->bdfn, "Fixing up bad PLX downstream port !\n");
> +
> + reg &= ~PCICAP_EXP_CAP_TYPE;
> + reg |= PCIE_TYPE_SWITCH_DNPORT;
> pd->dev_type = PCIE_TYPE_SWITCH_DNPORT;
> }
>
> + /* Set PCIe capability */
> + pci_set_cap(pd, PCI_CFG_CAP_ID_EXP, ecap, reg, false);
Why would you or "PCIE_TYPE_SWITCH_DNPORT" ?
The cap cache should just contain the offsets. The versions can be
read explicitely. If you want to cache the versions do a separate
array.
The above is very confusing. That cap "Data" need to die. A generic
untyped place holder is a bad thing.
> /* XXX Handle ARI */
> if (pd->dev_type == PCIE_TYPE_SWITCH_DNPORT ||
> pd->dev_type == PCIE_TYPE_ROOT_PORT)
> @@ -833,11 +837,13 @@ static int pci_configure_mps(struct phb *phb,
>
> static void pci_disable_completion_timeout(struct phb *phb, struct pci_device *pd)
> {
> - uint32_t ecap;
> - uint32_t val;
> + uint32_t ecap, val;
> + uint16_t ecap_data;
>
> /* PCIE capability required */
> - if (!pci_has_cap(pd, PCI_CFG_CAP_ID_EXP, false))
> + ecap_data = (uint16_t)pci_cap_data(pd, PCI_CFG_CAP_ID_EXP, false);
> + if (!pci_has_cap(pd, PCI_CFG_CAP_ID_EXP, false) ||
> + (ecap_data & PCICAP_EXP_CAP_VERSION) <= 1)
> return;
Just read the capability version off the HW here.
>
> /* Check if it has capability to disable completion timeout */
More information about the Skiboot
mailing list