diff options
author | Michael Chan <mchan@broadcom.com> | 2008-06-19 19:41:57 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-19 19:41:57 -0400 |
commit | f0ea2e63859cf234b7017a2d7bba2a5a1db3bf25 (patch) | |
tree | 6b5e2e18ce331d0467a729cbde0e5680c6d447b3 /drivers/net/bnx2.c | |
parent | 43e80b89b65cbc62b5e0fde09b47c9fc572a8b11 (diff) |
bnx2: Use one handler for all MSI-X vectors.
Use the same MSI-X handler to schedule NAPI. Change the dev_instance
void pointer to the bnx2_napi struct instead so we can have the proper
context for each MSI-X vector.
Add a new bnx2_poll_msix() that is optimized for handling MSI-X
NAPI polling of rx/tx work only. Remove the old bnx2_tx_poll() that
is no longer needed. Each MSI-X vector handles 1 tx and 1 rx ring.
The first vector handles link events as well.
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/bnx2.c')
-rw-r--r-- | drivers/net/bnx2.c | 99 |
1 files changed, 40 insertions, 59 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 3872e51b3c85..0a297f77a276 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -2996,9 +2996,9 @@ next_rx: | |||
2996 | static irqreturn_t | 2996 | static irqreturn_t |
2997 | bnx2_msi(int irq, void *dev_instance) | 2997 | bnx2_msi(int irq, void *dev_instance) |
2998 | { | 2998 | { |
2999 | struct net_device *dev = dev_instance; | 2999 | struct bnx2_napi *bnapi = dev_instance; |
3000 | struct bnx2 *bp = netdev_priv(dev); | 3000 | struct bnx2 *bp = bnapi->bp; |
3001 | struct bnx2_napi *bnapi = &bp->bnx2_napi[0]; | 3001 | struct net_device *dev = bp->dev; |
3002 | 3002 | ||
3003 | prefetch(bnapi->status_blk.msi); | 3003 | prefetch(bnapi->status_blk.msi); |
3004 | REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, | 3004 | REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, |
@@ -3017,9 +3017,9 @@ bnx2_msi(int irq, void *dev_instance) | |||
3017 | static irqreturn_t | 3017 | static irqreturn_t |
3018 | bnx2_msi_1shot(int irq, void *dev_instance) | 3018 | bnx2_msi_1shot(int irq, void *dev_instance) |
3019 | { | 3019 | { |
3020 | struct net_device *dev = dev_instance; | 3020 | struct bnx2_napi *bnapi = dev_instance; |
3021 | struct bnx2 *bp = netdev_priv(dev); | 3021 | struct bnx2 *bp = bnapi->bp; |
3022 | struct bnx2_napi *bnapi = &bp->bnx2_napi[0]; | 3022 | struct net_device *dev = bp->dev; |
3023 | 3023 | ||
3024 | prefetch(bnapi->status_blk.msi); | 3024 | prefetch(bnapi->status_blk.msi); |
3025 | 3025 | ||
@@ -3035,9 +3035,9 @@ bnx2_msi_1shot(int irq, void *dev_instance) | |||
3035 | static irqreturn_t | 3035 | static irqreturn_t |
3036 | bnx2_interrupt(int irq, void *dev_instance) | 3036 | bnx2_interrupt(int irq, void *dev_instance) |
3037 | { | 3037 | { |
3038 | struct net_device *dev = dev_instance; | 3038 | struct bnx2_napi *bnapi = dev_instance; |
3039 | struct bnx2 *bp = netdev_priv(dev); | 3039 | struct bnx2 *bp = bnapi->bp; |
3040 | struct bnx2_napi *bnapi = &bp->bnx2_napi[0]; | 3040 | struct net_device *dev = bp->dev; |
3041 | struct status_block *sblk = bnapi->status_blk.msi; | 3041 | struct status_block *sblk = bnapi->status_blk.msi; |
3042 | 3042 | ||
3043 | /* When using INTx, it is possible for the interrupt to arrive | 3043 | /* When using INTx, it is possible for the interrupt to arrive |
@@ -3072,23 +3072,6 @@ bnx2_interrupt(int irq, void *dev_instance) | |||
3072 | return IRQ_HANDLED; | 3072 | return IRQ_HANDLED; |
3073 | } | 3073 | } |
3074 | 3074 | ||
3075 | static irqreturn_t | ||
3076 | bnx2_tx_msix(int irq, void *dev_instance) | ||
3077 | { | ||
3078 | struct net_device *dev = dev_instance; | ||
3079 | struct bnx2 *bp = netdev_priv(dev); | ||
3080 | struct bnx2_napi *bnapi = &bp->bnx2_napi[BNX2_TX_VEC]; | ||
3081 | |||
3082 | prefetch(bnapi->status_blk.msix); | ||
3083 | |||
3084 | /* Return here if interrupt is disabled. */ | ||
3085 | if (unlikely(atomic_read(&bp->intr_sem) != 0)) | ||
3086 | return IRQ_HANDLED; | ||
3087 | |||
3088 | netif_rx_schedule(dev, &bnapi->napi); | ||
3089 | return IRQ_HANDLED; | ||
3090 | } | ||
3091 | |||
3092 | static inline int | 3075 | static inline int |
3093 | bnx2_has_fast_work(struct bnx2_napi *bnapi) | 3076 | bnx2_has_fast_work(struct bnx2_napi *bnapi) |
3094 | { | 3077 | { |
@@ -3119,30 +3102,6 @@ bnx2_has_work(struct bnx2_napi *bnapi) | |||
3119 | return 0; | 3102 | return 0; |
3120 | } | 3103 | } |
3121 | 3104 | ||
3122 | static int bnx2_tx_poll(struct napi_struct *napi, int budget) | ||
3123 | { | ||
3124 | struct bnx2_napi *bnapi = container_of(napi, struct bnx2_napi, napi); | ||
3125 | struct bnx2 *bp = bnapi->bp; | ||
3126 | struct bnx2_tx_ring_info *txr = &bnapi->tx_ring; | ||
3127 | int work_done = 0; | ||
3128 | struct status_block_msix *sblk = bnapi->status_blk.msix; | ||
3129 | |||
3130 | do { | ||
3131 | work_done += bnx2_tx_int(bp, bnapi, budget - work_done); | ||
3132 | if (unlikely(work_done >= budget)) | ||
3133 | return work_done; | ||
3134 | |||
3135 | bnapi->last_status_idx = sblk->status_idx; | ||
3136 | rmb(); | ||
3137 | } while (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons); | ||
3138 | |||
3139 | netif_rx_complete(bp->dev, napi); | ||
3140 | REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num | | ||
3141 | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | | ||
3142 | bnapi->last_status_idx); | ||
3143 | return work_done; | ||
3144 | } | ||
3145 | |||
3146 | static void bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi) | 3105 | static void bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi) |
3147 | { | 3106 | { |
3148 | struct status_block *sblk = bnapi->status_blk.msi; | 3107 | struct status_block *sblk = bnapi->status_blk.msi; |
@@ -3178,6 +3137,33 @@ static int bnx2_poll_work(struct bnx2 *bp, struct bnx2_napi *bnapi, | |||
3178 | return work_done; | 3137 | return work_done; |
3179 | } | 3138 | } |
3180 | 3139 | ||
3140 | static int bnx2_poll_msix(struct napi_struct *napi, int budget) | ||
3141 | { | ||
3142 | struct bnx2_napi *bnapi = container_of(napi, struct bnx2_napi, napi); | ||
3143 | struct bnx2 *bp = bnapi->bp; | ||
3144 | int work_done = 0; | ||
3145 | struct status_block_msix *sblk = bnapi->status_blk.msix; | ||
3146 | |||
3147 | while (1) { | ||
3148 | work_done = bnx2_poll_work(bp, bnapi, work_done, budget); | ||
3149 | if (unlikely(work_done >= budget)) | ||
3150 | break; | ||
3151 | |||
3152 | bnapi->last_status_idx = sblk->status_idx; | ||
3153 | /* status idx must be read before checking for more work. */ | ||
3154 | rmb(); | ||
3155 | if (likely(!bnx2_has_fast_work(bnapi))) { | ||
3156 | |||
3157 | netif_rx_complete(bp->dev, napi); | ||
3158 | REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num | | ||
3159 | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | | ||
3160 | bnapi->last_status_idx); | ||
3161 | break; | ||
3162 | } | ||
3163 | } | ||
3164 | return work_done; | ||
3165 | } | ||
3166 | |||
3181 | static int bnx2_poll(struct napi_struct *napi, int budget) | 3167 | static int bnx2_poll(struct napi_struct *napi, int budget) |
3182 | { | 3168 | { |
3183 | struct bnx2_napi *bnapi = container_of(napi, struct bnx2_napi, napi); | 3169 | struct bnx2_napi *bnapi = container_of(napi, struct bnx2_napi, napi); |
@@ -5636,7 +5622,6 @@ bnx2_restart_timer: | |||
5636 | static int | 5622 | static int |
5637 | bnx2_request_irq(struct bnx2 *bp) | 5623 | bnx2_request_irq(struct bnx2 *bp) |
5638 | { | 5624 | { |
5639 | struct net_device *dev = bp->dev; | ||
5640 | unsigned long flags; | 5625 | unsigned long flags; |
5641 | struct bnx2_irq *irq; | 5626 | struct bnx2_irq *irq; |
5642 | int rc = 0, i; | 5627 | int rc = 0, i; |
@@ -5649,7 +5634,7 @@ bnx2_request_irq(struct bnx2 *bp) | |||
5649 | for (i = 0; i < bp->irq_nvecs; i++) { | 5634 | for (i = 0; i < bp->irq_nvecs; i++) { |
5650 | irq = &bp->irq_tbl[i]; | 5635 | irq = &bp->irq_tbl[i]; |
5651 | rc = request_irq(irq->vector, irq->handler, flags, irq->name, | 5636 | rc = request_irq(irq->vector, irq->handler, flags, irq->name, |
5652 | dev); | 5637 | &bp->bnx2_napi[i]); |
5653 | if (rc) | 5638 | if (rc) |
5654 | break; | 5639 | break; |
5655 | irq->requested = 1; | 5640 | irq->requested = 1; |
@@ -5660,14 +5645,13 @@ bnx2_request_irq(struct bnx2 *bp) | |||
5660 | static void | 5645 | static void |
5661 | bnx2_free_irq(struct bnx2 *bp) | 5646 | bnx2_free_irq(struct bnx2 *bp) |
5662 | { | 5647 | { |
5663 | struct net_device *dev = bp->dev; | ||
5664 | struct bnx2_irq *irq; | 5648 | struct bnx2_irq *irq; |
5665 | int i; | 5649 | int i; |
5666 | 5650 | ||
5667 | for (i = 0; i < bp->irq_nvecs; i++) { | 5651 | for (i = 0; i < bp->irq_nvecs; i++) { |
5668 | irq = &bp->irq_tbl[i]; | 5652 | irq = &bp->irq_tbl[i]; |
5669 | if (irq->requested) | 5653 | if (irq->requested) |
5670 | free_irq(irq->vector, dev); | 5654 | free_irq(irq->vector, &bp->bnx2_napi[i]); |
5671 | irq->requested = 0; | 5655 | irq->requested = 0; |
5672 | } | 5656 | } |
5673 | if (bp->flags & BNX2_FLAG_USING_MSI) | 5657 | if (bp->flags & BNX2_FLAG_USING_MSI) |
@@ -5694,10 +5678,7 @@ bnx2_enable_msix(struct bnx2 *bp) | |||
5694 | msix_ent[i].vector = 0; | 5678 | msix_ent[i].vector = 0; |
5695 | 5679 | ||
5696 | strcpy(bp->irq_tbl[i].name, bp->dev->name); | 5680 | strcpy(bp->irq_tbl[i].name, bp->dev->name); |
5697 | if (i == 0) | 5681 | bp->irq_tbl[i].handler = bnx2_msi_1shot; |
5698 | bp->irq_tbl[i].handler = bnx2_msi_1shot; | ||
5699 | else | ||
5700 | bp->irq_tbl[i].handler = bnx2_tx_msix; | ||
5701 | } | 5682 | } |
5702 | 5683 | ||
5703 | rc = pci_enable_msix(bp->pdev, msix_ent, BNX2_MAX_MSIX_VEC); | 5684 | rc = pci_enable_msix(bp->pdev, msix_ent, BNX2_MAX_MSIX_VEC); |
@@ -7567,7 +7548,7 @@ bnx2_init_napi(struct bnx2 *bp) | |||
7567 | if (i == 0) | 7548 | if (i == 0) |
7568 | poll = bnx2_poll; | 7549 | poll = bnx2_poll; |
7569 | else | 7550 | else |
7570 | poll = bnx2_tx_poll; | 7551 | poll = bnx2_poll_msix; |
7571 | 7552 | ||
7572 | netif_napi_add(bp->dev, &bp->bnx2_napi[i].napi, poll, 64); | 7553 | netif_napi_add(bp->dev, &bp->bnx2_napi[i].napi, poll, 64); |
7573 | bnapi->bp = bp; | 7554 | bnapi->bp = bp; |