Commit 000233e4 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6

* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6:
  [BNX2]: Refine napi poll loop.
  [TG3]: Refine napi poll loop.
parents bfab36e8 6dee6421
...@@ -2652,10 +2652,10 @@ static int bnx2_poll_work(struct bnx2 *bp, int work_done, int budget) ...@@ -2652,10 +2652,10 @@ static int bnx2_poll_work(struct bnx2 *bp, int work_done, int budget)
REG_RD(bp, BNX2_HC_COMMAND); REG_RD(bp, BNX2_HC_COMMAND);
} }
if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons) if (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)
bnx2_tx_int(bp); bnx2_tx_int(bp);
if (bp->status_blk->status_rx_quick_consumer_index0 != bp->hw_rx_cons) if (sblk->status_rx_quick_consumer_index0 != bp->hw_rx_cons)
work_done += bnx2_rx_int(bp, budget - work_done); work_done += bnx2_rx_int(bp, budget - work_done);
return work_done; return work_done;
...@@ -2665,6 +2665,7 @@ static int bnx2_poll(struct napi_struct *napi, int budget) ...@@ -2665,6 +2665,7 @@ static int bnx2_poll(struct napi_struct *napi, int budget)
{ {
struct bnx2 *bp = container_of(napi, struct bnx2, napi); struct bnx2 *bp = container_of(napi, struct bnx2, napi);
int work_done = 0; int work_done = 0;
struct status_block *sblk = bp->status_blk;
while (1) { while (1) {
work_done = bnx2_poll_work(bp, work_done, budget); work_done = bnx2_poll_work(bp, work_done, budget);
...@@ -2672,16 +2673,19 @@ static int bnx2_poll(struct napi_struct *napi, int budget) ...@@ -2672,16 +2673,19 @@ static int bnx2_poll(struct napi_struct *napi, int budget)
if (unlikely(work_done >= budget)) if (unlikely(work_done >= budget))
break; break;
if (likely(!bnx2_has_work(bp))) { /* bp->last_status_idx is used below to tell the hw how
bp->last_status_idx = bp->status_blk->status_idx; * much work has been processed, so we must read it before
* checking for more work.
*/
bp->last_status_idx = sblk->status_idx;
rmb(); rmb();
if (likely(!bnx2_has_work(bp))) {
netif_rx_complete(bp->dev, napi); netif_rx_complete(bp->dev, napi);
if (likely(bp->flags & USING_MSI_FLAG)) { if (likely(bp->flags & USING_MSI_FLAG)) {
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
bp->last_status_idx); bp->last_status_idx);
return 0; break;
} }
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
......
...@@ -3576,7 +3576,7 @@ static int tg3_poll_work(struct tg3 *tp, int work_done, int budget) ...@@ -3576,7 +3576,7 @@ static int tg3_poll_work(struct tg3 *tp, int work_done, int budget)
if (sblk->idx[0].tx_consumer != tp->tx_cons) { if (sblk->idx[0].tx_consumer != tp->tx_cons) {
tg3_tx(tp); tg3_tx(tp);
if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING))
return 0; return work_done;
} }
/* run RX thread, within the bounds set by NAPI. /* run RX thread, within the bounds set by NAPI.
...@@ -3593,6 +3593,7 @@ static int tg3_poll(struct napi_struct *napi, int budget) ...@@ -3593,6 +3593,7 @@ static int tg3_poll(struct napi_struct *napi, int budget)
{ {
struct tg3 *tp = container_of(napi, struct tg3, napi); struct tg3 *tp = container_of(napi, struct tg3, napi);
int work_done = 0; int work_done = 0;
struct tg3_hw_status *sblk = tp->hw_status;
while (1) { while (1) {
work_done = tg3_poll_work(tp, work_done, budget); work_done = tg3_poll_work(tp, work_done, budget);
...@@ -3603,15 +3604,17 @@ static int tg3_poll(struct napi_struct *napi, int budget) ...@@ -3603,15 +3604,17 @@ static int tg3_poll(struct napi_struct *napi, int budget)
if (unlikely(work_done >= budget)) if (unlikely(work_done >= budget))
break; break;
if (likely(!tg3_has_work(tp))) {
struct tg3_hw_status *sblk = tp->hw_status;
if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) { if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
/* tp->last_tag is used in tg3_restart_ints() below
* to tell the hw how much work has been processed,
* so we must read it before checking for more work.
*/
tp->last_tag = sblk->status_tag; tp->last_tag = sblk->status_tag;
rmb(); rmb();
} else } else
sblk->status &= ~SD_STATUS_UPDATED; sblk->status &= ~SD_STATUS_UPDATED;
if (likely(!tg3_has_work(tp))) {
netif_rx_complete(tp->dev, napi); netif_rx_complete(tp->dev, napi);
tg3_restart_ints(tp); tg3_restart_ints(tp);
break; break;
...@@ -3621,9 +3624,10 @@ static int tg3_poll(struct napi_struct *napi, int budget) ...@@ -3621,9 +3624,10 @@ static int tg3_poll(struct napi_struct *napi, int budget)
return work_done; return work_done;
tx_recovery: tx_recovery:
/* work_done is guaranteed to be less than budget. */
netif_rx_complete(tp->dev, napi); netif_rx_complete(tp->dev, napi);
schedule_work(&tp->reset_task); schedule_work(&tp->reset_task);
return 0; return work_done;
} }
static void tg3_irq_quiesce(struct tg3 *tp) static void tg3_irq_quiesce(struct tg3 *tp)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment