diff options
author | Michael Chan <mchan@broadcom.com> | 2012-09-28 03:12:37 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-09-30 02:10:35 -0400 |
commit | 49a359e31762f798f3abef00c7d6b807a644eadf (patch) | |
tree | 1efafb46b643467cec48d3086528e5c47b2b6e9b /drivers/net/ethernet/broadcom/tg3.c | |
parent | 188c517a050ec5b123e72cab76ea213721e5bd9d (diff) |
tg3: Introduce separate functions to allocate/free RX/TX rings.
This is preparation work to allow the number of RX and TX rings to be
configured separately.
Reviewed-by: Nithin Nayak Sujir <nsujir@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/broadcom/tg3.c')
-rw-r--r-- | drivers/net/ethernet/broadcom/tg3.c | 220 |
1 files changed, 144 insertions, 76 deletions
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index bf906c51d82a..93b8120bbf68 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c | |||
@@ -7607,15 +7607,11 @@ static int tg3_init_rings(struct tg3 *tp) | |||
7607 | return 0; | 7607 | return 0; |
7608 | } | 7608 | } |
7609 | 7609 | ||
7610 | /* | 7610 | static void tg3_mem_tx_release(struct tg3 *tp) |
7611 | * Must not be invoked with interrupt sources disabled and | ||
7612 | * the hardware shutdown down. | ||
7613 | */ | ||
7614 | static void tg3_free_consistent(struct tg3 *tp) | ||
7615 | { | 7611 | { |
7616 | int i; | 7612 | int i; |
7617 | 7613 | ||
7618 | for (i = 0; i < tp->irq_cnt; i++) { | 7614 | for (i = 0; i < tp->irq_max; i++) { |
7619 | struct tg3_napi *tnapi = &tp->napi[i]; | 7615 | struct tg3_napi *tnapi = &tp->napi[i]; |
7620 | 7616 | ||
7621 | if (tnapi->tx_ring) { | 7617 | if (tnapi->tx_ring) { |
@@ -7626,17 +7622,114 @@ static void tg3_free_consistent(struct tg3 *tp) | |||
7626 | 7622 | ||
7627 | kfree(tnapi->tx_buffers); | 7623 | kfree(tnapi->tx_buffers); |
7628 | tnapi->tx_buffers = NULL; | 7624 | tnapi->tx_buffers = NULL; |
7625 | } | ||
7626 | } | ||
7629 | 7627 | ||
7630 | if (tnapi->rx_rcb) { | 7628 | static int tg3_mem_tx_acquire(struct tg3 *tp) |
7631 | dma_free_coherent(&tp->pdev->dev, | 7629 | { |
7632 | TG3_RX_RCB_RING_BYTES(tp), | 7630 | int i; |
7633 | tnapi->rx_rcb, | 7631 | struct tg3_napi *tnapi = &tp->napi[0]; |
7634 | tnapi->rx_rcb_mapping); | 7632 | |
7635 | tnapi->rx_rcb = NULL; | 7633 | /* If multivector TSS is enabled, vector 0 does not handle |
7636 | } | 7634 | * tx interrupts. Don't allocate any resources for it. |
7635 | */ | ||
7636 | if (tg3_flag(tp, ENABLE_TSS)) | ||
7637 | tnapi++; | ||
7638 | |||
7639 | for (i = 0; i < tp->txq_cnt; i++, tnapi++) { | ||
7640 | tnapi->tx_buffers = kzalloc(sizeof(struct tg3_tx_ring_info) * | ||
7641 | TG3_TX_RING_SIZE, GFP_KERNEL); | ||
7642 | if (!tnapi->tx_buffers) | ||
7643 | goto err_out; | ||
7644 | |||
7645 | tnapi->tx_ring = dma_alloc_coherent(&tp->pdev->dev, | ||
7646 | TG3_TX_RING_BYTES, | ||
7647 | &tnapi->tx_desc_mapping, | ||
7648 | GFP_KERNEL); | ||
7649 | if (!tnapi->tx_ring) | ||
7650 | goto err_out; | ||
7651 | } | ||
7652 | |||
7653 | return 0; | ||
7654 | |||
7655 | err_out: | ||
7656 | tg3_mem_tx_release(tp); | ||
7657 | return -ENOMEM; | ||
7658 | } | ||
7659 | |||
7660 | static void tg3_mem_rx_release(struct tg3 *tp) | ||
7661 | { | ||
7662 | int i; | ||
7663 | |||
7664 | for (i = 0; i < tp->irq_max; i++) { | ||
7665 | struct tg3_napi *tnapi = &tp->napi[i]; | ||
7637 | 7666 | ||
7638 | tg3_rx_prodring_fini(tp, &tnapi->prodring); | 7667 | tg3_rx_prodring_fini(tp, &tnapi->prodring); |
7639 | 7668 | ||
7669 | if (!tnapi->rx_rcb) | ||
7670 | continue; | ||
7671 | |||
7672 | dma_free_coherent(&tp->pdev->dev, | ||
7673 | TG3_RX_RCB_RING_BYTES(tp), | ||
7674 | tnapi->rx_rcb, | ||
7675 | tnapi->rx_rcb_mapping); | ||
7676 | tnapi->rx_rcb = NULL; | ||
7677 | } | ||
7678 | } | ||
7679 | |||
7680 | static int tg3_mem_rx_acquire(struct tg3 *tp) | ||
7681 | { | ||
7682 | unsigned int i, limit; | ||
7683 | |||
7684 | limit = tp->rxq_cnt; | ||
7685 | |||
7686 | /* If RSS is enabled, we need a (dummy) producer ring | ||
7687 | * set on vector zero. This is the true hw prodring. | ||
7688 | */ | ||
7689 | if (tg3_flag(tp, ENABLE_RSS)) | ||
7690 | limit++; | ||
7691 | |||
7692 | for (i = 0; i < limit; i++) { | ||
7693 | struct tg3_napi *tnapi = &tp->napi[i]; | ||
7694 | |||
7695 | if (tg3_rx_prodring_init(tp, &tnapi->prodring)) | ||
7696 | goto err_out; | ||
7697 | |||
7698 | /* If multivector RSS is enabled, vector 0 | ||
7699 | * does not handle rx or tx interrupts. | ||
7700 | * Don't allocate any resources for it. | ||
7701 | */ | ||
7702 | if (!i && tg3_flag(tp, ENABLE_RSS)) | ||
7703 | continue; | ||
7704 | |||
7705 | tnapi->rx_rcb = dma_alloc_coherent(&tp->pdev->dev, | ||
7706 | TG3_RX_RCB_RING_BYTES(tp), | ||
7707 | &tnapi->rx_rcb_mapping, | ||
7708 | GFP_KERNEL); | ||
7709 | if (!tnapi->rx_rcb) | ||
7710 | goto err_out; | ||
7711 | |||
7712 | memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); | ||
7713 | } | ||
7714 | |||
7715 | return 0; | ||
7716 | |||
7717 | err_out: | ||
7718 | tg3_mem_rx_release(tp); | ||
7719 | return -ENOMEM; | ||
7720 | } | ||
7721 | |||
7722 | /* | ||
7723 | * Must not be invoked with interrupt sources disabled and | ||
7724 | * the hardware shutdown down. | ||
7725 | */ | ||
7726 | static void tg3_free_consistent(struct tg3 *tp) | ||
7727 | { | ||
7728 | int i; | ||
7729 | |||
7730 | for (i = 0; i < tp->irq_cnt; i++) { | ||
7731 | struct tg3_napi *tnapi = &tp->napi[i]; | ||
7732 | |||
7640 | if (tnapi->hw_status) { | 7733 | if (tnapi->hw_status) { |
7641 | dma_free_coherent(&tp->pdev->dev, TG3_HW_STATUS_SIZE, | 7734 | dma_free_coherent(&tp->pdev->dev, TG3_HW_STATUS_SIZE, |
7642 | tnapi->hw_status, | 7735 | tnapi->hw_status, |
@@ -7645,6 +7738,9 @@ static void tg3_free_consistent(struct tg3 *tp) | |||
7645 | } | 7738 | } |
7646 | } | 7739 | } |
7647 | 7740 | ||
7741 | tg3_mem_rx_release(tp); | ||
7742 | tg3_mem_tx_release(tp); | ||
7743 | |||
7648 | if (tp->hw_stats) { | 7744 | if (tp->hw_stats) { |
7649 | dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats), | 7745 | dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats), |
7650 | tp->hw_stats, tp->stats_mapping); | 7746 | tp->hw_stats, tp->stats_mapping); |
@@ -7683,72 +7779,38 @@ static int tg3_alloc_consistent(struct tg3 *tp) | |||
7683 | memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE); | 7779 | memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE); |
7684 | sblk = tnapi->hw_status; | 7780 | sblk = tnapi->hw_status; |
7685 | 7781 | ||
7686 | if (tg3_rx_prodring_init(tp, &tnapi->prodring)) | 7782 | if (tg3_flag(tp, ENABLE_RSS)) { |
7687 | goto err_out; | 7783 | u16 *prodptr = 0; |
7688 | 7784 | ||
7689 | /* If multivector TSS is enabled, vector 0 does not handle | 7785 | /* |
7690 | * tx interrupts. Don't allocate any resources for it. | 7786 | * When RSS is enabled, the status block format changes |
7691 | */ | 7787 | * slightly. The "rx_jumbo_consumer", "reserved", |
7692 | if ((!i && !tg3_flag(tp, ENABLE_TSS)) || | 7788 | * and "rx_mini_consumer" members get mapped to the |
7693 | (i && tg3_flag(tp, ENABLE_TSS))) { | 7789 | * other three rx return ring producer indexes. |
7694 | tnapi->tx_buffers = kzalloc( | 7790 | */ |
7695 | sizeof(struct tg3_tx_ring_info) * | 7791 | switch (i) { |
7696 | TG3_TX_RING_SIZE, GFP_KERNEL); | 7792 | case 1: |
7697 | if (!tnapi->tx_buffers) | 7793 | prodptr = &sblk->idx[0].rx_producer; |
7698 | goto err_out; | 7794 | break; |
7699 | 7795 | case 2: | |
7700 | tnapi->tx_ring = dma_alloc_coherent(&tp->pdev->dev, | 7796 | prodptr = &sblk->rx_jumbo_consumer; |
7701 | TG3_TX_RING_BYTES, | 7797 | break; |
7702 | &tnapi->tx_desc_mapping, | 7798 | case 3: |
7703 | GFP_KERNEL); | 7799 | prodptr = &sblk->reserved; |
7704 | if (!tnapi->tx_ring) | 7800 | break; |
7705 | goto err_out; | 7801 | case 4: |
7706 | } | 7802 | prodptr = &sblk->rx_mini_consumer; |
7707 | |||
7708 | /* | ||
7709 | * When RSS is enabled, the status block format changes | ||
7710 | * slightly. The "rx_jumbo_consumer", "reserved", | ||
7711 | * and "rx_mini_consumer" members get mapped to the | ||
7712 | * other three rx return ring producer indexes. | ||
7713 | */ | ||
7714 | switch (i) { | ||
7715 | default: | ||
7716 | if (tg3_flag(tp, ENABLE_RSS)) { | ||
7717 | tnapi->rx_rcb_prod_idx = NULL; | ||
7718 | break; | 7803 | break; |
7719 | } | 7804 | } |
7720 | /* Fall through */ | 7805 | tnapi->rx_rcb_prod_idx = prodptr; |
7721 | case 1: | 7806 | } else { |
7722 | tnapi->rx_rcb_prod_idx = &sblk->idx[0].rx_producer; | 7807 | tnapi->rx_rcb_prod_idx = &sblk->idx[0].rx_producer; |
7723 | break; | ||
7724 | case 2: | ||
7725 | tnapi->rx_rcb_prod_idx = &sblk->rx_jumbo_consumer; | ||
7726 | break; | ||
7727 | case 3: | ||
7728 | tnapi->rx_rcb_prod_idx = &sblk->reserved; | ||
7729 | break; | ||
7730 | case 4: | ||
7731 | tnapi->rx_rcb_prod_idx = &sblk->rx_mini_consumer; | ||
7732 | break; | ||
7733 | } | 7808 | } |
7734 | |||
7735 | /* | ||
7736 | * If multivector RSS is enabled, vector 0 does not handle | ||
7737 | * rx or tx interrupts. Don't allocate any resources for it. | ||
7738 | */ | ||
7739 | if (!i && tg3_flag(tp, ENABLE_RSS)) | ||
7740 | continue; | ||
7741 | |||
7742 | tnapi->rx_rcb = dma_alloc_coherent(&tp->pdev->dev, | ||
7743 | TG3_RX_RCB_RING_BYTES(tp), | ||
7744 | &tnapi->rx_rcb_mapping, | ||
7745 | GFP_KERNEL); | ||
7746 | if (!tnapi->rx_rcb) | ||
7747 | goto err_out; | ||
7748 | |||
7749 | memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); | ||
7750 | } | 7809 | } |
7751 | 7810 | ||
7811 | if (tg3_mem_tx_acquire(tp) || tg3_mem_rx_acquire(tp)) | ||
7812 | goto err_out; | ||
7813 | |||
7752 | return 0; | 7814 | return 0; |
7753 | 7815 | ||
7754 | err_out: | 7816 | err_out: |
@@ -10154,6 +10216,7 @@ static bool tg3_enable_msix(struct tg3 *tp) | |||
10154 | * one to the number of vectors we are requesting. | 10216 | * one to the number of vectors we are requesting. |
10155 | */ | 10217 | */ |
10156 | tp->irq_cnt = min_t(unsigned, tp->irq_cnt + 1, tp->irq_max); | 10218 | tp->irq_cnt = min_t(unsigned, tp->irq_cnt + 1, tp->irq_max); |
10219 | tp->rxq_cnt = tp->irq_cnt - 1; | ||
10157 | } | 10220 | } |
10158 | 10221 | ||
10159 | for (i = 0; i < tp->irq_max; i++) { | 10222 | for (i = 0; i < tp->irq_max; i++) { |
@@ -10170,14 +10233,13 @@ static bool tg3_enable_msix(struct tg3 *tp) | |||
10170 | netdev_notice(tp->dev, "Requested %d MSI-X vectors, received %d\n", | 10233 | netdev_notice(tp->dev, "Requested %d MSI-X vectors, received %d\n", |
10171 | tp->irq_cnt, rc); | 10234 | tp->irq_cnt, rc); |
10172 | tp->irq_cnt = rc; | 10235 | tp->irq_cnt = rc; |
10236 | tp->rxq_cnt = max(rc - 1, 1); | ||
10173 | } | 10237 | } |
10174 | 10238 | ||
10175 | for (i = 0; i < tp->irq_max; i++) | 10239 | for (i = 0; i < tp->irq_max; i++) |
10176 | tp->napi[i].irq_vec = msix_ent[i].vector; | 10240 | tp->napi[i].irq_vec = msix_ent[i].vector; |
10177 | 10241 | ||
10178 | netif_set_real_num_tx_queues(tp->dev, 1); | 10242 | if (netif_set_real_num_rx_queues(tp->dev, tp->rxq_cnt)) { |
10179 | rc = tp->irq_cnt > 1 ? tp->irq_cnt - 1 : 1; | ||
10180 | if (netif_set_real_num_rx_queues(tp->dev, rc)) { | ||
10181 | pci_disable_msix(tp->pdev); | 10243 | pci_disable_msix(tp->pdev); |
10182 | return false; | 10244 | return false; |
10183 | } | 10245 | } |
@@ -10188,7 +10250,8 @@ static bool tg3_enable_msix(struct tg3 *tp) | |||
10188 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || | 10250 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || |
10189 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { | 10251 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { |
10190 | tg3_flag_set(tp, ENABLE_TSS); | 10252 | tg3_flag_set(tp, ENABLE_TSS); |
10191 | netif_set_real_num_tx_queues(tp->dev, tp->irq_cnt - 1); | 10253 | tp->txq_cnt = tp->rxq_cnt; |
10254 | netif_set_real_num_tx_queues(tp->dev, tp->txq_cnt); | ||
10192 | } | 10255 | } |
10193 | } | 10256 | } |
10194 | 10257 | ||
@@ -10224,6 +10287,11 @@ defcfg: | |||
10224 | if (!tg3_flag(tp, USING_MSIX)) { | 10287 | if (!tg3_flag(tp, USING_MSIX)) { |
10225 | tp->irq_cnt = 1; | 10288 | tp->irq_cnt = 1; |
10226 | tp->napi[0].irq_vec = tp->pdev->irq; | 10289 | tp->napi[0].irq_vec = tp->pdev->irq; |
10290 | } | ||
10291 | |||
10292 | if (tp->irq_cnt == 1) { | ||
10293 | tp->txq_cnt = 1; | ||
10294 | tp->rxq_cnt = 1; | ||
10227 | netif_set_real_num_tx_queues(tp->dev, 1); | 10295 | netif_set_real_num_tx_queues(tp->dev, 1); |
10228 | netif_set_real_num_rx_queues(tp->dev, 1); | 10296 | netif_set_real_num_rx_queues(tp->dev, 1); |
10229 | } | 10297 | } |