Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI: xilinx-nwl: Fix ECAM programming

When PCIe has been set up by the bootloader, the ecam_size field in the
E_ECAM_CONTROL register already contains a value.

The driver previously programmed it to 0xc (for 16 busses; 16 MB), but
bumped to 0x10 (for 256 busses; 256 MB) by the commit 2fccd11518f1 ("PCI:
xilinx-nwl: Modify ECAM size to enable support for 256 buses").

Regardless of what the bootloader has programmed, the driver ORs in a
new maximal value without doing a proper RMW sequence. This can lead to
problems.

For example, if the bootloader programs in 0xc and the driver uses 0x10,
the ORed result is 0x1c, which is beyond the ecam_max_size limit of 0x10
(from E_ECAM_CAPABILITIES).

Avoid the problems by doing a proper RMW.

Fixes: 2fccd11518f1 ("PCI: xilinx-nwl: Modify ECAM size to enable support for 256 buses")
Signed-off-by: Jani Nurminen <jani.nurminen@windriver.com>
[mani: added stable tag]
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/e83a2af2-af0b-4670-bcf5-ad408571c2b0@windriver.com

authored by

Jani Nurminen and committed by
Bjorn Helgaas
98a4f5b7 8f5ae30d

+4 -3
+4 -3
drivers/pci/controller/pcie-xilinx-nwl.c
··· 718 718 nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, E_ECAM_CONTROL) | 719 719 E_ECAM_CR_ENABLE, E_ECAM_CONTROL); 720 720 721 - nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, E_ECAM_CONTROL) | 722 - (NWL_ECAM_MAX_SIZE << E_ECAM_SIZE_SHIFT), 723 - E_ECAM_CONTROL); 721 + ecam_val = nwl_bridge_readl(pcie, E_ECAM_CONTROL); 722 + ecam_val &= ~E_ECAM_SIZE_LOC; 723 + ecam_val |= NWL_ECAM_MAX_SIZE << E_ECAM_SIZE_SHIFT; 724 + nwl_bridge_writel(pcie, ecam_val, E_ECAM_CONTROL); 724 725 725 726 nwl_bridge_writel(pcie, lower_32_bits(pcie->phys_ecam_base), 726 727 E_ECAM_BASE_LO);