diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 226 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-main.c | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe.h | 10 |
4 files changed, 209 insertions, 49 deletions
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index b3719f154637..ac3d319ffab3 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c | |||
@@ -481,17 +481,21 @@ static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata) | |||
481 | 481 | ||
482 | if (channel->tx_ring) { | 482 | if (channel->tx_ring) { |
483 | /* Enable the following Tx interrupts | 483 | /* Enable the following Tx interrupts |
484 | * TIE - Transmit Interrupt Enable (unless polling) | 484 | * TIE - Transmit Interrupt Enable (unless using |
485 | * per channel interrupts) | ||
485 | */ | 486 | */ |
486 | XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1); | 487 | if (!pdata->per_channel_irq) |
488 | XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1); | ||
487 | } | 489 | } |
488 | if (channel->rx_ring) { | 490 | if (channel->rx_ring) { |
489 | /* Enable following Rx interrupts | 491 | /* Enable following Rx interrupts |
490 | * RBUE - Receive Buffer Unavailable Enable | 492 | * RBUE - Receive Buffer Unavailable Enable |
491 | * RIE - Receive Interrupt Enable | 493 | * RIE - Receive Interrupt Enable (unless using |
494 | * per channel interrupts) | ||
492 | */ | 495 | */ |
493 | XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1); | 496 | XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1); |
494 | XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1); | 497 | if (!pdata->per_channel_irq) |
498 | XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1); | ||
495 | } | 499 | } |
496 | 500 | ||
497 | XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier); | 501 | XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier); |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 07e2d216323a..c3533e104c61 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c | |||
@@ -114,6 +114,7 @@ | |||
114 | * THE POSSIBILITY OF SUCH DAMAGE. | 114 | * THE POSSIBILITY OF SUCH DAMAGE. |
115 | */ | 115 | */ |
116 | 116 | ||
117 | #include <linux/platform_device.h> | ||
117 | #include <linux/spinlock.h> | 118 | #include <linux/spinlock.h> |
118 | #include <linux/tcp.h> | 119 | #include <linux/tcp.h> |
119 | #include <linux/if_vlan.h> | 120 | #include <linux/if_vlan.h> |
@@ -126,7 +127,8 @@ | |||
126 | #include "xgbe.h" | 127 | #include "xgbe.h" |
127 | #include "xgbe-common.h" | 128 | #include "xgbe-common.h" |
128 | 129 | ||
129 | static int xgbe_poll(struct napi_struct *, int); | 130 | static int xgbe_one_poll(struct napi_struct *, int); |
131 | static int xgbe_all_poll(struct napi_struct *, int); | ||
130 | static void xgbe_set_rx_mode(struct net_device *); | 132 | static void xgbe_set_rx_mode(struct net_device *); |
131 | 133 | ||
132 | static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) | 134 | static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) |
@@ -134,6 +136,7 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) | |||
134 | struct xgbe_channel *channel_mem, *channel; | 136 | struct xgbe_channel *channel_mem, *channel; |
135 | struct xgbe_ring *tx_ring, *rx_ring; | 137 | struct xgbe_ring *tx_ring, *rx_ring; |
136 | unsigned int count, i; | 138 | unsigned int count, i; |
139 | int ret = -ENOMEM; | ||
137 | 140 | ||
138 | count = max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count); | 141 | count = max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count); |
139 | 142 | ||
@@ -158,6 +161,19 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) | |||
158 | channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE + | 161 | channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE + |
159 | (DMA_CH_INC * i); | 162 | (DMA_CH_INC * i); |
160 | 163 | ||
164 | if (pdata->per_channel_irq) { | ||
165 | /* Get the DMA interrupt (offset 1) */ | ||
166 | ret = platform_get_irq(pdata->pdev, i + 1); | ||
167 | if (ret < 0) { | ||
168 | netdev_err(pdata->netdev, | ||
169 | "platform_get_irq %u failed\n", | ||
170 | i + 1); | ||
171 | goto err_irq; | ||
172 | } | ||
173 | |||
174 | channel->dma_irq = ret; | ||
175 | } | ||
176 | |||
161 | if (i < pdata->tx_ring_count) { | 177 | if (i < pdata->tx_ring_count) { |
162 | spin_lock_init(&tx_ring->lock); | 178 | spin_lock_init(&tx_ring->lock); |
163 | channel->tx_ring = tx_ring++; | 179 | channel->tx_ring = tx_ring++; |
@@ -168,9 +184,9 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) | |||
168 | channel->rx_ring = rx_ring++; | 184 | channel->rx_ring = rx_ring++; |
169 | } | 185 | } |
170 | 186 | ||
171 | DBGPR(" %s - queue_index=%u, dma_regs=%p, tx=%p, rx=%p\n", | 187 | DBGPR(" %s: queue=%u, dma_regs=%p, dma_irq=%d, tx=%p, rx=%p\n", |
172 | channel->name, channel->queue_index, channel->dma_regs, | 188 | channel->name, channel->queue_index, channel->dma_regs, |
173 | channel->tx_ring, channel->rx_ring); | 189 | channel->dma_irq, channel->tx_ring, channel->rx_ring); |
174 | } | 190 | } |
175 | 191 | ||
176 | pdata->channel = channel_mem; | 192 | pdata->channel = channel_mem; |
@@ -178,6 +194,9 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) | |||
178 | 194 | ||
179 | return 0; | 195 | return 0; |
180 | 196 | ||
197 | err_irq: | ||
198 | kfree(rx_ring); | ||
199 | |||
181 | err_rx_ring: | 200 | err_rx_ring: |
182 | kfree(tx_ring); | 201 | kfree(tx_ring); |
183 | 202 | ||
@@ -185,9 +204,7 @@ err_tx_ring: | |||
185 | kfree(channel_mem); | 204 | kfree(channel_mem); |
186 | 205 | ||
187 | err_channel: | 206 | err_channel: |
188 | netdev_err(pdata->netdev, "channel allocation failed\n"); | 207 | return ret; |
189 | |||
190 | return -ENOMEM; | ||
191 | } | 208 | } |
192 | 209 | ||
193 | static void xgbe_free_channels(struct xgbe_prv_data *pdata) | 210 | static void xgbe_free_channels(struct xgbe_prv_data *pdata) |
@@ -287,11 +304,7 @@ static irqreturn_t xgbe_isr(int irq, void *data) | |||
287 | if (!dma_isr) | 304 | if (!dma_isr) |
288 | goto isr_done; | 305 | goto isr_done; |
289 | 306 | ||
290 | DBGPR("-->xgbe_isr\n"); | ||
291 | |||
292 | DBGPR(" DMA_ISR = %08x\n", dma_isr); | 307 | DBGPR(" DMA_ISR = %08x\n", dma_isr); |
293 | DBGPR(" DMA_DS0 = %08x\n", XGMAC_IOREAD(pdata, DMA_DSR0)); | ||
294 | DBGPR(" DMA_DS1 = %08x\n", XGMAC_IOREAD(pdata, DMA_DSR1)); | ||
295 | 308 | ||
296 | for (i = 0; i < pdata->channel_count; i++) { | 309 | for (i = 0; i < pdata->channel_count; i++) { |
297 | if (!(dma_isr & (1 << i))) | 310 | if (!(dma_isr & (1 << i))) |
@@ -302,6 +315,10 @@ static irqreturn_t xgbe_isr(int irq, void *data) | |||
302 | dma_ch_isr = XGMAC_DMA_IOREAD(channel, DMA_CH_SR); | 315 | dma_ch_isr = XGMAC_DMA_IOREAD(channel, DMA_CH_SR); |
303 | DBGPR(" DMA_CH%u_ISR = %08x\n", i, dma_ch_isr); | 316 | DBGPR(" DMA_CH%u_ISR = %08x\n", i, dma_ch_isr); |
304 | 317 | ||
318 | /* If we get a TI or RI interrupt that means per channel DMA | ||
319 | * interrupts are not enabled, so we use the private data napi | ||
320 | * structure, not the per channel napi structure | ||
321 | */ | ||
305 | if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, TI) || | 322 | if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, TI) || |
306 | XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RI)) { | 323 | XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RI)) { |
307 | if (napi_schedule_prep(&pdata->napi)) { | 324 | if (napi_schedule_prep(&pdata->napi)) { |
@@ -344,12 +361,28 @@ static irqreturn_t xgbe_isr(int irq, void *data) | |||
344 | 361 | ||
345 | DBGPR(" DMA_ISR = %08x\n", XGMAC_IOREAD(pdata, DMA_ISR)); | 362 | DBGPR(" DMA_ISR = %08x\n", XGMAC_IOREAD(pdata, DMA_ISR)); |
346 | 363 | ||
347 | DBGPR("<--xgbe_isr\n"); | ||
348 | |||
349 | isr_done: | 364 | isr_done: |
350 | return IRQ_HANDLED; | 365 | return IRQ_HANDLED; |
351 | } | 366 | } |
352 | 367 | ||
368 | static irqreturn_t xgbe_dma_isr(int irq, void *data) | ||
369 | { | ||
370 | struct xgbe_channel *channel = data; | ||
371 | |||
372 | /* Per channel DMA interrupts are enabled, so we use the per | ||
373 | * channel napi structure and not the private data napi structure | ||
374 | */ | ||
375 | if (napi_schedule_prep(&channel->napi)) { | ||
376 | /* Disable Tx and Rx interrupts */ | ||
377 | disable_irq(channel->dma_irq); | ||
378 | |||
379 | /* Turn on polling */ | ||
380 | __napi_schedule(&channel->napi); | ||
381 | } | ||
382 | |||
383 | return IRQ_HANDLED; | ||
384 | } | ||
385 | |||
353 | static enum hrtimer_restart xgbe_tx_timer(struct hrtimer *timer) | 386 | static enum hrtimer_restart xgbe_tx_timer(struct hrtimer *timer) |
354 | { | 387 | { |
355 | struct xgbe_channel *channel = container_of(timer, | 388 | struct xgbe_channel *channel = container_of(timer, |
@@ -357,18 +390,24 @@ static enum hrtimer_restart xgbe_tx_timer(struct hrtimer *timer) | |||
357 | tx_timer); | 390 | tx_timer); |
358 | struct xgbe_ring *ring = channel->tx_ring; | 391 | struct xgbe_ring *ring = channel->tx_ring; |
359 | struct xgbe_prv_data *pdata = channel->pdata; | 392 | struct xgbe_prv_data *pdata = channel->pdata; |
393 | struct napi_struct *napi; | ||
360 | unsigned long flags; | 394 | unsigned long flags; |
361 | 395 | ||
362 | DBGPR("-->xgbe_tx_timer\n"); | 396 | DBGPR("-->xgbe_tx_timer\n"); |
363 | 397 | ||
398 | napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi; | ||
399 | |||
364 | spin_lock_irqsave(&ring->lock, flags); | 400 | spin_lock_irqsave(&ring->lock, flags); |
365 | 401 | ||
366 | if (napi_schedule_prep(&pdata->napi)) { | 402 | if (napi_schedule_prep(napi)) { |
367 | /* Disable Tx and Rx interrupts */ | 403 | /* Disable Tx and Rx interrupts */ |
368 | xgbe_disable_rx_tx_ints(pdata); | 404 | if (pdata->per_channel_irq) |
405 | disable_irq(channel->dma_irq); | ||
406 | else | ||
407 | xgbe_disable_rx_tx_ints(pdata); | ||
369 | 408 | ||
370 | /* Turn on polling */ | 409 | /* Turn on polling */ |
371 | __napi_schedule(&pdata->napi); | 410 | __napi_schedule(napi); |
372 | } | 411 | } |
373 | 412 | ||
374 | channel->tx_timer_active = 0; | 413 | channel->tx_timer_active = 0; |
@@ -504,18 +543,46 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata) | |||
504 | 543 | ||
505 | static void xgbe_napi_enable(struct xgbe_prv_data *pdata, unsigned int add) | 544 | static void xgbe_napi_enable(struct xgbe_prv_data *pdata, unsigned int add) |
506 | { | 545 | { |
507 | if (add) | 546 | struct xgbe_channel *channel; |
508 | netif_napi_add(pdata->netdev, &pdata->napi, xgbe_poll, | 547 | unsigned int i; |
509 | NAPI_POLL_WEIGHT); | 548 | |
510 | napi_enable(&pdata->napi); | 549 | if (pdata->per_channel_irq) { |
550 | channel = pdata->channel; | ||
551 | for (i = 0; i < pdata->channel_count; i++, channel++) { | ||
552 | if (add) | ||
553 | netif_napi_add(pdata->netdev, &channel->napi, | ||
554 | xgbe_one_poll, NAPI_POLL_WEIGHT); | ||
555 | |||
556 | napi_enable(&channel->napi); | ||
557 | } | ||
558 | } else { | ||
559 | if (add) | ||
560 | netif_napi_add(pdata->netdev, &pdata->napi, | ||
561 | xgbe_all_poll, NAPI_POLL_WEIGHT); | ||
562 | |||
563 | napi_enable(&pdata->napi); | ||
564 | } | ||
511 | } | 565 | } |
512 | 566 | ||
513 | static void xgbe_napi_disable(struct xgbe_prv_data *pdata, unsigned int del) | 567 | static void xgbe_napi_disable(struct xgbe_prv_data *pdata, unsigned int del) |
514 | { | 568 | { |
515 | napi_disable(&pdata->napi); | 569 | struct xgbe_channel *channel; |
570 | unsigned int i; | ||
571 | |||
572 | if (pdata->per_channel_irq) { | ||
573 | channel = pdata->channel; | ||
574 | for (i = 0; i < pdata->channel_count; i++, channel++) { | ||
575 | napi_disable(&channel->napi); | ||
516 | 576 | ||
517 | if (del) | 577 | if (del) |
518 | netif_napi_del(&pdata->napi); | 578 | netif_napi_del(&channel->napi); |
579 | } | ||
580 | } else { | ||
581 | napi_disable(&pdata->napi); | ||
582 | |||
583 | if (del) | ||
584 | netif_napi_del(&pdata->napi); | ||
585 | } | ||
519 | } | 586 | } |
520 | 587 | ||
521 | void xgbe_init_tx_coalesce(struct xgbe_prv_data *pdata) | 588 | void xgbe_init_tx_coalesce(struct xgbe_prv_data *pdata) |
@@ -828,7 +895,9 @@ static void xgbe_stop(struct xgbe_prv_data *pdata) | |||
828 | 895 | ||
829 | static void xgbe_restart_dev(struct xgbe_prv_data *pdata, unsigned int reset) | 896 | static void xgbe_restart_dev(struct xgbe_prv_data *pdata, unsigned int reset) |
830 | { | 897 | { |
898 | struct xgbe_channel *channel; | ||
831 | struct xgbe_hw_if *hw_if = &pdata->hw_if; | 899 | struct xgbe_hw_if *hw_if = &pdata->hw_if; |
900 | unsigned int i; | ||
832 | 901 | ||
833 | DBGPR("-->xgbe_restart_dev\n"); | 902 | DBGPR("-->xgbe_restart_dev\n"); |
834 | 903 | ||
@@ -837,7 +906,12 @@ static void xgbe_restart_dev(struct xgbe_prv_data *pdata, unsigned int reset) | |||
837 | return; | 906 | return; |
838 | 907 | ||
839 | xgbe_stop(pdata); | 908 | xgbe_stop(pdata); |
840 | synchronize_irq(pdata->irq_number); | 909 | synchronize_irq(pdata->dev_irq); |
910 | if (pdata->per_channel_irq) { | ||
911 | channel = pdata->channel; | ||
912 | for (i = 0; i < pdata->channel_count; i++, channel++) | ||
913 | synchronize_irq(channel->dma_irq); | ||
914 | } | ||
841 | 915 | ||
842 | xgbe_free_tx_data(pdata); | 916 | xgbe_free_tx_data(pdata); |
843 | xgbe_free_rx_data(pdata); | 917 | xgbe_free_rx_data(pdata); |
@@ -1165,6 +1239,9 @@ static int xgbe_open(struct net_device *netdev) | |||
1165 | struct xgbe_prv_data *pdata = netdev_priv(netdev); | 1239 | struct xgbe_prv_data *pdata = netdev_priv(netdev); |
1166 | struct xgbe_hw_if *hw_if = &pdata->hw_if; | 1240 | struct xgbe_hw_if *hw_if = &pdata->hw_if; |
1167 | struct xgbe_desc_if *desc_if = &pdata->desc_if; | 1241 | struct xgbe_desc_if *desc_if = &pdata->desc_if; |
1242 | struct xgbe_channel *channel = NULL; | ||
1243 | char dma_irq_name[IFNAMSIZ + 32]; | ||
1244 | unsigned int i = 0; | ||
1168 | int ret; | 1245 | int ret; |
1169 | 1246 | ||
1170 | DBGPR("-->xgbe_open\n"); | 1247 | DBGPR("-->xgbe_open\n"); |
@@ -1208,14 +1285,32 @@ static int xgbe_open(struct net_device *netdev) | |||
1208 | INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp); | 1285 | INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp); |
1209 | 1286 | ||
1210 | /* Request interrupts */ | 1287 | /* Request interrupts */ |
1211 | ret = devm_request_irq(pdata->dev, netdev->irq, xgbe_isr, 0, | 1288 | ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0, |
1212 | netdev->name, pdata); | 1289 | netdev->name, pdata); |
1213 | if (ret) { | 1290 | if (ret) { |
1214 | netdev_alert(netdev, "error requesting irq %d\n", | 1291 | netdev_alert(netdev, "error requesting irq %d\n", |
1215 | pdata->irq_number); | 1292 | pdata->dev_irq); |
1216 | goto err_rings; | 1293 | goto err_rings; |
1217 | } | 1294 | } |
1218 | pdata->irq_number = netdev->irq; | 1295 | |
1296 | if (pdata->per_channel_irq) { | ||
1297 | channel = pdata->channel; | ||
1298 | for (i = 0; i < pdata->channel_count; i++, channel++) { | ||
1299 | snprintf(dma_irq_name, sizeof(dma_irq_name) - 1, | ||
1300 | "%s-TxRx-%u", netdev_name(netdev), | ||
1301 | channel->queue_index); | ||
1302 | |||
1303 | ret = devm_request_irq(pdata->dev, channel->dma_irq, | ||
1304 | xgbe_dma_isr, 0, dma_irq_name, | ||
1305 | channel); | ||
1306 | if (ret) { | ||
1307 | netdev_alert(netdev, | ||
1308 | "error requesting irq %d\n", | ||
1309 | channel->dma_irq); | ||
1310 | goto err_irq; | ||
1311 | } | ||
1312 | } | ||
1313 | } | ||
1219 | 1314 | ||
1220 | ret = xgbe_start(pdata); | 1315 | ret = xgbe_start(pdata); |
1221 | if (ret) | 1316 | if (ret) |
@@ -1228,8 +1323,14 @@ static int xgbe_open(struct net_device *netdev) | |||
1228 | err_start: | 1323 | err_start: |
1229 | hw_if->exit(pdata); | 1324 | hw_if->exit(pdata); |
1230 | 1325 | ||
1231 | devm_free_irq(pdata->dev, pdata->irq_number, pdata); | 1326 | err_irq: |
1232 | pdata->irq_number = 0; | 1327 | if (pdata->per_channel_irq) { |
1328 | /* Using an unsigned int, 'i' will go to UINT_MAX and exit */ | ||
1329 | for (i--, channel--; i < pdata->channel_count; i--, channel--) | ||
1330 | devm_free_irq(pdata->dev, channel->dma_irq, channel); | ||
1331 | } | ||
1332 | |||
1333 | devm_free_irq(pdata->dev, pdata->dev_irq, pdata); | ||
1233 | 1334 | ||
1234 | err_rings: | 1335 | err_rings: |
1235 | desc_if->free_ring_resources(pdata); | 1336 | desc_if->free_ring_resources(pdata); |
@@ -1254,6 +1355,8 @@ static int xgbe_close(struct net_device *netdev) | |||
1254 | struct xgbe_prv_data *pdata = netdev_priv(netdev); | 1355 | struct xgbe_prv_data *pdata = netdev_priv(netdev); |
1255 | struct xgbe_hw_if *hw_if = &pdata->hw_if; | 1356 | struct xgbe_hw_if *hw_if = &pdata->hw_if; |
1256 | struct xgbe_desc_if *desc_if = &pdata->desc_if; | 1357 | struct xgbe_desc_if *desc_if = &pdata->desc_if; |
1358 | struct xgbe_channel *channel; | ||
1359 | unsigned int i; | ||
1257 | 1360 | ||
1258 | DBGPR("-->xgbe_close\n"); | 1361 | DBGPR("-->xgbe_close\n"); |
1259 | 1362 | ||
@@ -1269,10 +1372,12 @@ static int xgbe_close(struct net_device *netdev) | |||
1269 | /* Free the channel and ring structures */ | 1372 | /* Free the channel and ring structures */ |
1270 | xgbe_free_channels(pdata); | 1373 | xgbe_free_channels(pdata); |
1271 | 1374 | ||
1272 | /* Release the interrupt */ | 1375 | /* Release the interrupts */ |
1273 | if (pdata->irq_number != 0) { | 1376 | devm_free_irq(pdata->dev, pdata->dev_irq, pdata); |
1274 | devm_free_irq(pdata->dev, pdata->irq_number, pdata); | 1377 | if (pdata->per_channel_irq) { |
1275 | pdata->irq_number = 0; | 1378 | channel = pdata->channel; |
1379 | for (i = 0; i < pdata->channel_count; i++, channel++) | ||
1380 | devm_free_irq(pdata->dev, channel->dma_irq, channel); | ||
1276 | } | 1381 | } |
1277 | 1382 | ||
1278 | /* Disable the clocks */ | 1383 | /* Disable the clocks */ |
@@ -1505,14 +1610,20 @@ static int xgbe_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, | |||
1505 | static void xgbe_poll_controller(struct net_device *netdev) | 1610 | static void xgbe_poll_controller(struct net_device *netdev) |
1506 | { | 1611 | { |
1507 | struct xgbe_prv_data *pdata = netdev_priv(netdev); | 1612 | struct xgbe_prv_data *pdata = netdev_priv(netdev); |
1613 | struct xgbe_channel *channel; | ||
1614 | unsigned int i; | ||
1508 | 1615 | ||
1509 | DBGPR("-->xgbe_poll_controller\n"); | 1616 | DBGPR("-->xgbe_poll_controller\n"); |
1510 | 1617 | ||
1511 | disable_irq(pdata->irq_number); | 1618 | if (pdata->per_channel_irq) { |
1512 | 1619 | channel = pdata->channel; | |
1513 | xgbe_isr(pdata->irq_number, pdata); | 1620 | for (i = 0; i < pdata->channel_count; i++, channel++) |
1514 | 1621 | xgbe_dma_isr(channel->dma_irq, channel); | |
1515 | enable_irq(pdata->irq_number); | 1622 | } else { |
1623 | disable_irq(pdata->dev_irq); | ||
1624 | xgbe_isr(pdata->dev_irq, pdata); | ||
1625 | enable_irq(pdata->dev_irq); | ||
1626 | } | ||
1516 | 1627 | ||
1517 | DBGPR("<--xgbe_poll_controller\n"); | 1628 | DBGPR("<--xgbe_poll_controller\n"); |
1518 | } | 1629 | } |
@@ -1704,6 +1815,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) | |||
1704 | struct xgbe_ring_data *rdata; | 1815 | struct xgbe_ring_data *rdata; |
1705 | struct xgbe_packet_data *packet; | 1816 | struct xgbe_packet_data *packet; |
1706 | struct net_device *netdev = pdata->netdev; | 1817 | struct net_device *netdev = pdata->netdev; |
1818 | struct napi_struct *napi; | ||
1707 | struct sk_buff *skb; | 1819 | struct sk_buff *skb; |
1708 | struct skb_shared_hwtstamps *hwtstamps; | 1820 | struct skb_shared_hwtstamps *hwtstamps; |
1709 | unsigned int incomplete, error, context_next, context; | 1821 | unsigned int incomplete, error, context_next, context; |
@@ -1717,6 +1829,8 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) | |||
1717 | if (!ring) | 1829 | if (!ring) |
1718 | return 0; | 1830 | return 0; |
1719 | 1831 | ||
1832 | napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi; | ||
1833 | |||
1720 | rdata = XGBE_GET_DESC_DATA(ring, ring->cur); | 1834 | rdata = XGBE_GET_DESC_DATA(ring, ring->cur); |
1721 | packet = &ring->packet_data; | 1835 | packet = &ring->packet_data; |
1722 | while (packet_count < budget) { | 1836 | while (packet_count < budget) { |
@@ -1849,10 +1963,10 @@ read_again: | |||
1849 | skb->dev = netdev; | 1963 | skb->dev = netdev; |
1850 | skb->protocol = eth_type_trans(skb, netdev); | 1964 | skb->protocol = eth_type_trans(skb, netdev); |
1851 | skb_record_rx_queue(skb, channel->queue_index); | 1965 | skb_record_rx_queue(skb, channel->queue_index); |
1852 | skb_mark_napi_id(skb, &pdata->napi); | 1966 | skb_mark_napi_id(skb, napi); |
1853 | 1967 | ||
1854 | netdev->last_rx = jiffies; | 1968 | netdev->last_rx = jiffies; |
1855 | napi_gro_receive(&pdata->napi, skb); | 1969 | napi_gro_receive(napi, skb); |
1856 | 1970 | ||
1857 | next_packet: | 1971 | next_packet: |
1858 | packet_count++; | 1972 | packet_count++; |
@@ -1874,7 +1988,35 @@ next_packet: | |||
1874 | return packet_count; | 1988 | return packet_count; |
1875 | } | 1989 | } |
1876 | 1990 | ||
1877 | static int xgbe_poll(struct napi_struct *napi, int budget) | 1991 | static int xgbe_one_poll(struct napi_struct *napi, int budget) |
1992 | { | ||
1993 | struct xgbe_channel *channel = container_of(napi, struct xgbe_channel, | ||
1994 | napi); | ||
1995 | int processed = 0; | ||
1996 | |||
1997 | DBGPR("-->xgbe_one_poll: budget=%d\n", budget); | ||
1998 | |||
1999 | /* Cleanup Tx ring first */ | ||
2000 | xgbe_tx_poll(channel); | ||
2001 | |||
2002 | /* Process Rx ring next */ | ||
2003 | processed = xgbe_rx_poll(channel, budget); | ||
2004 | |||
2005 | /* If we processed everything, we are done */ | ||
2006 | if (processed < budget) { | ||
2007 | /* Turn off polling */ | ||
2008 | napi_complete(napi); | ||
2009 | |||
2010 | /* Enable Tx and Rx interrupts */ | ||
2011 | enable_irq(channel->dma_irq); | ||
2012 | } | ||
2013 | |||
2014 | DBGPR("<--xgbe_one_poll: received = %d\n", processed); | ||
2015 | |||
2016 | return processed; | ||
2017 | } | ||
2018 | |||
2019 | static int xgbe_all_poll(struct napi_struct *napi, int budget) | ||
1878 | { | 2020 | { |
1879 | struct xgbe_prv_data *pdata = container_of(napi, struct xgbe_prv_data, | 2021 | struct xgbe_prv_data *pdata = container_of(napi, struct xgbe_prv_data, |
1880 | napi); | 2022 | napi); |
@@ -1883,7 +2025,7 @@ static int xgbe_poll(struct napi_struct *napi, int budget) | |||
1883 | int processed, last_processed; | 2025 | int processed, last_processed; |
1884 | unsigned int i; | 2026 | unsigned int i; |
1885 | 2027 | ||
1886 | DBGPR("-->xgbe_poll: budget=%d\n", budget); | 2028 | DBGPR("-->xgbe_all_poll: budget=%d\n", budget); |
1887 | 2029 | ||
1888 | processed = 0; | 2030 | processed = 0; |
1889 | ring_budget = budget / pdata->rx_ring_count; | 2031 | ring_budget = budget / pdata->rx_ring_count; |
@@ -1911,7 +2053,7 @@ static int xgbe_poll(struct napi_struct *napi, int budget) | |||
1911 | xgbe_enable_rx_tx_ints(pdata); | 2053 | xgbe_enable_rx_tx_ints(pdata); |
1912 | } | 2054 | } |
1913 | 2055 | ||
1914 | DBGPR("<--xgbe_poll: received = %d\n", processed); | 2056 | DBGPR("<--xgbe_all_poll: received = %d\n", processed); |
1915 | 2057 | ||
1916 | return processed; | 2058 | return processed; |
1917 | } | 2059 | } |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c index e5077fd5b012..cff9902d1456 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c | |||
@@ -264,12 +264,18 @@ static int xgbe_probe(struct platform_device *pdev) | |||
264 | pdata->awcache = XGBE_DMA_SYS_AWCACHE; | 264 | pdata->awcache = XGBE_DMA_SYS_AWCACHE; |
265 | } | 265 | } |
266 | 266 | ||
267 | /* Check for per channel interrupt support */ | ||
268 | if (of_property_read_bool(dev->of_node, XGBE_DMA_IRQS)) | ||
269 | pdata->per_channel_irq = 1; | ||
270 | |||
267 | ret = platform_get_irq(pdev, 0); | 271 | ret = platform_get_irq(pdev, 0); |
268 | if (ret < 0) { | 272 | if (ret < 0) { |
269 | dev_err(dev, "platform_get_irq failed\n"); | 273 | dev_err(dev, "platform_get_irq 0 failed\n"); |
270 | goto err_io; | 274 | goto err_io; |
271 | } | 275 | } |
272 | netdev->irq = ret; | 276 | pdata->dev_irq = ret; |
277 | |||
278 | netdev->irq = pdata->dev_irq; | ||
273 | netdev->base_addr = (unsigned long)pdata->xgmac_regs; | 279 | netdev->base_addr = (unsigned long)pdata->xgmac_regs; |
274 | 280 | ||
275 | /* Set all the function pointers */ | 281 | /* Set all the function pointers */ |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 1480c9d41821..55c935f4884a 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h | |||
@@ -173,6 +173,7 @@ | |||
173 | /* Device-tree clock names */ | 173 | /* Device-tree clock names */ |
174 | #define XGBE_DMA_CLOCK "dma_clk" | 174 | #define XGBE_DMA_CLOCK "dma_clk" |
175 | #define XGBE_PTP_CLOCK "ptp_clk" | 175 | #define XGBE_PTP_CLOCK "ptp_clk" |
176 | #define XGBE_DMA_IRQS "amd,per-channel-interrupt" | ||
176 | 177 | ||
177 | /* Timestamp support - values based on 50MHz PTP clock | 178 | /* Timestamp support - values based on 50MHz PTP clock |
178 | * 50MHz => 20 nsec | 179 | * 50MHz => 20 nsec |
@@ -359,6 +360,12 @@ struct xgbe_channel { | |||
359 | unsigned int queue_index; | 360 | unsigned int queue_index; |
360 | void __iomem *dma_regs; | 361 | void __iomem *dma_regs; |
361 | 362 | ||
363 | /* Per channel interrupt irq number */ | ||
364 | int dma_irq; | ||
365 | |||
366 | /* Netdev related settings */ | ||
367 | struct napi_struct napi; | ||
368 | |||
362 | unsigned int saved_ier; | 369 | unsigned int saved_ier; |
363 | 370 | ||
364 | unsigned int tx_timer_active; | 371 | unsigned int tx_timer_active; |
@@ -609,7 +616,8 @@ struct xgbe_prv_data { | |||
609 | /* XPCS indirect addressing mutex */ | 616 | /* XPCS indirect addressing mutex */ |
610 | struct mutex xpcs_mutex; | 617 | struct mutex xpcs_mutex; |
611 | 618 | ||
612 | int irq_number; | 619 | int dev_irq; |
620 | unsigned int per_channel_irq; | ||
613 | 621 | ||
614 | struct xgbe_hw_if hw_if; | 622 | struct xgbe_hw_if hw_if; |
615 | struct xgbe_desc_if desc_if; | 623 | struct xgbe_desc_if desc_if; |