From patchwork Thu Sep 28 12:58:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Petazzoni X-Patchwork-Id: 9975993 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3A9BA6034B for ; Thu, 28 Sep 2017 12:58:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2C5E62950C for ; Thu, 28 Sep 2017 12:58:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 20D8E29571; Thu, 28 Sep 2017 12:58:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5B4392950C for ; Thu, 28 Sep 2017 12:58:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753175AbdI1M6y (ORCPT ); Thu, 28 Sep 2017 08:58:54 -0400 Received: from mail.free-electrons.com ([62.4.15.54]:44148 "EHLO mail.free-electrons.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753146AbdI1M6w (ORCPT ); Thu, 28 Sep 2017 08:58:52 -0400 Received: by mail.free-electrons.com (Postfix, from userid 110) id C4B4C20885; Thu, 28 Sep 2017 14:58:50 +0200 (CEST) Received: from localhost (LStLambert-657-1-97-87.w90-63.abo.wanadoo.fr [90.63.216.87]) by mail.free-electrons.com (Postfix) with ESMTPSA id 9F4E920911; Thu, 28 Sep 2017 14:58:40 +0200 (CEST) From: Thomas Petazzoni To: Bjorn Helgaas , linux-pci@vger.kernel.org Cc: Jason Cooper , Andrew Lunn , Sebastian Hesselbarth , Gregory Clement , Nadav Haklai , Hanna Hawa , Yehuda Yitschak , linux-arm-kernel@lists.infradead.org, Antoine Tenart , =?UTF-8?q?Miqu=C3=A8l=20Raynal?= , Victor Gu , Thomas Petazzoni Subject: [PATCH v2 3/7] PCI: aardvark: set host and device to the same MAX payload size Date: Thu, 28 Sep 2017 14:58:34 +0200 Message-Id: <20170928125838.11887-4-thomas.petazzoni@free-electrons.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170928125838.11887-1-thomas.petazzoni@free-electrons.com> References: <20170928125838.11887-1-thomas.petazzoni@free-electrons.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Victor Gu 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 Reviewed-by: Evan Wang Reviewed-by: Nadav Haklai [Thomas: tweak commit log.] Signed-off-by: Thomas Petazzoni --- 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 af7a9c4a61a4..c8a97bad6c4c 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) @@ -297,7 +299,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); @@ -879,6 +882,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; @@ -950,6 +1005,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; }