diff options
| author | Lendacky, Thomas <Thomas.Lendacky@amd.com> | 2014-11-04 17:06:56 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-11-05 21:50:12 -0500 |
| commit | 9227dc5e579b6b2ef58ad0d3d0d23ddac77846ef (patch) | |
| tree | cef535601eda5a1c79f6d6d96bf2b752993d72bb /drivers/net | |
| parent | 174fd2597b0bd8c19fce6a97e8b0f753ef4ce7cb (diff) | |
amd-xgbe: Add support for per DMA channel interrupts
This patch provides support for interrupts that are generated by the
Tx/Rx DMA channel pairs of the device. This allows for Tx and Rx
processing to run across multiple processsors.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
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; |
