/branches/18.06.1/target/linux/mvebu/patches-4.14/524-PCI-aardvark-set-host-and-device-to-the-same-MAX-payload-size.patch |
@@ -0,0 +1,138 @@ |
From patchwork Thu Sep 28 12:58:34 2017 |
Content-Type: text/plain; charset="utf-8" |
MIME-Version: 1.0 |
Content-Transfer-Encoding: 7bit |
Subject: [v2, |
3/7] PCI: aardvark: set host and device to the same MAX payload size |
X-Patchwork-Submitter: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> |
X-Patchwork-Id: 819587 |
Message-Id: <20170928125838.11887-4-thomas.petazzoni@free-electrons.com> |
To: Bjorn Helgaas <bhelgaas@google.com>, linux-pci@vger.kernel.org |
Cc: Jason Cooper <jason@lakedaemon.net>, Andrew Lunn <andrew@lunn.ch>, |
Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>, Gregory Clement |
<gregory.clement@free-electrons.com>, |
Nadav Haklai <nadavh@marvell.com>, Hanna Hawa <hannah@marvell.com>, |
Yehuda Yitschak <yehuday@marvell.com>, |
linux-arm-kernel@lists.infradead.org, Antoine Tenart |
<antoine.tenart@free-electrons.com>, =?utf-8?q?Miqu=C3=A8l_Raynal?= |
<miquel.raynal@free-electrons.com>, Victor Gu <xigu@marvell.com>, |
Thomas Petazzoni <thomas.petazzoni@free-electrons.com> |
Date: Thu, 28 Sep 2017 14:58:34 +0200 |
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> |
List-Id: <linux-pci.vger.kernel.org> |
|
From: Victor Gu <xigu@marvell.com> |
|
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(-) |
|
--- a/drivers/pci/host/pci-aardvark.c |
+++ b/drivers/pci/host/pci-aardvark.c |
@@ -30,9 +30,11 @@ |
#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_DEV_CTRL_STATS_MAX_RD_REQ_SZ 0x2 |
+#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) |
@@ -297,7 +299,8 @@ static void advk_pcie_setup_hw(struct ad |
|
/* 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_SZ << |
PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT); |
@@ -886,6 +889,58 @@ out_release_res: |
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; |
@@ -960,6 +1015,9 @@ static int advk_pcie_probe(struct platfo |
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; |
} |