lkml.org 
[lkml]   [2016]   [Feb]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.3 059/200] PCI: spear: Fix dw_pcie_cfg_read/write() usage
    Date
    4.3-stable review patch.  If anyone has any objections, please let me know.

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

    From: Gabriele Paoloni <gabriele.paoloni@huawei.com>

    commit fa3b7cbab548b15da438b0cc13aa515f7f291f4d upstream.

    The first argument of dw_pcie_cfg_read/write() is a 32-bit aligned address.
    The second argument is the byte offset into a 32-bit word, and
    dw_pcie_cfg_read/write() only look at the low two bits.

    SPEAr13xx used dw_pcie_cfg_read() and dw_pcie_cfg_write() incorrectly: it
    passed important address bits in the second argument, where they were
    ignored.

    Pass the complete 32-bit word address in the first argument and only the
    2-bit offset into that word in the second argument.

    Without this fix, SPEAr13xx host will never work with few buggy gen1 card
    which connects with only gen1 host and also with any endpoint which would
    generate a read request of more than 128 bytes.

    [bhelgaas: changelog]
    Reported-by: Bjorn Helgaas <bhelgaas@google.com>
    Signed-off-by: Pratyush Anand <panand@redhat.com>
    Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/pci/host/pcie-spear13xx.c | 26 ++++++++++++++------------
    1 file changed, 14 insertions(+), 12 deletions(-)

    --- a/drivers/pci/host/pcie-spear13xx.c
    +++ b/drivers/pci/host/pcie-spear13xx.c
    @@ -163,34 +163,36 @@ static int spear13xx_pcie_establish_link
    * default value in capability register is 512 bytes. So force
    * it to 128 here.
    */
    - dw_pcie_cfg_read(pp->dbi_base, exp_cap_off + PCI_EXP_DEVCTL, 4, &val);
    + dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_DEVCTL,
    + 0, 2, &val);
    val &= ~PCI_EXP_DEVCTL_READRQ;
    - dw_pcie_cfg_write(pp->dbi_base, exp_cap_off + PCI_EXP_DEVCTL, 4, val);
    + dw_pcie_cfg_write(pp->dbi_base + exp_cap_off + PCI_EXP_DEVCTL,
    + 0, 2, val);

    - dw_pcie_cfg_write(pp->dbi_base, PCI_VENDOR_ID, 2, 0x104A);
    - dw_pcie_cfg_write(pp->dbi_base, PCI_DEVICE_ID, 2, 0xCD80);
    + dw_pcie_cfg_write(pp->dbi_base + PCI_VENDOR_ID, 0, 2, 0x104A);
    + dw_pcie_cfg_write(pp->dbi_base + PCI_VENDOR_ID, 2, 2, 0xCD80);

    /*
    * if is_gen1 is set then handle it, so that some buggy card
    * also works
    */
    if (spear13xx_pcie->is_gen1) {
    - dw_pcie_cfg_read(pp->dbi_base, exp_cap_off + PCI_EXP_LNKCAP, 4,
    - &val);
    + dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_LNKCAP,
    + 0, 4, &val);
    if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) {
    val &= ~((u32)PCI_EXP_LNKCAP_SLS);
    val |= PCI_EXP_LNKCAP_SLS_2_5GB;
    - dw_pcie_cfg_write(pp->dbi_base, exp_cap_off +
    - PCI_EXP_LNKCAP, 4, val);
    + dw_pcie_cfg_write(pp->dbi_base + exp_cap_off +
    + PCI_EXP_LNKCAP, 0, 4, val);
    }

    - dw_pcie_cfg_read(pp->dbi_base, exp_cap_off + PCI_EXP_LNKCTL2, 4,
    - &val);
    + dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_LNKCTL2,
    + 0, 2, &val);
    if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) {
    val &= ~((u32)PCI_EXP_LNKCAP_SLS);
    val |= PCI_EXP_LNKCAP_SLS_2_5GB;
    - dw_pcie_cfg_write(pp->dbi_base, exp_cap_off +
    - PCI_EXP_LNKCTL2, 4, val);
    + dw_pcie_cfg_write(pp->dbi_base + exp_cap_off +
    + PCI_EXP_LNKCTL2, 0, 2, val);
    }
    }


    \
     
     \ /
      Last update: 2016-02-15 01:21    [W:4.192 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site