PCI: aardvark: Fix support for bus mastering and PCI_COMMAND on emulated bridge
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: 8a3ebd8de3 ("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: Marek Behún <kabel@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
bbc6201152
commit
44b2776a93
@@ -27,9 +27,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
|
||||
@@ -505,6 +502,11 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
|
||||
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 |
|
||||
@@ -603,12 +605,6 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
|
||||
advk_pcie_disable_ob_win(pcie, i);
|
||||
|
||||
advk_pcie_train_link(pcie);
|
||||
|
||||
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)
|
||||
@@ -737,6 +733,37 @@ static int advk_pcie_wait_pio(struct advk_pcie *pcie)
|
||||
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,
|
||||
@@ -838,6 +865,8 @@ advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user