6457deba0a339d93787d99df04e990e63beabcff
[oweals/openwrt.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