Re: [PATCH v4 3/3] PCI: Add CRS handling to pci_dev_wait()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 2021-09-13 at 11:07 -0500, Bjorn Helgaas wrote:
> 
> 1) It sounds like this *might* be a workaround for a device defect?
>    Should we infer that there's a device where:
> 
>     - We reset the device
>     - We read PCI_COMMAND until it is not ~0, for up to 60 seconds
>     - The device returns CRS status for each read, until ...
>     - The platform hardware times out before 60 seconds and fails the
>       transaction, causing a system crash?

Yes. As detailed in my other reply (which raced with this mail), I
implemented this patch because I encountered a device (and a platform)
that behaved exactly as described.

>    But reading PCI_VENDOR_ID instead of PCI_COMMAND somehow avoids the
>    platform timeout?

Correct. More specifically, that "somehow" is the CRS SV mechanism
standardized by the PCIe specification. This mechanism relies
specifically on the target offset being PCI_VENDOR_ID.

> 2) I think this should somehow be integrated with pci_bus_wait_crs(),
>    which also loops looking for CRS status.

Good point. I will see if that can be incorporated in next version, or
explain why not if that turns out to be the case.

> 3) pci_bus_wait_crs() is used in the enumeration path, and we do a
>    32-bit read there, which reads both the Vendor ID and the Device
>    ID.  Maybe that's some sort of micro-optimization, but apparently
>    there are devices that don't implement CRS SV correctly (see
>    89665a6a7140 ("PCI: Check only the Vendor ID to identify
>    Configuration Request Retry"), and doing a 16-bit read would avoid
>    that issue.
> 
>    For pci_dev_wait(), I don't think there's any point in doing a
>    32-bit read, so maybe we should just do a 16-bit read.

I agree, and will change it to a 16-bit read in next version.

> > Signed-off-by: Stanislav Spassov <stanspas@xxxxxxxxx>
> > ---
> >  drivers/pci/pci.c | 55 ++++++++++++++++++++++++++++++++++++++++-------
> >  1 file changed, 47 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > index 44f5d4907db6..a028147f4471 100644
> > --- a/drivers/pci/pci.c
> > +++ b/drivers/pci/pci.c
> > @@ -1073,17 +1073,56 @@ static inline int pci_dev_poll_until_not_equal(struct pci_dev *dev, int where,
> > 
> >  static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
> >  {
> > +     int waited = 0;
> > +     int rc = 0;
> > +
> > +
> >       /*
> >        * After reset, the device should not silently discard config
> >        * requests, but it may still indicate that it needs more time by
> > -      * responding to them with CRS completions.  The Root Port will
> > -      * generally synthesize ~0 data to complete the read (except when
> > -      * CRS SV is enabled and the read was for the Vendor ID; in that
> > -      * case it synthesizes 0x0001 data).
> > -      *
> > -      * Wait for the device to return a non-CRS completion.  Read the
> > -      * Command register instead of Vendor ID so we don't have to
> > -      * contend with the CRS SV value.
> > +      * responding to them with CRS completions. For such completions:
> > +      * - If CRS SV is enabled on the Root Port, and the read request
> > +      *   covers both bytes of the Vendor ID register, the Root Port
> > +      *   will synthesize the value 0x0001 (and set any extra requested
> > +      *   bytes to 0xff)
> > +      * - If CRS SV is not enabled on the Root Port, the Root Port must
> > +      *   re-issue the Configuration Request as a new Request.
> > +      *   Depending on platform-specific Root Complex configurations,
> > +      *   the Root Port may stop retrying after a set number of attempts,
> > +      *   or a configured timeout is hit, or continue indefinitely
> > +      *   (ultimately resulting in non-PCI-specific platform errors, such as
> > +      *   a TOR timeout).
> > +      */
> > +     if (dev->crssv_enabled) {
> > +             u32 id;
> > +
> > +             rc = pci_dev_poll_until_not_equal(dev, PCI_VENDOR_ID, 0xffff,
> > +                                               0x0001, reset_type, timeout,
> > +                                               &waited, &id);
> > +             if (rc)
> > +                     return rc;
> > +
> > +             timeout -= waited;
> > +
> > +             /*
> > +              * If Vendor/Device ID is valid, the device must be ready.
> > +              * Note: SR-IOV VFs return ~0 for reads to Vendor/Device
> > +              * ID and will not be recognized as ready by this check.
> > +              */
> > +             if (id != 0x0000ffff && id != 0xffff0000 &&
> > +                 id != 0x00000000 && id != 0xffffffff)
> > +                     return 0;
> > +     }
> > +
> > +     /*
> > +      * Root Ports will generally indicate error scenarios (e.g.
> > +      * internal timeouts, or received Completion with CA/UR) by
> > +      * synthesizing an 'all bits set' value (~0).
> > +      * In case CRS is not supported/enabled, as well as for SR-IOV VFs,
> > +      * fall back to polling a different register that cannot validly
> > +      * contain ~0. As of PCIe 5.0, bits 11-15 of COMMAND are still RsvdP
> > +      * and must return 0 when read.
> > +      * XXX: These bits might become meaningful in the future
> >        */
> >       return pci_dev_poll_until_not_equal(dev, PCI_COMMAND, ~0, ~0,
> >                                           reset_type, timeout, NULL,
> > --
> > 2.25.1
> > 
> > 
> > 
> > 
> > Amazon Development Center Germany GmbH
> > Krausenstr. 38
> > 10117 Berlin
> > Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss
> > Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
> > Sitz: Berlin
> > Ust-ID: DE 289 237 879
> > 
> > 
> > 



Amazon Development Center Germany GmbH
Krausenstr. 38
10117 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss
Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
Sitz: Berlin
Ust-ID: DE 289 237 879






[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux