lkml.org 
[lkml]   [2022]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.16 0801/1039] PCI: mvebu: Fix support for bus mastering and PCI_COMMAND on emulated bridge
    Date
    From: Pali Rohár <pali@kernel.org>

    [ Upstream commit e42b85583719adb87ab88dc7bcd41b38011f7d11 ]

    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
    beginning of driver initialization.

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

    Adjust existing functions mvebu_pcie_handle_iobase_change() and
    mvebu_pcie_handle_membase_change() to handle PCI_IO_BASE and PCI_MEM_BASE
    registers correctly even when bus mastering on emulated bridge is disabled.

    Link: https://lore.kernel.org/r/20211125124605.25915-7-pali@kernel.org
    Signed-off-by: Pali Rohár <pali@kernel.org>
    Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/pci/controller/pci-mvebu.c | 52 ++++++++++++++++++------------
    1 file changed, 32 insertions(+), 20 deletions(-)

    diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
    index beae555b06bbc..326527f2d6f41 100644
    --- a/drivers/pci/controller/pci-mvebu.c
    +++ b/drivers/pci/controller/pci-mvebu.c
    @@ -215,16 +215,14 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
    {
    u32 cmd, mask;

    - /* Point PCIe unit MBUS decode windows to DRAM space. */
    - mvebu_pcie_setup_wins(port);
    -
    - /* Master + slave enable. */
    + /* Disable Root Bridge I/O space, memory space and bus mastering. */
    cmd = mvebu_readl(port, PCIE_CMD_OFF);
    - cmd |= PCI_COMMAND_IO;
    - cmd |= PCI_COMMAND_MEMORY;
    - cmd |= PCI_COMMAND_MASTER;
    + cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
    mvebu_writel(port, cmd, PCIE_CMD_OFF);

    + /* Point PCIe unit MBUS decode windows to DRAM space. */
    + mvebu_pcie_setup_wins(port);
    +
    /* Enable interrupt lines A-D. */
    mask = mvebu_readl(port, PCIE_MASK_OFF);
    mask |= PCIE_MASK_ENABLE_INTS;
    @@ -371,8 +369,7 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)

    /* Are the new iobase/iolimit values invalid? */
    if (conf->iolimit < conf->iobase ||
    - conf->iolimitupper < conf->iobaseupper ||
    - !(conf->command & PCI_COMMAND_IO)) {
    + conf->iolimitupper < conf->iobaseupper) {
    mvebu_pcie_set_window(port, port->io_target, port->io_attr,
    &desired, &port->iowin);
    return;
    @@ -409,8 +406,7 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
    struct pci_bridge_emul_conf *conf = &port->bridge.conf;

    /* Are the new membase/memlimit values invalid? */
    - if (conf->memlimit < conf->membase ||
    - !(conf->command & PCI_COMMAND_MEMORY)) {
    + if (conf->memlimit < conf->membase) {
    mvebu_pcie_set_window(port, port->mem_target, port->mem_attr,
    &desired, &port->memwin);
    return;
    @@ -430,6 +426,24 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
    &port->memwin);
    }

    +static pci_bridge_emul_read_status_t
    +mvebu_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge,
    + int reg, u32 *value)
    +{
    + struct mvebu_pcie_port *port = bridge->data;
    +
    + switch (reg) {
    + case PCI_COMMAND:
    + *value = mvebu_readl(port, PCIE_CMD_OFF);
    + break;
    +
    + default:
    + return PCI_BRIDGE_EMUL_NOT_HANDLED;
    + }
    +
    + return PCI_BRIDGE_EMUL_HANDLED;
    +}
    +
    static pci_bridge_emul_read_status_t
    mvebu_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
    int reg, u32 *value)
    @@ -484,17 +498,14 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,

    switch (reg) {
    case PCI_COMMAND:
    - {
    - if (!mvebu_has_ioport(port))
    - conf->command &= ~PCI_COMMAND_IO;
    -
    - if ((old ^ new) & PCI_COMMAND_IO)
    - mvebu_pcie_handle_iobase_change(port);
    - if ((old ^ new) & PCI_COMMAND_MEMORY)
    - mvebu_pcie_handle_membase_change(port);
    + if (!mvebu_has_ioport(port)) {
    + conf->command = cpu_to_le16(
    + le16_to_cpu(conf->command) & ~PCI_COMMAND_IO);
    + new &= ~PCI_COMMAND_IO;
    + }

    + mvebu_writel(port, new, PCIE_CMD_OFF);
    break;
    - }

    case PCI_IO_BASE:
    mvebu_pcie_handle_iobase_change(port);
    @@ -554,6 +565,7 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
    }

    static struct pci_bridge_emul_ops mvebu_pci_bridge_emul_ops = {
    + .read_base = mvebu_pci_bridge_emul_base_conf_read,
    .write_base = mvebu_pci_bridge_emul_base_conf_write,
    .read_pcie = mvebu_pci_bridge_emul_pcie_conf_read,
    .write_pcie = mvebu_pci_bridge_emul_pcie_conf_write,
    --
    2.34.1


    \
     
     \ /
      Last update: 2022-01-25 00:11    [W:4.028 / U:0.096 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site