c6cfe3783c59b0743f13453d97d405ee111627db
[oweals/openwrt.git] /
1 From patchwork Thu Sep 28 12:58:34 2017
2 Content-Type: text/plain; charset="utf-8"
3 MIME-Version: 1.0
4 Content-Transfer-Encoding: 7bit
5 Subject: [v2,
6  3/7] PCI: aardvark: set host and device to the same MAX payload size
7 X-Patchwork-Submitter: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
8 X-Patchwork-Id: 819587
9 Message-Id: <20170928125838.11887-4-thomas.petazzoni@free-electrons.com>
10 To: Bjorn Helgaas <bhelgaas@google.com>, linux-pci@vger.kernel.org
11 Cc: Jason Cooper <jason@lakedaemon.net>, Andrew Lunn <andrew@lunn.ch>,
12  Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>, Gregory Clement
13  <gregory.clement@free-electrons.com>, 
14  Nadav Haklai <nadavh@marvell.com>, Hanna Hawa <hannah@marvell.com>,
15  Yehuda Yitschak <yehuday@marvell.com>,
16  linux-arm-kernel@lists.infradead.org, Antoine Tenart
17  <antoine.tenart@free-electrons.com>, =?utf-8?q?Miqu=C3=A8l_Raynal?=
18  <miquel.raynal@free-electrons.com>, Victor Gu <xigu@marvell.com>,
19  Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
20 Date: Thu, 28 Sep 2017 14:58:34 +0200
21 From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
22 List-Id: <linux-pci.vger.kernel.org>
23
24 From: Victor Gu <xigu@marvell.com>
25
26 Since the Aardvark does not implement a PCIe root bus, the Linux PCIe
27 subsystem will not align the MAX payload size between the host and the
28 device. This patch ensures that the host and device have the same MAX
29 payload size, fixing a number of problems with various PCIe devices.
30
31 This is part of fixing bug
32 https://bugzilla.kernel.org/show_bug.cgi?id=196339, this commit was
33 reported as the user to be important to get a Intel 7260 mini-PCIe
34 WiFi card working.
35
36 Fixes: Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver")
37 Signed-off-by: Victor Gu <xigu@marvell.com>
38 Reviewed-by: Evan Wang <xswang@marvell.com>
39 Reviewed-by: Nadav Haklai <nadavh@marvell.com>
40 [Thomas: tweak commit log.]
41 Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
42 ---
43  drivers/pci/controller/pci-aardvark.c | 60 ++++++++++++++++++++++++++++++++++++++++-
44  1 file changed, 59 insertions(+), 1 deletion(-)
45
46 --- a/drivers/pci/controller/pci-aardvark.c
47 +++ b/drivers/pci/controller/pci-aardvark.c
48 @@ -33,9 +33,11 @@
49  #define PCIE_CORE_DEV_CTRL_STATS_REG                           0xc8
50  #define     PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE       (0 << 4)
51  #define     PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT      5
52 +#define     PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ            0x2
53  #define     PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE             (0 << 11)
54  #define     PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT     12
55  #define     PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SZ             0x2
56 +#define     PCIE_CORE_MPS_UNIT_BYTE                            128
57  #define PCIE_CORE_LINK_CTRL_STAT_REG                           0xd0
58  #define     PCIE_CORE_LINK_L0S_ENTRY                           BIT(0)
59  #define     PCIE_CORE_LINK_TRAINING                            BIT(5)
60 @@ -276,7 +278,8 @@ static void advk_pcie_setup_hw(struct ad
61  
62         /* Set PCIe Device Control and Status 1 PF0 register */
63         reg = PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE |
64 -               (7 << PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT) |
65 +               (PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ <<
66 +                PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT) |
67                 PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE |
68                 (PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SZ <<
69                  PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT);
70 @@ -994,6 +997,58 @@ out_release_res:
71         return err;
72  }
73  
74 +static int advk_pcie_find_smpss(struct pci_dev *dev, void *data)
75 +{
76 +       u8 *smpss = data;
77 +
78 +       if (!dev)
79 +               return 0;
80 +
81 +       if (!pci_is_pcie(dev))
82 +               return 0;
83 +
84 +       if (*smpss > dev->pcie_mpss)
85 +               *smpss = dev->pcie_mpss;
86 +
87 +       return 0;
88 +}
89 +
90 +static int advk_pcie_bus_configure_mps(struct pci_dev *dev, void *data)
91 +{
92 +       int mps;
93 +
94 +       if (!dev)
95 +               return 0;
96 +
97 +       if (!pci_is_pcie(dev))
98 +               return 0;
99 +
100 +       mps = PCIE_CORE_MPS_UNIT_BYTE << *(u8 *)data;
101 +       pcie_set_mps(dev, mps);
102 +
103 +       return 0;
104 +}
105 +
106 +static void advk_pcie_configure_mps(struct pci_bus *bus, struct advk_pcie *pcie)
107 +{
108 +       u8 smpss = PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ;
109 +       u32 reg;
110 +
111 +       /* Find the minimal supported MAX payload size */
112 +       advk_pcie_find_smpss(bus->self, &smpss);
113 +       pci_walk_bus(bus, advk_pcie_find_smpss, &smpss);
114 +
115 +       /* Configure RC MAX payload size */
116 +       reg = advk_readl(pcie, PCIE_CORE_DEV_CTRL_STATS_REG);
117 +       reg &= ~PCI_EXP_DEVCTL_PAYLOAD;
118 +       reg |= smpss << PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT;
119 +       advk_writel(pcie, reg, PCIE_CORE_DEV_CTRL_STATS_REG);
120 +
121 +       /* Configure device MAX payload size */
122 +       advk_pcie_bus_configure_mps(bus->self, &smpss);
123 +       pci_walk_bus(bus, advk_pcie_bus_configure_mps, &smpss);
124 +}
125 +
126  static int advk_pcie_probe(struct platform_device *pdev)
127  {
128         struct device *dev = &pdev->dev;
129 @@ -1070,6 +1125,9 @@ static int advk_pcie_probe(struct platfo
130         list_for_each_entry(child, &bus->children, node)
131                 pcie_bus_configure_settings(child);
132  
133 +       /* Configure the MAX pay load size */
134 +       advk_pcie_configure_mps(bus, pcie);
135 +
136         pci_bus_add_devices(bus);
137         return 0;
138  }