mirror of
https://github.com/archlinuxarm/PKGBUILDs.git
synced 2024-11-18 22:54:00 +00:00
123 lines
4 KiB
Diff
123 lines
4 KiB
Diff
From c5cdcc007c34ff5236fc3f37cb8897b545342699 Mon Sep 17 00:00:00 2001
|
|
From: Victor Gu <xigu@marvell.com>
|
|
Date: Fri, 8 Sep 2017 11:53:44 +0200
|
|
Subject: [PATCH 08/11] PCI: aardvark: set host and device to the same MAX
|
|
payload size
|
|
|
|
Since the Aardvark does not implement a PCIe root bus, the Linux PCIe
|
|
subsystem will not align the MAX payload size between the host and the
|
|
device. This patch ensures that the host and device have the same MAX
|
|
payload size, fixing a number of problems with various PCIe devices.
|
|
|
|
This is part of fixing bug
|
|
https://bugzilla.kernel.org/show_bug.cgi?id=196339, this commit was
|
|
reported as the user to be important to get a Intel 7260 mini-PCIe
|
|
WiFi card working.
|
|
|
|
Fixes: Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver")
|
|
Signed-off-by: Victor Gu <xigu@marvell.com>
|
|
Reviewed-by: Evan Wang <xswang@marvell.com>
|
|
Reviewed-by: Nadav Haklai <nadavh@marvell.com>
|
|
[Thomas: tweak commit log.]
|
|
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
|
---
|
|
drivers/pci/host/pci-aardvark.c | 60 ++++++++++++++++++++++++++++++++++++++++-
|
|
1 file changed, 59 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/pci/host/pci-aardvark.c b/drivers/pci/host/pci-aardvark.c
|
|
index fe94d064483b..f74834d8667d 100644
|
|
--- a/drivers/pci/host/pci-aardvark.c
|
|
+++ b/drivers/pci/host/pci-aardvark.c
|
|
@@ -30,8 +30,10 @@
|
|
#define PCIE_CORE_DEV_CTRL_STATS_REG 0xc8
|
|
#define PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE (0 << 4)
|
|
#define PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT 5
|
|
+#define PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ 0x2
|
|
#define PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE (0 << 11)
|
|
#define PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT 12
|
|
+#define PCIE_CORE_MPS_UNIT_BYTE 128
|
|
#define PCIE_CORE_LINK_CTRL_STAT_REG 0xd0
|
|
#define PCIE_CORE_LINK_L0S_ENTRY BIT(0)
|
|
#define PCIE_CORE_LINK_TRAINING BIT(5)
|
|
@@ -298,7 +300,8 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
|
|
|
|
/* Set PCIe Device Control and Status 1 PF0 register */
|
|
reg = PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE |
|
|
- (7 << PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT) |
|
|
+ (PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ <<
|
|
+ PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT) |
|
|
PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE |
|
|
PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT;
|
|
advk_writel(pcie, reg, PCIE_CORE_DEV_CTRL_STATS_REG);
|
|
@@ -880,6 +883,58 @@ static int advk_pcie_parse_request_of_pci_ranges(struct advk_pcie *pcie)
|
|
return err;
|
|
}
|
|
|
|
+static int advk_pcie_find_smpss(struct pci_dev *dev, void *data)
|
|
+{
|
|
+ u8 *smpss = data;
|
|
+
|
|
+ if (!dev)
|
|
+ return 0;
|
|
+
|
|
+ if (!pci_is_pcie(dev))
|
|
+ return 0;
|
|
+
|
|
+ if (*smpss > dev->pcie_mpss)
|
|
+ *smpss = dev->pcie_mpss;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int advk_pcie_bus_configure_mps(struct pci_dev *dev, void *data)
|
|
+{
|
|
+ int mps;
|
|
+
|
|
+ if (!dev)
|
|
+ return 0;
|
|
+
|
|
+ if (!pci_is_pcie(dev))
|
|
+ return 0;
|
|
+
|
|
+ mps = PCIE_CORE_MPS_UNIT_BYTE << *(u8 *)data;
|
|
+ pcie_set_mps(dev, mps);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void advk_pcie_configure_mps(struct pci_bus *bus, struct advk_pcie *pcie)
|
|
+{
|
|
+ u8 smpss = PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ;
|
|
+ u32 reg;
|
|
+
|
|
+ /* Find the minimal supported MAX payload size */
|
|
+ advk_pcie_find_smpss(bus->self, &smpss);
|
|
+ pci_walk_bus(bus, advk_pcie_find_smpss, &smpss);
|
|
+
|
|
+ /* Configure RC MAX payload size */
|
|
+ reg = advk_readl(pcie, PCIE_CORE_DEV_CTRL_STATS_REG);
|
|
+ reg &= ~PCI_EXP_DEVCTL_PAYLOAD;
|
|
+ reg |= smpss << PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT;
|
|
+ advk_writel(pcie, reg, PCIE_CORE_DEV_CTRL_STATS_REG);
|
|
+
|
|
+ /* Configure device MAX payload size */
|
|
+ advk_pcie_bus_configure_mps(bus->self, &smpss);
|
|
+ pci_walk_bus(bus, advk_pcie_bus_configure_mps, &smpss);
|
|
+}
|
|
+
|
|
static int advk_pcie_probe(struct platform_device *pdev)
|
|
{
|
|
struct device *dev = &pdev->dev;
|
|
@@ -953,6 +1008,9 @@ static int advk_pcie_probe(struct platform_device *pdev)
|
|
list_for_each_entry(child, &bus->children, node)
|
|
pcie_bus_configure_settings(child);
|
|
|
|
+ /* Configure the MAX pay load size */
|
|
+ advk_pcie_configure_mps(bus, pcie);
|
|
+
|
|
pci_bus_add_devices(bus);
|
|
return 0;
|
|
}
|
|
--
|
|
2.14.2
|
|
|