[Skiboot] [PATCH 3/3] core/pci: Fix access non-existing registers on disabling cmpl timeout
Gavin Shan
gwshan at linux.vnet.ibm.com
Mon Jun 19 13:39:54 AEST 2017
On Thu, Jun 15, 2017 at 03:46:41PM +1000, Benjamin Herrenschmidt wrote:
>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.
>
Ok, It's going to die in v2.
>> /* 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.
Yes, Will do in v2.
>>
>> /* Check if it has capability to disable completion timeout */
Cheers,
Gavin
More information about the Skiboot
mailing list