6457deba0a339d93787d99df04e990e63beabcff
[openwrt/staging/chunkeey.git] / target / linux / mediatek / patches-4.4 / 0073-net-next-mediatek-add-support-for-IRQ-grouping.patch
1 From e301da64a9fd2ebc24d4c9b2d184681ec833fd72 Mon Sep 17 00:00:00 2001
2 From: John Crispin <blogic@openwrt.org>
3 Date: Wed, 23 Mar 2016 18:31:48 +0100
4 Subject: [PATCH 73/78] net-next: mediatek: add support for IRQ grouping
5
6 The ethernet core has 3 IRQs. using the IRQ grouping registers we are able
7 to separate TX and RX IRQs, which allows us to service them on separate
8 cores. This patch splits the irq handler into 2 separate functiosn, one for
9 TX and another for RX. The TX housekeeping is split out of the NAPI handler.
10 Instead we use a tasklet to handle housekeeping.
11
12 Signed-off-by: John Crispin <blogic@openwrt.org>
13 ---
14 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 115 +++++++++++++++++----------
15 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 12 ++-
16 2 files changed, 86 insertions(+), 41 deletions(-)
17
18 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
19 index bbcd607..2097ae1 100644
20 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
21 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
22 @@ -757,7 +757,7 @@ drop:
23 }
24
25 static int mtk_poll_rx(struct napi_struct *napi, int budget,
26 - struct mtk_eth *eth, u32 rx_intr)
27 + struct mtk_eth *eth)
28 {
29 struct mtk_rx_ring *ring = &eth->rx_ring;
30 int idx = ring->calc_idx;
31 @@ -843,12 +843,12 @@ release_desc:
32 }
33
34 if (done < budget)
35 - mtk_w32(eth, rx_intr, MTK_QMTK_INT_STATUS);
36 + mtk_w32(eth, MTK_RX_DONE_INT, MTK_QMTK_INT_STATUS);
37
38 return done;
39 }
40
41 -static int mtk_poll_tx(struct mtk_eth *eth, int budget, bool *tx_again)
42 +static int mtk_poll_tx(struct mtk_eth *eth, int budget)
43 {
44 struct mtk_tx_ring *ring = &eth->tx_ring;
45 struct mtk_tx_dma *desc;
46 @@ -911,9 +911,7 @@ static int mtk_poll_tx(struct mtk_eth *eth, int budget, bool *tx_again)
47 }
48
49 /* read hw index again make sure no new tx packet */
50 - if (cpu != dma || cpu != mtk_r32(eth, MTK_QTX_DRX_PTR))
51 - *tx_again = true;
52 - else
53 + if (cpu == dma && cpu == mtk_r32(eth, MTK_QTX_DRX_PTR))
54 mtk_w32(eth, MTK_TX_DONE_INT, MTK_QMTK_INT_STATUS);
55
56 if (!total)
57 @@ -925,27 +923,27 @@ static int mtk_poll_tx(struct mtk_eth *eth, int budget, bool *tx_again)
58 return total;
59 }
60
61 +static void mtk_clean_tx_tasklet(unsigned long arg)
62 +{
63 + struct mtk_eth *eth = (struct mtk_eth *)arg;
64 +
65 + if (mtk_poll_tx(eth, MTK_NAPI_WEIGHT) > 0)
66 + tasklet_schedule(&eth->tx_clean_tasklet);
67 + else
68 + mtk_irq_enable(eth, MTK_TX_DONE_INT);
69 +}
70 +
71 static int mtk_poll(struct napi_struct *napi, int budget)
72 {
73 struct mtk_eth *eth = container_of(napi, struct mtk_eth, rx_napi);
74 - u32 status, status2, mask, tx_intr, rx_intr, status_intr;
75 - int tx_done, rx_done;
76 - bool tx_again = false;
77 + u32 status, status2, mask, status_intr;
78 + int rx_done = 0;
79
80 status = mtk_r32(eth, MTK_QMTK_INT_STATUS);
81 status2 = mtk_r32(eth, MTK_INT_STATUS2);
82 - tx_intr = MTK_TX_DONE_INT;
83 - rx_intr = MTK_RX_DONE_INT;
84 status_intr = (MTK_GDM1_AF | MTK_GDM2_AF);
85 - tx_done = 0;
86 - rx_done = 0;
87 - tx_again = 0;
88
89 - if (status & tx_intr)
90 - tx_done = mtk_poll_tx(eth, budget, &tx_again);
91 -
92 - if (status & rx_intr)
93 - rx_done = mtk_poll_rx(napi, budget, eth, rx_intr);
94 + rx_done = mtk_poll_rx(napi, budget, eth);
95
96 if (unlikely(status2 & status_intr)) {
97 mtk_stats_update(eth);
98 @@ -954,20 +952,20 @@ static int mtk_poll(struct napi_struct *napi, int budget)
99
100 if (unlikely(netif_msg_intr(eth))) {
101 mask = mtk_r32(eth, MTK_QDMA_INT_MASK);
102 - netdev_info(eth->netdev[0],
103 - "done tx %d, rx %d, intr 0x%08x/0x%x\n",
104 - tx_done, rx_done, status, mask);
105 + dev_info(eth->dev,
106 + "done rx %d, intr 0x%08x/0x%x\n",
107 + rx_done, status, mask);
108 }
109
110 - if (tx_again || rx_done == budget)
111 + if (rx_done == budget)
112 return budget;
113
114 status = mtk_r32(eth, MTK_QMTK_INT_STATUS);
115 - if (status & (tx_intr | rx_intr))
116 + if (status & MTK_RX_DONE_INT)
117 return budget;
118
119 napi_complete(napi);
120 - mtk_irq_enable(eth, tx_intr | rx_intr);
121 + mtk_irq_enable(eth, MTK_RX_DONE_INT);
122
123 return rx_done;
124 }
125 @@ -1196,22 +1194,43 @@ static void mtk_tx_timeout(struct net_device *dev)
126 schedule_work(&eth->pending_work);
127 }
128
129 -static irqreturn_t mtk_handle_irq(int irq, void *_eth)
130 +static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth)
131 {
132 struct mtk_eth *eth = _eth;
133 u32 status;
134
135 status = mtk_r32(eth, MTK_QMTK_INT_STATUS);
136 + status &= ~MTK_TX_DONE_INT;
137 +
138 if (unlikely(!status))
139 return IRQ_NONE;
140
141 - if (likely(status & (MTK_RX_DONE_INT | MTK_TX_DONE_INT))) {
142 + if (status & MTK_RX_DONE_INT) {
143 if (likely(napi_schedule_prep(&eth->rx_napi)))
144 __napi_schedule(&eth->rx_napi);
145 - } else {
146 - mtk_w32(eth, status, MTK_QMTK_INT_STATUS);
147 + mtk_irq_disable(eth, MTK_RX_DONE_INT);
148 }
149 - mtk_irq_disable(eth, (MTK_RX_DONE_INT | MTK_TX_DONE_INT));
150 + mtk_w32(eth, status, MTK_QMTK_INT_STATUS);
151 +
152 + return IRQ_HANDLED;
153 +}
154 +
155 +static irqreturn_t mtk_handle_irq_tx(int irq, void *_eth)
156 +{
157 + struct mtk_eth *eth = _eth;
158 + u32 status;
159 +
160 + status = mtk_r32(eth, MTK_QMTK_INT_STATUS);
161 + status &= ~MTK_RX_DONE_INT;
162 +
163 + if (unlikely(!status))
164 + return IRQ_NONE;
165 +
166 + if (status & MTK_TX_DONE_INT) {
167 + tasklet_schedule(&eth->tx_clean_tasklet);
168 + mtk_irq_disable(eth, MTK_TX_DONE_INT);
169 + }
170 + mtk_w32(eth, status, MTK_QMTK_INT_STATUS);
171
172 return IRQ_HANDLED;
173 }
174 @@ -1224,7 +1243,7 @@ static void mtk_poll_controller(struct net_device *dev)
175 u32 int_mask = MTK_TX_DONE_INT | MTK_RX_DONE_INT;
176
177 mtk_irq_disable(eth, int_mask);
178 - mtk_handle_irq(dev->irq, dev);
179 + mtk_handle_irq(dev->irq[0], dev);
180 mtk_irq_enable(eth, int_mask);
181 }
182 #endif
183 @@ -1345,7 +1364,11 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
184 /* Enable RX VLan Offloading */
185 mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
186
187 - err = devm_request_irq(eth->dev, eth->irq, mtk_handle_irq, 0,
188 + err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
189 + dev_name(eth->dev), eth);
190 + if (err)
191 + return err;
192 + err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
193 dev_name(eth->dev), eth);
194 if (err)
195 return err;
196 @@ -1361,7 +1384,11 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
197 mtk_w32(eth, 0, MTK_RST_GL);
198
199 /* FE int grouping */
200 - mtk_w32(eth, 0, MTK_FE_INT_GRP);
201 + mtk_w32(eth, MTK_TX_DONE_INT, MTK_PDMA_INT_GRP1);
202 + mtk_w32(eth, MTK_RX_DONE_INT, MTK_PDMA_INT_GRP2);
203 + mtk_w32(eth, MTK_TX_DONE_INT, MTK_QDMA_INT_GRP1);
204 + mtk_w32(eth, MTK_RX_DONE_INT, MTK_QDMA_INT_GRP2);
205 + mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP);
206
207 for (i = 0; i < 2; i++) {
208 u32 val = mtk_r32(eth, MTK_GDMA_FWD_CFG(i));
209 @@ -1409,7 +1436,9 @@ static void mtk_uninit(struct net_device *dev)
210 phy_disconnect(mac->phy_dev);
211 mtk_mdio_cleanup(eth);
212 mtk_irq_disable(eth, ~0);
213 - free_irq(dev->irq, dev);
214 + free_irq(eth->irq[0], dev);
215 + free_irq(eth->irq[1], dev);
216 + free_irq(eth->irq[2], dev);
217 }
218
219 static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
220 @@ -1684,10 +1713,10 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
221 dev_err(eth->dev, "error bringing up device\n");
222 goto free_netdev;
223 }
224 - eth->netdev[id]->irq = eth->irq;
225 + eth->netdev[id]->irq = eth->irq[0];
226 netif_info(eth, probe, eth->netdev[id],
227 "mediatek frame engine at 0x%08lx, irq %d\n",
228 - eth->netdev[id]->base_addr, eth->netdev[id]->irq);
229 + eth->netdev[id]->base_addr, eth->irq[0]);
230
231 return 0;
232
233 @@ -1704,6 +1733,7 @@ static int mtk_probe(struct platform_device *pdev)
234 struct mtk_soc_data *soc;
235 struct mtk_eth *eth;
236 int err;
237 + int i;
238
239 match = of_match_device(of_mtk_match, &pdev->dev);
240 soc = (struct mtk_soc_data *)match->data;
241 @@ -1738,10 +1768,12 @@ static int mtk_probe(struct platform_device *pdev)
242 return PTR_ERR(eth->rstc);
243 }
244
245 - eth->irq = platform_get_irq(pdev, 0);
246 - if (eth->irq < 0) {
247 - dev_err(&pdev->dev, "no IRQ resource found\n");
248 - return -ENXIO;
249 + for (i = 0; i < 3; i++) {
250 + eth->irq[i] = platform_get_irq(pdev, i);
251 + if (eth->irq[i] < 0) {
252 + dev_err(&pdev->dev, "no IRQ%d resource found\n", i);
253 + return -ENXIO;
254 + }
255 }
256
257 eth->clk_ethif = devm_clk_get(&pdev->dev, "ethif");
258 @@ -1785,6 +1817,9 @@ static int mtk_probe(struct platform_device *pdev)
259 netif_napi_add(&eth->dummy_dev, &eth->rx_napi, mtk_poll,
260 MTK_NAPI_WEIGHT);
261
262 + tasklet_init(&eth->tx_clean_tasklet,
263 + mtk_clean_tx_tasklet, (unsigned long)eth);
264 +
265 platform_set_drvdata(pdev, eth);
266
267 return 0;
268 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
269 index eed626d..4cfb40c 100644
270 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
271 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
272 @@ -68,6 +68,10 @@
273 /* Unicast Filter MAC Address Register - High */
274 #define MTK_GDMA_MAC_ADRH(x) (0x50C + (x * 0x1000))
275
276 +/* PDMA Interrupt grouping registers */
277 +#define MTK_PDMA_INT_GRP1 0xa50
278 +#define MTK_PDMA_INT_GRP2 0xa54
279 +
280 /* QDMA TX Queue Configuration Registers */
281 #define MTK_QTX_CFG(x) (0x1800 + (x * 0x10))
282 #define QDMA_RES_THRES 4
283 @@ -124,6 +128,11 @@
284 #define MTK_TX_DONE_INT (MTK_TX_DONE_INT0 | MTK_TX_DONE_INT1 | \
285 MTK_TX_DONE_INT2 | MTK_TX_DONE_INT3)
286
287 +/* QDMA Interrupt grouping registers */
288 +#define MTK_QDMA_INT_GRP1 0x1a20
289 +#define MTK_QDMA_INT_GRP2 0x1a24
290 +#define MTK_RLS_DONE_INT BIT(0)
291 +
292 /* QDMA Interrupt Status Register */
293 #define MTK_QDMA_INT_MASK 0x1A1C
294
295 @@ -374,7 +383,7 @@ struct mtk_eth {
296 struct net_device dummy_dev;
297 struct net_device *netdev[MTK_MAX_DEVS];
298 struct mtk_mac *mac[MTK_MAX_DEVS];
299 - int irq;
300 + int irq[3];
301 u32 msg_enable;
302 unsigned long sysclk;
303 struct regmap *ethsys;
304 @@ -391,6 +400,7 @@ struct mtk_eth {
305 struct clk *clk_gp2;
306 struct mii_bus *mii_bus;
307 struct work_struct pending_work;
308 + struct tasklet_struct tx_clean_tasklet;
309 };
310
311 /* struct mtk_mac - the structure that holds the info about the MACs of the
312 --
313 1.7.10.4
314