aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-5.4/812-pcie-0014-PCI-mobiveil-ls_pcie_g4-add-Workaround-for-A-011451.patch
blob: 5486bdd0030913058cec24804f5105f0cad5a6e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
From 5f1673ff67d5e8acf590fb5a4cc2d0d5d4115927 Mon Sep 17 00:00:00 2001
From: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
Date: Tue, 6 Nov 2018 10:14:57 +0800
Subject: [PATCH] PCI: mobiveil: ls_pcie_g4: add Workaround for A-011451

When LX2 PCIe controller is sending multiple split completions and
ACK latency expires indicating that ACK should be send at priority.
But because of large number of split completions and FC update DLLP,
the controller does not give priority to ACK transmission. This
results into ACK latency timer timeout error at the link partner and
the pending TLPs are replayed by the link partner again.

Workaround:
1. Reduce the ACK latency timeout value to a very small value.
2. Restrict the number of completions from the LX2 PCIe controller
   to 1, by changing the Max Read Request Size (MRRS) of link partner
   to the same value as Max Packet size (MPS).

This patch implemented part 1, the part 2 can be set by kernel parameter
'pci=pcie_bus_perf'

This ERRATA is only for LX2160A Rev1.0, and it will be fixed
in Rev2.0.

Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
---
 drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c | 15 +++++++++++++++
 drivers/pci/controller/mobiveil/pcie-mobiveil.h        |  4 ++++
 2 files changed, 19 insertions(+)

--- a/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
+++ b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
@@ -80,12 +80,27 @@ static bool ls_pcie_g4_is_bridge(struct
 	return header_type == PCI_HEADER_TYPE_BRIDGE;
 }
 
+static void workaround_A011451(struct ls_pcie_g4 *pcie)
+{
+	struct mobiveil_pcie *mv_pci = &pcie->pci;
+	u32 val;
+
+	/* Set ACK latency timeout */
+	val = csr_readl(mv_pci, GPEX_ACK_REPLAY_TO);
+	val &= ~(ACK_LAT_TO_VAL_MASK << ACK_LAT_TO_VAL_SHIFT);
+	val |= (4 << ACK_LAT_TO_VAL_SHIFT);
+	csr_writel(mv_pci, val, GPEX_ACK_REPLAY_TO);
+}
+
 static int ls_pcie_g4_host_init(struct mobiveil_pcie *pci)
 {
 	struct ls_pcie_g4 *pcie = to_ls_pcie_g4(pci);
 
 	pcie->rev = csr_readb(pci, PCI_REVISION_ID);
 
+	if (pcie->rev == REV_1_0)
+		workaround_A011451(pcie);
+
 	return 0;
 }
 
--- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
@@ -86,6 +86,10 @@
 #define PAB_AXI_AMAP_PEX_WIN_H(win)	PAB_REG_ADDR(0x0bac, win)
 #define PAB_INTP_AXI_PIO_CLASS		0x474
 
+#define GPEX_ACK_REPLAY_TO		0x438
+#define  ACK_LAT_TO_VAL_MASK		0x1fff
+#define  ACK_LAT_TO_VAL_SHIFT		0
+
 #define PAB_PEX_AMAP_CTRL(win)		PAB_REG_ADDR(0x4ba0, win)
 #define  AMAP_CTRL_EN_SHIFT		0
 #define  AMAP_CTRL_TYPE_SHIFT		1
+ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; + + return rt2800ops->hw_get_chipver(); +} + +static inline int rt2800_hw_get_chipeco(struct rt2x00_dev *rt2x00dev) +{ + const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; + + return rt2800ops->hw_get_chipeco(); +} + void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, const u8 command, const u8 token, const u8 arg0, const u8 arg1); --- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c @@ -286,6 +286,10 @@ static int rt2800pci_read_eeprom(struct return retval; } +static int rt2800pci_get_chippkg(void) { return 0; } +static int rt2800pci_get_chipver(void) { return 0; } +static int rt2800pci_get_chipeco(void) { return 0; } + static const struct ieee80211_ops rt2800pci_mac80211_ops = { .tx = rt2x00mac_tx, .start = rt2x00mac_start, @@ -328,6 +332,9 @@ static const struct rt2800_ops rt2800pci .drv_init_registers = rt2800mmio_init_registers, .drv_get_txwi = rt2800mmio_get_txwi, .drv_get_dma_done = rt2800mmio_get_dma_done, + .hw_get_chippkg = rt2800pci_get_chippkg, + .hw_get_chipver = rt2800pci_get_chipver, + .hw_get_chipeco = rt2800pci_get_chipeco, }; static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { --- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c @@ -27,6 +27,12 @@ #include "rt2800lib.h" #include "rt2800mmio.h" +/* Needed to probe CHIP_VER register on MT7620 */ +#ifdef CONFIG_SOC_MT7620 +#include <asm/mach-ralink/ralink_regs.h> +#include <asm/mach-ralink/mt7620.h> +#endif + /* Allow hardware encryption to be disabled. */ static bool modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, 0444); @@ -118,6 +124,27 @@ static int rt2800soc_write_firmware(stru return 0; } +#ifdef CONFIG_SOC_MT7620 +static int rt2800soc_get_chippkg(void) +{ + return mt7620_get_pkg(); +} + +static int rt2800soc_get_chipver(void) +{ + return mt7620_get_chipver(); +} + +static int rt2800soc_get_chipeco(void) +{ + return mt7620_get_eco(); +} +#else +static int rt2800soc_get_chippkg(void) { return 0; } +static int rt2800soc_get_chipver(void) { return 0; } +static int rt2800soc_get_chipeco(void) { return 0; } +#endif + static const struct ieee80211_ops rt2800soc_mac80211_ops = { .tx = rt2x00mac_tx, .start = rt2x00mac_start, @@ -159,6 +186,9 @@ static const struct rt2800_ops rt2800soc .drv_init_registers = rt2800mmio_init_registers, .drv_get_txwi = rt2800mmio_get_txwi, .drv_get_dma_done = rt2800mmio_get_dma_done, + .hw_get_chippkg = rt2800soc_get_chippkg, + .hw_get_chipver = rt2800soc_get_chipver, + .hw_get_chipeco = rt2800soc_get_chipeco, }; static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = { --- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c @@ -628,6 +628,10 @@ static int rt2800usb_probe_hw(struct rt2 return 0; } +static int rt2800usb_get_chippkg(void) { return 0; } +static int rt2800usb_get_chipver(void) { return 0; } +static int rt2800usb_get_chipeco(void) { return 0; } + static const struct ieee80211_ops rt2800usb_mac80211_ops = { .tx = rt2x00mac_tx, .start = rt2x00mac_start, @@ -671,6 +675,9 @@ static const struct rt2800_ops rt2800usb .drv_init_registers = rt2800usb_init_registers, .drv_get_txwi = rt2800usb_get_txwi, .drv_get_dma_done = rt2800usb_get_dma_done, + .hw_get_chippkg = rt2800usb_get_chippkg, + .hw_get_chipver = rt2800usb_get_chipver, + .hw_get_chipeco = rt2800usb_get_chipeco, }; static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {