lkml.org 
[lkml]   [2017]   [Dec]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 074/115] PCI/PME: Handle invalid data when reading Root Status
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Qiang <zhengqiang10@huawei.com>


    [ Upstream commit 3ad3f8ce50914288731a3018b27ee44ab803e170 ]

    PCIe PME and native hotplug share the same interrupt number, so hotplug
    interrupts are also processed by PME. In some cases, e.g., a Link Down
    interrupt, a device may be present but unreachable, so when we try to
    read its Root Status register, the read fails and we get all ones data
    (0xffffffff).

    Previously, we interpreted that data as PCI_EXP_RTSTA_PME being set, i.e.,
    "some device has asserted PME," so we scheduled pcie_pme_work_fn(). This
    caused an infinite loop because pcie_pme_work_fn() tried to handle PME
    requests until PCI_EXP_RTSTA_PME is cleared, but with the link down,
    PCI_EXP_RTSTA_PME can't be cleared.

    Check for the invalid 0xffffffff data everywhere we read the Root Status
    register.

    1469d17dd341 ("PCI: pciehp: Handle invalid data when reading from
    non-existent devices") added similar checks in the hotplug driver.

    Signed-off-by: Qiang Zheng <zhengqiang10@huawei.com>
    [bhelgaas: changelog, also check in pcie_pme_work_fn(), use "~0" to follow
    other similar checks]
    Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>

    Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/pci/pcie/pme.c | 5 ++++-
    1 file changed, 4 insertions(+), 1 deletion(-)

    --- a/drivers/pci/pcie/pme.c
    +++ b/drivers/pci/pcie/pme.c
    @@ -233,6 +233,9 @@ static void pcie_pme_work_fn(struct work
    break;

    pcie_capability_read_dword(port, PCI_EXP_RTSTA, &rtsta);
    + if (rtsta == (u32) ~0)
    + break;
    +
    if (rtsta & PCI_EXP_RTSTA_PME) {
    /*
    * Clear PME status of the port. If there are other
    @@ -280,7 +283,7 @@ static irqreturn_t pcie_pme_irq(int irq,
    spin_lock_irqsave(&data->lock, flags);
    pcie_capability_read_dword(port, PCI_EXP_RTSTA, &rtsta);

    - if (!(rtsta & PCI_EXP_RTSTA_PME)) {
    + if (rtsta == (u32) ~0 || !(rtsta & PCI_EXP_RTSTA_PME)) {
    spin_unlock_irqrestore(&data->lock, flags);
    return IRQ_NONE;
    }

    \
     
     \ /
      Last update: 2017-12-18 19:01    [W:4.036 / U:0.452 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site