lkml.org 
[lkml]   [2020]   [Aug]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 04/10] PCI/RCEC: Add pcie_walk_rcec() to walk associated RCiEPs
    Date
    From: Qiuxu Zhuo <qiuxu.zhuo@intel.com>

    When an RCEC device signals error(s) to a CPU core, the CPU core
    needs to walk all the RCiEPs associated with that RCEC to check
    errors. So add the function pcie_walk_rcec() to walk all RCiEPs
    associated with the RCEC device.

    Co-developed-by: Sean V Kelley <sean.v.kelley@intel.com>
    Signed-off-by: Sean V Kelley <sean.v.kelley@intel.com>
    Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
    Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
    ---
    drivers/pci/pci.h | 4 +++
    drivers/pci/pcie/rcec.c | 76 +++++++++++++++++++++++++++++++++++++++++
    2 files changed, 80 insertions(+)

    diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
    index bd25e6047b54..8bd7528d6977 100644
    --- a/drivers/pci/pci.h
    +++ b/drivers/pci/pci.h
    @@ -473,9 +473,13 @@ static inline void pci_dpc_init(struct pci_dev *pdev) {}
    #ifdef CONFIG_PCIEPORTBUS
    void pci_rcec_init(struct pci_dev *dev);
    void pci_rcec_exit(struct pci_dev *dev);
    +void pcie_walk_rcec(struct pci_dev *rcec, int (*cb)(struct pci_dev *, void *),
    + void *userdata);
    #else
    static inline void pci_rcec_init(struct pci_dev *dev) {}
    static inline void pci_rcec_exit(struct pci_dev *dev) {}
    +static inline void pcie_walk_rcec(struct pci_dev *rcec, int (*cb)(struct pci_dev *, void *),
    + void *userdata) {}
    #endif

    #ifdef CONFIG_PCI_ATS
    diff --git a/drivers/pci/pcie/rcec.c b/drivers/pci/pcie/rcec.c
    index 519ae086ff41..405f92fcdf7f 100644
    --- a/drivers/pci/pcie/rcec.c
    +++ b/drivers/pci/pcie/rcec.c
    @@ -17,6 +17,82 @@

    #include "../pci.h"

    +static int pcie_walk_rciep_devfn(struct pci_bus *bus, int (*cb)(struct pci_dev *, void *),
    + void *userdata, const unsigned long bitmap)
    +{
    + unsigned int devn, fn;
    + struct pci_dev *dev;
    + int retval;
    +
    + for_each_set_bit(devn, &bitmap, 32) {
    + for (fn = 0; fn < 8; fn++) {
    + dev = pci_get_slot(bus, PCI_DEVFN(devn, fn));
    +
    + if (!dev)
    + continue;
    +
    + if (pci_pcie_type(dev) != PCI_EXP_TYPE_RC_END) {
    + pci_dev_put(dev);
    + continue;
    + }
    +
    + retval = cb(dev, userdata);
    + pci_dev_put(dev);
    + if (retval)
    + return retval;
    + }
    + }
    +
    + return 0;
    +}
    +
    +/**
    + * pcie_walk_rcec - Walk RCiEP devices associating with RCEC and call callback.
    + * @rcec RCEC whose RCiEP devices should be walked.
    + * @cb Callback to be called for each RCiEP device found.
    + * @userdata Arbitrary pointer to be passed to callback.
    + *
    + * Walk the given RCEC. Call the provided callback on each RCiEP device found.
    + *
    + * We check the return of @cb each time. If it returns anything
    + * other than 0, we break out.
    + */
    +void pcie_walk_rcec(struct pci_dev *rcec, int (*cb)(struct pci_dev *, void *),
    + void *userdata)
    +{
    + u8 nextbusn, lastbusn;
    + struct pci_bus *bus;
    + unsigned int bnr;
    +
    + if (!rcec->rcec_cap)
    + return;
    +
    + /* Find RCiEP devices on the same bus as the RCEC */
    + if (pcie_walk_rciep_devfn(rcec->bus, cb, userdata, rcec->rcec_ext->bitmap))
    + return;
    +
    + /* Check whether RCEC BUSN register is present */
    + if (rcec->rcec_ext->ver < PCI_RCEC_BUSN_REG_VER)
    + return;
    +
    + nextbusn = rcec->rcec_ext->nextbusn;
    + lastbusn = rcec->rcec_ext->lastbusn;
    +
    + /* All RCiEP devices are on the same bus as the RCEC */
    + if (nextbusn == 0xff && lastbusn == 0x00)
    + return;
    +
    + for (bnr = nextbusn; bnr <= lastbusn; bnr++) {
    + bus = pci_find_bus(pci_domain_nr(rcec->bus), bnr);
    + if (!bus)
    + continue;
    +
    + /* Find RCiEP devices on the given bus */
    + if (pcie_walk_rciep_devfn(bus, cb, userdata, 0xffffffff))
    + return;
    + }
    +}
    +
    void pci_rcec_init(struct pci_dev *dev)
    {
    u32 rcec, hdr, busn;
    --
    2.28.0
    \
     
     \ /
      Last update: 2020-08-12 18:48    [W:5.093 / U:0.044 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site