diff options
-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) | |||
573 | return 0; | 573 | return 0; |
574 | } | 574 | } |
575 | 575 | ||
576 | static int alx_alloc_descriptors(struct alx_priv *alx) | 576 | static int alx_alloc_tx_ring(struct alx_priv *alx, struct alx_tx_queue *txq, |
577 | int offset) | ||
577 | { | 578 | { |
578 | alx->txq.bufs = kcalloc(alx->tx_ringsz, | 579 | txq->bufs = kcalloc(alx->tx_ringsz, sizeof(struct alx_buffer), GFP_KERNEL); |
579 | sizeof(struct alx_buffer), | 580 | if (!txq->bufs) |
580 | GFP_KERNEL); | ||
581 | if (!alx->txq.bufs) | ||
582 | return -ENOMEM; | 581 | return -ENOMEM; |
583 | 582 | ||
584 | alx->rxq.bufs = kcalloc(alx->rx_ringsz, | 583 | txq->tpd = alx->descmem.virt + offset; |
585 | sizeof(struct alx_buffer), | 584 | txq->tpd_dma = alx->descmem.dma + offset; |
586 | GFP_KERNEL); | 585 | offset += sizeof(struct alx_txd) * alx->tx_ringsz; |
587 | if (!alx->rxq.bufs) | 586 | |
588 | goto out_free; | 587 | return offset; |
588 | } | ||
589 | |||
590 | static int alx_alloc_rx_ring(struct alx_priv *alx, struct alx_rx_queue *rxq, | ||
591 | int offset) | ||
592 | { | ||
593 | rxq->bufs = kcalloc(alx->rx_ringsz, sizeof(struct alx_buffer), GFP_KERNEL); | ||
594 | if (!rxq->bufs) | ||
595 | return -ENOMEM; | ||
596 | |||
597 | rxq->rrd = alx->descmem.virt + offset; | ||
598 | rxq->rrd_dma = alx->descmem.dma + offset; | ||
599 | offset += sizeof(struct alx_rrd) * alx->rx_ringsz; | ||
600 | |||
601 | rxq->rfd = alx->descmem.virt + offset; | ||
602 | rxq->rfd_dma = alx->descmem.dma + offset; | ||
603 | offset += sizeof(struct alx_rfd) * alx->rx_ringsz; | ||
604 | |||
605 | return offset; | ||
606 | } | ||
607 | |||
608 | static int alx_alloc_rings(struct alx_priv *alx) | ||
609 | { | ||
610 | int offset = 0; | ||
589 | 611 | ||
590 | /* physical tx/rx ring descriptors | 612 | /* physical tx/rx ring descriptors |
591 | * | 613 | * |
@@ -601,45 +623,23 @@ static int alx_alloc_descriptors(struct alx_priv *alx) | |||
601 | &alx->descmem.dma, | 623 | &alx->descmem.dma, |
602 | GFP_KERNEL); | 624 | GFP_KERNEL); |
603 | if (!alx->descmem.virt) | 625 | if (!alx->descmem.virt) |
604 | goto out_free; | 626 | return -ENOMEM; |
605 | |||
606 | alx->txq.tpd = alx->descmem.virt; | ||
607 | alx->txq.tpd_dma = alx->descmem.dma; | ||
608 | 627 | ||
609 | /* alignment requirement for next block */ | 628 | /* alignment requirements */ |
610 | BUILD_BUG_ON(sizeof(struct alx_txd) % 8); | 629 | BUILD_BUG_ON(sizeof(struct alx_txd) % 8); |
611 | |||
612 | alx->rxq.rrd = | ||
613 | (void *)((u8 *)alx->descmem.virt + | ||
614 | sizeof(struct alx_txd) * alx->tx_ringsz); | ||
615 | alx->rxq.rrd_dma = alx->descmem.dma + | ||
616 | sizeof(struct alx_txd) * alx->tx_ringsz; | ||
617 | |||
618 | /* alignment requirement for next block */ | ||
619 | BUILD_BUG_ON(sizeof(struct alx_rrd) % 8); | 630 | BUILD_BUG_ON(sizeof(struct alx_rrd) % 8); |
620 | 631 | ||
621 | alx->rxq.rfd = | 632 | offset = alx_alloc_tx_ring(alx, &alx->txq, offset); |
622 | (void *)((u8 *)alx->descmem.virt + | 633 | if (offset < 0) { |
623 | sizeof(struct alx_txd) * alx->tx_ringsz + | 634 | netdev_err(alx->dev, "Allocation of tx buffer failed!\n"); |
624 | sizeof(struct alx_rrd) * alx->rx_ringsz); | 635 | goto out_free; |
625 | alx->rxq.rfd_dma = alx->descmem.dma + | 636 | } |
626 | sizeof(struct alx_txd) * alx->tx_ringsz + | ||
627 | sizeof(struct alx_rrd) * alx->rx_ringsz; | ||
628 | |||
629 | return 0; | ||
630 | out_free: | ||
631 | kfree(alx->txq.bufs); | ||
632 | kfree(alx->rxq.bufs); | ||
633 | return -ENOMEM; | ||
634 | } | ||
635 | |||
636 | static int alx_alloc_rings(struct alx_priv *alx) | ||
637 | { | ||
638 | int err; | ||
639 | 637 | ||
640 | err = alx_alloc_descriptors(alx); | 638 | offset = alx_alloc_rx_ring(alx, &alx->rxq, offset); |
641 | if (err) | 639 | if (offset < 0) { |
642 | return err; | 640 | netdev_err(alx->dev, "Allocation of rx buffer failed!\n"); |
641 | goto out_free; | ||
642 | } | ||
643 | 643 | ||
644 | alx->int_mask &= ~ALX_ISR_ALL_QUEUES; | 644 | alx->int_mask &= ~ALX_ISR_ALL_QUEUES; |
645 | alx->int_mask |= ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0; | 645 | alx->int_mask |= ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0; |
@@ -647,7 +647,16 @@ static int alx_alloc_rings(struct alx_priv *alx) | |||
647 | netif_napi_add(alx->dev, &alx->napi, alx_poll, 64); | 647 | netif_napi_add(alx->dev, &alx->napi, alx_poll, 64); |
648 | 648 | ||
649 | alx_reinit_rings(alx); | 649 | alx_reinit_rings(alx); |
650 | |||
650 | return 0; | 651 | return 0; |
652 | out_free: | ||
653 | kfree(alx->txq.bufs); | ||
654 | kfree(alx->rxq.bufs); | ||
655 | dma_free_coherent(&alx->hw.pdev->dev, | ||
656 | alx->descmem.size, | ||
657 | alx->descmem.virt, | ||
658 | alx->descmem.dma); | ||
659 | return -ENOMEM; | ||
651 | } | 660 | } |
652 | 661 | ||
653 | static void alx_free_rings(struct alx_priv *alx) | 662 | static void alx_free_rings(struct alx_priv *alx) |