aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/atheros/alx/main.c99
1 files changed, 78 insertions, 21 deletions
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index 8935766829b1..193da6799979 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -632,45 +632,96 @@ static int alx_alloc_rings(struct alx_priv *alx)
632 offset = alx_alloc_tx_ring(alx, &alx->txq, offset); 632 offset = alx_alloc_tx_ring(alx, &alx->txq, offset);
633 if (offset < 0) { 633 if (offset < 0) {
634 netdev_err(alx->dev, "Allocation of tx buffer failed!\n"); 634 netdev_err(alx->dev, "Allocation of tx buffer failed!\n");
635 goto out_free; 635 return -ENOMEM;
636 } 636 }
637 637
638 offset = alx_alloc_rx_ring(alx, &alx->rxq, offset); 638 offset = alx_alloc_rx_ring(alx, &alx->rxq, offset);
639 if (offset < 0) { 639 if (offset < 0) {
640 netdev_err(alx->dev, "Allocation of rx buffer failed!\n"); 640 netdev_err(alx->dev, "Allocation of rx buffer failed!\n");
641 goto out_free; 641 return -ENOMEM;
642 } 642 }
643 643
644 alx->int_mask &= ~ALX_ISR_ALL_QUEUES;
645 alx->int_mask |= ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0;
646
647 netif_napi_add(alx->dev, &alx->napi, alx_poll, 64);
648
649 alx_reinit_rings(alx); 644 alx_reinit_rings(alx);
650 645
651 return 0; 646 return 0;
652out_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;
660} 647}
661 648
662static void alx_free_rings(struct alx_priv *alx) 649static void alx_free_rings(struct alx_priv *alx)
663{ 650{
664 netif_napi_del(&alx->napi);
665 alx_free_buffers(alx); 651 alx_free_buffers(alx);
666 652
667 kfree(alx->txq.bufs); 653 kfree(alx->txq.bufs);
668 kfree(alx->rxq.bufs); 654 kfree(alx->rxq.bufs);
669 655
670 dma_free_coherent(&alx->hw.pdev->dev, 656 if (!alx->descmem.virt)
671 alx->descmem.size, 657 dma_free_coherent(&alx->hw.pdev->dev,
672 alx->descmem.virt, 658 alx->descmem.size,
673 alx->descmem.dma); 659 alx->descmem.virt,
660 alx->descmem.dma);
661}
662
663static void alx_free_napis(struct alx_priv *alx)
664{
665 struct alx_napi *np;
666
667 np = alx->qnapi[0];
668 if (!np)
669 return;
670
671 netif_napi_del(&alx->napi);
672 kfree(np->txq);
673 kfree(np->rxq);
674 kfree(np);
675 alx->qnapi[0] = NULL;
676}
677
678static int alx_alloc_napis(struct alx_priv *alx)
679{
680 struct alx_napi *np;
681 struct alx_rx_queue *rxq;
682 struct alx_tx_queue *txq;
683
684 alx->int_mask &= ~ALX_ISR_ALL_QUEUES;
685 alx->int_mask |= ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0;
686
687 /* allocate alx_napi structures */
688 np = kzalloc(sizeof(struct alx_napi), GFP_KERNEL);
689 if (!np)
690 goto err_out;
691
692 np->alx = alx;
693 netif_napi_add(alx->dev, &alx->napi, alx_poll, 64);
694 alx->qnapi[0] = np;
695
696 /* allocate tx queues */
697 np = alx->qnapi[0];
698 txq = kzalloc(sizeof(*txq), GFP_KERNEL);
699 if (!txq)
700 goto err_out;
701
702 np->txq = txq;
703 txq->count = alx->tx_ringsz;
704 txq->netdev = alx->dev;
705 txq->dev = &alx->hw.pdev->dev;
706
707 /* allocate rx queues */
708 np = alx->qnapi[0];
709 rxq = kzalloc(sizeof(*rxq), GFP_KERNEL);
710 if (!rxq)
711 goto err_out;
712
713 np->rxq = rxq;
714 rxq->np = alx->qnapi[0];
715 rxq->count = alx->rx_ringsz;
716 rxq->netdev = alx->dev;
717 rxq->dev = &alx->hw.pdev->dev;
718
719 return 0;
720
721err_out:
722 netdev_err(alx->dev, "error allocating internal structures\n");
723 alx_free_napis(alx);
724 return -ENOMEM;
674} 725}
675 726
676static void alx_config_vector_mapping(struct alx_priv *alx) 727static void alx_config_vector_mapping(struct alx_priv *alx)
@@ -1031,10 +1082,14 @@ static int __alx_open(struct alx_priv *alx, bool resume)
1031 if (!resume) 1082 if (!resume)
1032 netif_carrier_off(alx->dev); 1083 netif_carrier_off(alx->dev);
1033 1084
1034 err = alx_alloc_rings(alx); 1085 err = alx_alloc_napis(alx);
1035 if (err) 1086 if (err)
1036 goto out_disable_adv_intr; 1087 goto out_disable_adv_intr;
1037 1088
1089 err = alx_alloc_rings(alx);
1090 if (err)
1091 goto out_free_rings;
1092
1038 alx_configure(alx); 1093 alx_configure(alx);
1039 1094
1040 err = alx_request_irq(alx); 1095 err = alx_request_irq(alx);
@@ -1054,6 +1109,7 @@ static int __alx_open(struct alx_priv *alx, bool resume)
1054 1109
1055out_free_rings: 1110out_free_rings:
1056 alx_free_rings(alx); 1111 alx_free_rings(alx);
1112 alx_free_napis(alx);
1057out_disable_adv_intr: 1113out_disable_adv_intr:
1058 alx_disable_advanced_intr(alx); 1114 alx_disable_advanced_intr(alx);
1059 return err; 1115 return err;
@@ -1064,6 +1120,7 @@ static void __alx_stop(struct alx_priv *alx)
1064 alx_halt(alx); 1120 alx_halt(alx);
1065 alx_free_irq(alx); 1121 alx_free_irq(alx);
1066 alx_free_rings(alx); 1122 alx_free_rings(alx);
1123 alx_free_napis(alx);
1067} 1124}
1068 1125
1069static const char *alx_speed_desc(struct alx_hw *hw) 1126static const char *alx_speed_desc(struct alx_hw *hw)