diff options
Diffstat (limited to 'drivers/net/bnx2.c')
| -rw-r--r-- | drivers/net/bnx2.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 430d430bce29..a1a3d0e5d2b4 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
| @@ -3144,6 +3144,28 @@ bnx2_has_work(struct bnx2_napi *bnapi) | |||
| 3144 | return 0; | 3144 | return 0; |
| 3145 | } | 3145 | } |
| 3146 | 3146 | ||
| 3147 | static void | ||
| 3148 | bnx2_chk_missed_msi(struct bnx2 *bp) | ||
| 3149 | { | ||
| 3150 | struct bnx2_napi *bnapi = &bp->bnx2_napi[0]; | ||
| 3151 | u32 msi_ctrl; | ||
| 3152 | |||
| 3153 | if (bnx2_has_work(bnapi)) { | ||
| 3154 | msi_ctrl = REG_RD(bp, BNX2_PCICFG_MSI_CONTROL); | ||
| 3155 | if (!(msi_ctrl & BNX2_PCICFG_MSI_CONTROL_ENABLE)) | ||
| 3156 | return; | ||
| 3157 | |||
| 3158 | if (bnapi->last_status_idx == bp->idle_chk_status_idx) { | ||
| 3159 | REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl & | ||
| 3160 | ~BNX2_PCICFG_MSI_CONTROL_ENABLE); | ||
| 3161 | REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl); | ||
| 3162 | bnx2_msi(bp->irq_tbl[0].vector, bnapi); | ||
| 3163 | } | ||
| 3164 | } | ||
| 3165 | |||
| 3166 | bp->idle_chk_status_idx = bnapi->last_status_idx; | ||
| 3167 | } | ||
| 3168 | |||
| 3147 | static void bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi) | 3169 | static void bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi) |
| 3148 | { | 3170 | { |
| 3149 | struct status_block *sblk = bnapi->status_blk.msi; | 3171 | struct status_block *sblk = bnapi->status_blk.msi; |
| @@ -3218,14 +3240,15 @@ static int bnx2_poll(struct napi_struct *napi, int budget) | |||
| 3218 | 3240 | ||
| 3219 | work_done = bnx2_poll_work(bp, bnapi, work_done, budget); | 3241 | work_done = bnx2_poll_work(bp, bnapi, work_done, budget); |
| 3220 | 3242 | ||
| 3221 | if (unlikely(work_done >= budget)) | ||
| 3222 | break; | ||
| 3223 | |||
| 3224 | /* bnapi->last_status_idx is used below to tell the hw how | 3243 | /* bnapi->last_status_idx is used below to tell the hw how |
| 3225 | * much work has been processed, so we must read it before | 3244 | * much work has been processed, so we must read it before |
| 3226 | * checking for more work. | 3245 | * checking for more work. |
| 3227 | */ | 3246 | */ |
| 3228 | bnapi->last_status_idx = sblk->status_idx; | 3247 | bnapi->last_status_idx = sblk->status_idx; |
| 3248 | |||
| 3249 | if (unlikely(work_done >= budget)) | ||
| 3250 | break; | ||
| 3251 | |||
| 3229 | rmb(); | 3252 | rmb(); |
| 3230 | if (likely(!bnx2_has_work(bnapi))) { | 3253 | if (likely(!bnx2_has_work(bnapi))) { |
| 3231 | netif_rx_complete(bp->dev, napi); | 3254 | netif_rx_complete(bp->dev, napi); |
| @@ -4570,6 +4593,8 @@ bnx2_init_chip(struct bnx2 *bp) | |||
| 4570 | for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) | 4593 | for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) |
| 4571 | bp->bnx2_napi[i].last_status_idx = 0; | 4594 | bp->bnx2_napi[i].last_status_idx = 0; |
| 4572 | 4595 | ||
| 4596 | bp->idle_chk_status_idx = 0xffff; | ||
| 4597 | |||
| 4573 | bp->rx_mode = BNX2_EMAC_RX_MODE_SORT_MODE; | 4598 | bp->rx_mode = BNX2_EMAC_RX_MODE_SORT_MODE; |
| 4574 | 4599 | ||
| 4575 | /* Set up how to generate a link change interrupt. */ | 4600 | /* Set up how to generate a link change interrupt. */ |
| @@ -5718,6 +5743,10 @@ bnx2_timer(unsigned long data) | |||
| 5718 | if (atomic_read(&bp->intr_sem) != 0) | 5743 | if (atomic_read(&bp->intr_sem) != 0) |
| 5719 | goto bnx2_restart_timer; | 5744 | goto bnx2_restart_timer; |
| 5720 | 5745 | ||
| 5746 | if ((bp->flags & (BNX2_FLAG_USING_MSI | BNX2_FLAG_ONE_SHOT_MSI)) == | ||
| 5747 | BNX2_FLAG_USING_MSI) | ||
| 5748 | bnx2_chk_missed_msi(bp); | ||
| 5749 | |||
| 5721 | bnx2_send_heart_beat(bp); | 5750 | bnx2_send_heart_beat(bp); |
| 5722 | 5751 | ||
| 5723 | bp->stats_blk->stat_FwRxDrop = | 5752 | bp->stats_blk->stat_FwRxDrop = |
| @@ -7204,10 +7233,13 @@ static void | |||
| 7204 | poll_bnx2(struct net_device *dev) | 7233 | poll_bnx2(struct net_device *dev) |
| 7205 | { | 7234 | { |
| 7206 | struct bnx2 *bp = netdev_priv(dev); | 7235 | struct bnx2 *bp = netdev_priv(dev); |
| 7236 | int i; | ||
| 7207 | 7237 | ||
| 7208 | disable_irq(bp->pdev->irq); | 7238 | for (i = 0; i < bp->irq_nvecs; i++) { |
| 7209 | bnx2_interrupt(bp->pdev->irq, dev); | 7239 | disable_irq(bp->irq_tbl[i].vector); |
| 7210 | enable_irq(bp->pdev->irq); | 7240 | bnx2_interrupt(bp->irq_tbl[i].vector, &bp->bnx2_napi[i]); |
| 7241 | enable_irq(bp->irq_tbl[i].vector); | ||
| 7242 | } | ||
| 7211 | } | 7243 | } |
| 7212 | #endif | 7244 | #endif |
| 7213 | 7245 | ||
