aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2008-06-19 19:41:08 -0400
committerDavid S. Miller <davem@davemloft.net>2008-06-19 19:41:08 -0400
commit43e80b89b65cbc62b5e0fde09b47c9fc572a8b11 (patch)
tree894984eda36c720a44e00a6bd1c1c2567b45102b /drivers/net
parentbb4f98abf590cf9899017f14f1a54984f02a0009 (diff)
bnx2: Optimize fast-path tx and rx work.
Add hw_tx_cons_ptr and hw_rx_cons_ptr to speed up the retreival of the tx and rx consumer index, since the MSI-X and default status blocks have different structures. Combine status_blk and status_blk_msix into a union. We'll only use one type of status block for each vector. Separate the code to detect more rx and tx work from the code to detect link related work. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: Benjamin Li <benli@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/bnx2.c107
-rw-r--r--drivers/net/bnx2.h9
2 files changed, 72 insertions, 44 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 4360528ded39..3872e51b3c85 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -624,6 +624,7 @@ static void
624bnx2_free_mem(struct bnx2 *bp) 624bnx2_free_mem(struct bnx2 *bp)
625{ 625{
626 int i; 626 int i;
627 struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
627 628
628 bnx2_free_tx_mem(bp); 629 bnx2_free_tx_mem(bp);
629 bnx2_free_rx_mem(bp); 630 bnx2_free_rx_mem(bp);
@@ -636,10 +637,11 @@ bnx2_free_mem(struct bnx2 *bp)
636 bp->ctx_blk[i] = NULL; 637 bp->ctx_blk[i] = NULL;
637 } 638 }
638 } 639 }
639 if (bp->status_blk) { 640 if (bnapi->status_blk.msi) {
640 pci_free_consistent(bp->pdev, bp->status_stats_size, 641 pci_free_consistent(bp->pdev, bp->status_stats_size,
641 bp->status_blk, bp->status_blk_mapping); 642 bnapi->status_blk.msi,
642 bp->status_blk = NULL; 643 bp->status_blk_mapping);
644 bnapi->status_blk.msi = NULL;
643 bp->stats_blk = NULL; 645 bp->stats_blk = NULL;
644 } 646 }
645} 647}
@@ -648,6 +650,8 @@ static int
648bnx2_alloc_mem(struct bnx2 *bp) 650bnx2_alloc_mem(struct bnx2 *bp)
649{ 651{
650 int i, status_blk_size, err; 652 int i, status_blk_size, err;
653 struct bnx2_napi *bnapi;
654 void *status_blk;
651 655
652 /* Combine status and statistics blocks into one allocation. */ 656 /* Combine status and statistics blocks into one allocation. */
653 status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block)); 657 status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block));
@@ -657,27 +661,37 @@ bnx2_alloc_mem(struct bnx2 *bp)
657 bp->status_stats_size = status_blk_size + 661 bp->status_stats_size = status_blk_size +
658 sizeof(struct statistics_block); 662 sizeof(struct statistics_block);
659 663
660 bp->status_blk = pci_alloc_consistent(bp->pdev, bp->status_stats_size, 664 status_blk = pci_alloc_consistent(bp->pdev, bp->status_stats_size,
661 &bp->status_blk_mapping); 665 &bp->status_blk_mapping);
662 if (bp->status_blk == NULL) 666 if (status_blk == NULL)
663 goto alloc_mem_err; 667 goto alloc_mem_err;
664 668
665 memset(bp->status_blk, 0, bp->status_stats_size); 669 memset(status_blk, 0, bp->status_stats_size);
666 670
667 bp->bnx2_napi[0].status_blk = bp->status_blk; 671 bnapi = &bp->bnx2_napi[0];
672 bnapi->status_blk.msi = status_blk;
673 bnapi->hw_tx_cons_ptr =
674 &bnapi->status_blk.msi->status_tx_quick_consumer_index0;
675 bnapi->hw_rx_cons_ptr =
676 &bnapi->status_blk.msi->status_rx_quick_consumer_index0;
668 if (bp->flags & BNX2_FLAG_MSIX_CAP) { 677 if (bp->flags & BNX2_FLAG_MSIX_CAP) {
669 for (i = 1; i < BNX2_MAX_MSIX_VEC; i++) { 678 for (i = 1; i < BNX2_MAX_MSIX_VEC; i++) {
670 struct bnx2_napi *bnapi = &bp->bnx2_napi[i]; 679 struct status_block_msix *sblk;
680
681 bnapi = &bp->bnx2_napi[i];
671 682
672 bnapi->status_blk_msix = (void *) 683 sblk = (void *) (status_blk +
673 ((unsigned long) bp->status_blk + 684 BNX2_SBLK_MSIX_ALIGN_SIZE * i);
674 BNX2_SBLK_MSIX_ALIGN_SIZE * i); 685 bnapi->status_blk.msix = sblk;
686 bnapi->hw_tx_cons_ptr =
687 &sblk->status_tx_quick_consumer_index;
688 bnapi->hw_rx_cons_ptr =
689 &sblk->status_rx_quick_consumer_index;
675 bnapi->int_num = i << 24; 690 bnapi->int_num = i << 24;
676 } 691 }
677 } 692 }
678 693
679 bp->stats_blk = (void *) ((unsigned long) bp->status_blk + 694 bp->stats_blk = status_blk + status_blk_size;
680 status_blk_size);
681 695
682 bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size; 696 bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size;
683 697
@@ -2515,7 +2529,7 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index)
2515static int 2529static int
2516bnx2_phy_event_is_set(struct bnx2 *bp, struct bnx2_napi *bnapi, u32 event) 2530bnx2_phy_event_is_set(struct bnx2 *bp, struct bnx2_napi *bnapi, u32 event)
2517{ 2531{
2518 struct status_block *sblk = bnapi->status_blk; 2532 struct status_block *sblk = bnapi->status_blk.msi;
2519 u32 new_link_state, old_link_state; 2533 u32 new_link_state, old_link_state;
2520 int is_set = 1; 2534 int is_set = 1;
2521 2535
@@ -2551,11 +2565,9 @@ bnx2_get_hw_tx_cons(struct bnx2_napi *bnapi)
2551{ 2565{
2552 u16 cons; 2566 u16 cons;
2553 2567
2554 if (bnapi->int_num == 0) 2568 /* Tell compiler that status block fields can change. */
2555 cons = bnapi->status_blk->status_tx_quick_consumer_index0; 2569 barrier();
2556 else 2570 cons = *bnapi->hw_tx_cons_ptr;
2557 cons = bnapi->status_blk_msix->status_tx_quick_consumer_index;
2558
2559 if (unlikely((cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT)) 2571 if (unlikely((cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT))
2560 cons++; 2572 cons++;
2561 return cons; 2573 return cons;
@@ -2822,11 +2834,9 @@ bnx2_get_hw_rx_cons(struct bnx2_napi *bnapi)
2822{ 2834{
2823 u16 cons; 2835 u16 cons;
2824 2836
2825 if (bnapi->int_num == 0) 2837 /* Tell compiler that status block fields can change. */
2826 cons = bnapi->status_blk->status_rx_quick_consumer_index0; 2838 barrier();
2827 else 2839 cons = *bnapi->hw_rx_cons_ptr;
2828 cons = bnapi->status_blk_msix->status_rx_quick_consumer_index;
2829
2830 if (unlikely((cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT)) 2840 if (unlikely((cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT))
2831 cons++; 2841 cons++;
2832 return cons; 2842 return cons;
@@ -2990,7 +3000,7 @@ bnx2_msi(int irq, void *dev_instance)
2990 struct bnx2 *bp = netdev_priv(dev); 3000 struct bnx2 *bp = netdev_priv(dev);
2991 struct bnx2_napi *bnapi = &bp->bnx2_napi[0]; 3001 struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
2992 3002
2993 prefetch(bnapi->status_blk); 3003 prefetch(bnapi->status_blk.msi);
2994 REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, 3004 REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
2995 BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | 3005 BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
2996 BNX2_PCICFG_INT_ACK_CMD_MASK_INT); 3006 BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
@@ -3011,7 +3021,7 @@ bnx2_msi_1shot(int irq, void *dev_instance)
3011 struct bnx2 *bp = netdev_priv(dev); 3021 struct bnx2 *bp = netdev_priv(dev);
3012 struct bnx2_napi *bnapi = &bp->bnx2_napi[0]; 3022 struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
3013 3023
3014 prefetch(bnapi->status_blk); 3024 prefetch(bnapi->status_blk.msi);
3015 3025
3016 /* Return here if interrupt is disabled. */ 3026 /* Return here if interrupt is disabled. */
3017 if (unlikely(atomic_read(&bp->intr_sem) != 0)) 3027 if (unlikely(atomic_read(&bp->intr_sem) != 0))
@@ -3028,7 +3038,7 @@ bnx2_interrupt(int irq, void *dev_instance)
3028 struct net_device *dev = dev_instance; 3038 struct net_device *dev = dev_instance;
3029 struct bnx2 *bp = netdev_priv(dev); 3039 struct bnx2 *bp = netdev_priv(dev);
3030 struct bnx2_napi *bnapi = &bp->bnx2_napi[0]; 3040 struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
3031 struct status_block *sblk = bnapi->status_blk; 3041 struct status_block *sblk = bnapi->status_blk.msi;
3032 3042
3033 /* When using INTx, it is possible for the interrupt to arrive 3043 /* When using INTx, it is possible for the interrupt to arrive
3034 * at the CPU before the status block posted prior to the 3044 * at the CPU before the status block posted prior to the
@@ -3069,7 +3079,7 @@ bnx2_tx_msix(int irq, void *dev_instance)
3069 struct bnx2 *bp = netdev_priv(dev); 3079 struct bnx2 *bp = netdev_priv(dev);
3070 struct bnx2_napi *bnapi = &bp->bnx2_napi[BNX2_TX_VEC]; 3080 struct bnx2_napi *bnapi = &bp->bnx2_napi[BNX2_TX_VEC];
3071 3081
3072 prefetch(bnapi->status_blk_msix); 3082 prefetch(bnapi->status_blk.msix);
3073 3083
3074 /* Return here if interrupt is disabled. */ 3084 /* Return here if interrupt is disabled. */
3075 if (unlikely(atomic_read(&bp->intr_sem) != 0)) 3085 if (unlikely(atomic_read(&bp->intr_sem) != 0))
@@ -3079,19 +3089,28 @@ bnx2_tx_msix(int irq, void *dev_instance)
3079 return IRQ_HANDLED; 3089 return IRQ_HANDLED;
3080} 3090}
3081 3091
3082#define STATUS_ATTN_EVENTS (STATUS_ATTN_BITS_LINK_STATE | \
3083 STATUS_ATTN_BITS_TIMER_ABORT)
3084
3085static inline int 3092static inline int
3086bnx2_has_work(struct bnx2_napi *bnapi) 3093bnx2_has_fast_work(struct bnx2_napi *bnapi)
3087{ 3094{
3088 struct bnx2_tx_ring_info *txr = &bnapi->tx_ring; 3095 struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
3089 struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring; 3096 struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
3090 struct status_block *sblk = bnapi->status_blk;
3091 3097
3092 if ((bnx2_get_hw_rx_cons(bnapi) != rxr->rx_cons) || 3098 if ((bnx2_get_hw_rx_cons(bnapi) != rxr->rx_cons) ||
3093 (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons)) 3099 (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons))
3094 return 1; 3100 return 1;
3101 return 0;
3102}
3103
3104#define STATUS_ATTN_EVENTS (STATUS_ATTN_BITS_LINK_STATE | \
3105 STATUS_ATTN_BITS_TIMER_ABORT)
3106
3107static inline int
3108bnx2_has_work(struct bnx2_napi *bnapi)
3109{
3110 struct status_block *sblk = bnapi->status_blk.msi;
3111
3112 if (bnx2_has_fast_work(bnapi))
3113 return 1;
3095 3114
3096 if ((sblk->status_attn_bits & STATUS_ATTN_EVENTS) != 3115 if ((sblk->status_attn_bits & STATUS_ATTN_EVENTS) !=
3097 (sblk->status_attn_bits_ack & STATUS_ATTN_EVENTS)) 3116 (sblk->status_attn_bits_ack & STATUS_ATTN_EVENTS))
@@ -3106,7 +3125,7 @@ static int bnx2_tx_poll(struct napi_struct *napi, int budget)
3106 struct bnx2 *bp = bnapi->bp; 3125 struct bnx2 *bp = bnapi->bp;
3107 struct bnx2_tx_ring_info *txr = &bnapi->tx_ring; 3126 struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
3108 int work_done = 0; 3127 int work_done = 0;
3109 struct status_block_msix *sblk = bnapi->status_blk_msix; 3128 struct status_block_msix *sblk = bnapi->status_blk.msix;
3110 3129
3111 do { 3130 do {
3112 work_done += bnx2_tx_int(bp, bnapi, budget - work_done); 3131 work_done += bnx2_tx_int(bp, bnapi, budget - work_done);
@@ -3124,12 +3143,9 @@ static int bnx2_tx_poll(struct napi_struct *napi, int budget)
3124 return work_done; 3143 return work_done;
3125} 3144}
3126 3145
3127static int bnx2_poll_work(struct bnx2 *bp, struct bnx2_napi *bnapi, 3146static void bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi)
3128 int work_done, int budget)
3129{ 3147{
3130 struct bnx2_tx_ring_info *txr = &bnapi->tx_ring; 3148 struct status_block *sblk = bnapi->status_blk.msi;
3131 struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
3132 struct status_block *sblk = bnapi->status_blk;
3133 u32 status_attn_bits = sblk->status_attn_bits; 3149 u32 status_attn_bits = sblk->status_attn_bits;
3134 u32 status_attn_bits_ack = sblk->status_attn_bits_ack; 3150 u32 status_attn_bits_ack = sblk->status_attn_bits_ack;
3135 3151
@@ -3145,6 +3161,13 @@ static int bnx2_poll_work(struct bnx2 *bp, struct bnx2_napi *bnapi,
3145 bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); 3161 bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
3146 REG_RD(bp, BNX2_HC_COMMAND); 3162 REG_RD(bp, BNX2_HC_COMMAND);
3147 } 3163 }
3164}
3165
3166static int bnx2_poll_work(struct bnx2 *bp, struct bnx2_napi *bnapi,
3167 int work_done, int budget)
3168{
3169 struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
3170 struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
3148 3171
3149 if (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons) 3172 if (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons)
3150 bnx2_tx_int(bp, bnapi, 0); 3173 bnx2_tx_int(bp, bnapi, 0);
@@ -3160,9 +3183,11 @@ static int bnx2_poll(struct napi_struct *napi, int budget)
3160 struct bnx2_napi *bnapi = container_of(napi, struct bnx2_napi, napi); 3183 struct bnx2_napi *bnapi = container_of(napi, struct bnx2_napi, napi);
3161 struct bnx2 *bp = bnapi->bp; 3184 struct bnx2 *bp = bnapi->bp;
3162 int work_done = 0; 3185 int work_done = 0;
3163 struct status_block *sblk = bnapi->status_blk; 3186 struct status_block *sblk = bnapi->status_blk.msi;
3164 3187
3165 while (1) { 3188 while (1) {
3189 bnx2_poll_link(bp, bnapi);
3190
3166 work_done = bnx2_poll_work(bp, bnapi, work_done, budget); 3191 work_done = bnx2_poll_work(bp, bnapi, work_done, budget);
3167 3192
3168 if (unlikely(work_done >= budget)) 3193 if (unlikely(work_done >= budget))
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 1c5ce80f6269..362bef6ff5ff 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -6609,8 +6609,12 @@ struct bnx2_rx_ring_info {
6609struct bnx2_napi { 6609struct bnx2_napi {
6610 struct napi_struct napi ____cacheline_aligned; 6610 struct napi_struct napi ____cacheline_aligned;
6611 struct bnx2 *bp; 6611 struct bnx2 *bp;
6612 struct status_block *status_blk; 6612 union {
6613 struct status_block_msix *status_blk_msix; 6613 struct status_block *msi;
6614 struct status_block_msix *msix;
6615 } status_blk;
6616 u16 *hw_tx_cons_ptr;
6617 u16 *hw_rx_cons_ptr;
6614 u32 last_status_idx; 6618 u32 last_status_idx;
6615 u32 int_num; 6619 u32 int_num;
6616 6620
@@ -6759,7 +6763,6 @@ struct bnx2 {
6759 6763
6760 u32 stats_ticks; 6764 u32 stats_ticks;
6761 6765
6762 struct status_block *status_blk;
6763 dma_addr_t status_blk_mapping; 6766 dma_addr_t status_blk_mapping;
6764 6767
6765 struct statistics_block *stats_blk; 6768 struct statistics_block *stats_blk;