lkml.org 
[lkml]   [2021]   [Nov]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.10 147/575] PCI: aardvark: Fix support for bus mastering and PCI_COMMAND on emulated bridge
    Date
    From: Pali Rohár <pali@kernel.org>

    commit 771153fc884f566a89af2d30033b7f3bc6e24e84 upstream.

    >From very vague, ambiguous and incomplete information from Marvell we
    deduced that the 32-bit Aardvark register at address 0x4
    (PCIE_CORE_CMD_STATUS_REG), which is not documented for Root Complex mode
    in the Functional Specification (only for Endpoint mode), controls two
    16-bit PCIe registers: Command Register and Status Registers of PCIe Root
    Port.

    This means that bit 2 controls bus mastering and forwarding of memory and
    I/O requests in the upstream direction. According to PCI specifications
    bits [0:2] of Command Register, this should be by default disabled on
    reset. So explicitly disable these bits at early setup of the Aardvark
    driver.

    Remove code which unconditionally enables all 3 bits and let kernel code
    (via pci_set_master() function) to handle bus mastering of Root PCIe
    Bridge via emulated PCI_COMMAND on emulated bridge.

    Link: https://lore.kernel.org/r/20211028185659.20329-5-kabel@kernel.org
    Fixes: 8a3ebd8de328 ("PCI: aardvark: Implement emulated root PCI bridge config space")
    Signed-off-by: Pali Rohár <pali@kernel.org>
    Signed-off-by: Marek Behún <kabel@kernel.org>
    Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
    Cc: stable@vger.kernel.org # b2a56469d550 ("PCI: aardvark: Add FIXME comment for PCIE_CORE_CMD_STATUS_REG access")
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/pci/controller/pci-aardvark.c | 54 +++++++++++++++++++++++-----------
    1 file changed, 38 insertions(+), 16 deletions(-)

    --- a/drivers/pci/controller/pci-aardvark.c
    +++ b/drivers/pci/controller/pci-aardvark.c
    @@ -30,9 +30,6 @@
    /* PCIe core registers */
    #define PCIE_CORE_DEV_ID_REG 0x0
    #define PCIE_CORE_CMD_STATUS_REG 0x4
    -#define PCIE_CORE_CMD_IO_ACCESS_EN BIT(0)
    -#define PCIE_CORE_CMD_MEM_ACCESS_EN BIT(1)
    -#define PCIE_CORE_CMD_MEM_IO_REQ_EN BIT(2)
    #define PCIE_CORE_DEV_REV_REG 0x8
    #define PCIE_CORE_PCIEXP_CAP 0xc0
    #define PCIE_CORE_ERR_CAPCTL_REG 0x118
    @@ -563,6 +560,11 @@ static void advk_pcie_setup_hw(struct ad
    reg = (PCI_VENDOR_ID_MARVELL << 16) | PCI_VENDOR_ID_MARVELL;
    advk_writel(pcie, reg, VENDOR_ID_REG);

    + /* Disable Root Bridge I/O space, memory space and bus mastering */
    + reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
    + reg &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
    + advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG);
    +
    /* Set Advanced Error Capabilities and Control PF0 register */
    reg = PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX |
    PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN |
    @@ -660,19 +662,6 @@ static void advk_pcie_setup_hw(struct ad
    advk_pcie_disable_ob_win(pcie, i);

    advk_pcie_train_link(pcie);
    -
    - /*
    - * FIXME: The following register update is suspicious. This register is
    - * applicable only when the PCI controller is configured for Endpoint
    - * mode, not as a Root Complex. But apparently when this code is
    - * removed, some cards stop working. This should be investigated and
    - * a comment explaining this should be put here.
    - */
    - reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
    - reg |= PCIE_CORE_CMD_MEM_ACCESS_EN |
    - PCIE_CORE_CMD_IO_ACCESS_EN |
    - PCIE_CORE_CMD_MEM_IO_REQ_EN;
    - advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG);
    }

    static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u32 *val)
    @@ -793,6 +782,37 @@ static int advk_pcie_wait_pio(struct adv
    return -ETIMEDOUT;
    }

    +static pci_bridge_emul_read_status_t
    +advk_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge,
    + int reg, u32 *value)
    +{
    + struct advk_pcie *pcie = bridge->data;
    +
    + switch (reg) {
    + case PCI_COMMAND:
    + *value = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
    + return PCI_BRIDGE_EMUL_HANDLED;
    +
    + default:
    + return PCI_BRIDGE_EMUL_NOT_HANDLED;
    + }
    +}
    +
    +static void
    +advk_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
    + int reg, u32 old, u32 new, u32 mask)
    +{
    + struct advk_pcie *pcie = bridge->data;
    +
    + switch (reg) {
    + case PCI_COMMAND:
    + advk_writel(pcie, new, PCIE_CORE_CMD_STATUS_REG);
    + break;
    +
    + default:
    + break;
    + }
    +}

    static pci_bridge_emul_read_status_t
    advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
    @@ -893,6 +913,8 @@ advk_pci_bridge_emul_pcie_conf_write(str
    }

    static struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = {
    + .read_base = advk_pci_bridge_emul_base_conf_read,
    + .write_base = advk_pci_bridge_emul_base_conf_write,
    .read_pcie = advk_pci_bridge_emul_pcie_conf_read,
    .write_pcie = advk_pci_bridge_emul_pcie_conf_write,
    };

    \
     
     \ /
      Last update: 2021-11-15 20:40    [W:4.075 / U:0.080 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site