diff options
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r-- | drivers/net/ethernet/atheros/alx/main.c | 97 |
1 files changed, 53 insertions, 44 deletions
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index eccbacd96201..8935766829b1 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -573,19 +573,41 @@ static int alx_set_mac_address(struct net_device *netdev, void *data) return 0; } -static int alx_alloc_descriptors(struct alx_priv *alx) +static int alx_alloc_tx_ring(struct alx_priv *alx, struct alx_tx_queue *txq, + int offset) { - alx->txq.bufs = kcalloc(alx->tx_ringsz, - sizeof(struct alx_buffer), - GFP_KERNEL); - if (!alx->txq.bufs) + txq->bufs = kcalloc(alx->tx_ringsz, sizeof(struct alx_buffer), GFP_KERNEL); + if (!txq->bufs) return -ENOMEM; - alx->rxq.bufs = kcalloc(alx->rx_ringsz, - sizeof(struct alx_buffer), - GFP_KERNEL); - if (!alx->rxq.bufs) - goto out_free; + txq->tpd = alx->descmem.virt + offset; + txq->tpd_dma = alx->descmem.dma + offset; + offset += sizeof(struct alx_txd) * alx->tx_ringsz; + + return offset; +} + +static int alx_alloc_rx_ring(struct alx_priv *alx, struct alx_rx_queue *rxq, + int offset) +{ + rxq->bufs = kcalloc(alx->rx_ringsz, sizeof(struct alx_buffer), GFP_KERNEL); + if (!rxq->bufs) + return -ENOMEM; + + rxq->rrd = alx->descmem.virt + offset; + rxq->rrd_dma = alx->descmem.dma + offset; + offset += sizeof(struct alx_rrd) * alx->rx_ringsz; + + rxq->rfd = alx->descmem.virt + offset; + rxq->rfd_dma = alx->descmem.dma + offset; + offset += sizeof(struct alx_rfd) * alx->rx_ringsz; + + return offset; +} + +static int alx_alloc_rings(struct alx_priv *alx) +{ + int offset = 0; /* physical tx/rx ring descriptors * @@ -601,45 +623,23 @@ static int alx_alloc_descriptors(struct alx_priv *alx) &alx->descmem.dma, GFP_KERNEL); if (!alx->descmem.virt) - goto out_free; - - alx->txq.tpd = alx->descmem.virt; - alx->txq.tpd_dma = alx->descmem.dma; + return -ENOMEM; - /* alignment requirement for next block */ + /* alignment requirements */ BUILD_BUG_ON(sizeof(struct alx_txd) % 8); - - alx->rxq.rrd = - (void *)((u8 *)alx->descmem.virt + - sizeof(struct alx_txd) * alx->tx_ringsz); - alx->rxq.rrd_dma = alx->descmem.dma + - sizeof(struct alx_txd) * alx->tx_ringsz; - - /* alignment requirement for next block */ BUILD_BUG_ON(sizeof(struct alx_rrd) % 8); - alx->rxq.rfd = - (void *)((u8 *)alx->descmem.virt + - sizeof(struct alx_txd) * alx->tx_ringsz + - sizeof(struct alx_rrd) * alx->rx_ringsz); - alx->rxq.rfd_dma = alx->descmem.dma + - sizeof(struct alx_txd) * alx->tx_ringsz + - sizeof(struct alx_rrd) * alx->rx_ringsz; - - return 0; -out_free: - kfree(alx->txq.bufs); - kfree(alx->rxq.bufs); - return -ENOMEM; -} - -static int alx_alloc_rings(struct alx_priv *alx) -{ - int err; + offset = alx_alloc_tx_ring(alx, &alx->txq, offset); + if (offset < 0) { + netdev_err(alx->dev, "Allocation of tx buffer failed!\n"); + goto out_free; + } - err = alx_alloc_descriptors(alx); - if (err) - return err; + offset = alx_alloc_rx_ring(alx, &alx->rxq, offset); + if (offset < 0) { + netdev_err(alx->dev, "Allocation of rx buffer failed!\n"); + goto out_free; + } alx->int_mask &= ~ALX_ISR_ALL_QUEUES; alx->int_mask |= ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0; @@ -647,7 +647,16 @@ static int alx_alloc_rings(struct alx_priv *alx) netif_napi_add(alx->dev, &alx->napi, alx_poll, 64); alx_reinit_rings(alx); + return 0; +out_free: + kfree(alx->txq.bufs); + kfree(alx->rxq.bufs); + dma_free_coherent(&alx->hw.pdev->dev, + alx->descmem.size, + alx->descmem.virt, + alx->descmem.dma); + return -ENOMEM; } static void alx_free_rings(struct alx_priv *alx) |