Skip to content

Commit

Permalink
[TG3]: Refine napi poll loop.
Browse files Browse the repository at this point in the history
Need to read and store sblk->status_tag before checking for more work.
The status tag is later written back to the hardware when enabling
interrupts to acknowledge how much work has been processed.  If the
order is reversed, we can end up acknowledging work we haven't
processed.

When we detect tx error, it is more correct to return the rx
work_done so far instead of 0.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Michael Chan authored and David S. Miller committed Oct 12, 2007
1 parent 782e3b3 commit 4fd7ab5
Showing 1 changed file with 14 additions and 10 deletions.
24 changes: 14 additions & 10 deletions drivers/net/tg3.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
tg3_tx(tp);
if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING))
return 0;
return work_done;
}

/* run RX thread, within the bounds set by NAPI.
Expand All @@ -3593,6 +3593,7 @@ static int tg3_poll(struct napi_struct *napi, int budget)
{
struct tg3 *tp = container_of(napi, struct tg3, napi);
int work_done = 0;
struct tg3_hw_status *sblk = tp->hw_status;

while (1) {
work_done = tg3_poll_work(tp, work_done, budget);
Expand All @@ -3603,15 +3604,17 @@ static int tg3_poll(struct napi_struct *napi, int budget)
if (unlikely(work_done >= budget))
break;

if (likely(!tg3_has_work(tp))) {
struct tg3_hw_status *sblk = tp->hw_status;

if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
tp->last_tag = sblk->status_tag;
rmb();
} else
sblk->status &= ~SD_STATUS_UPDATED;
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;
rmb();
} else
sblk->status &= ~SD_STATUS_UPDATED;

if (likely(!tg3_has_work(tp))) {
netif_rx_complete(tp->dev, napi);
tg3_restart_ints(tp);
break;
Expand All @@ -3621,9 +3624,10 @@ static int tg3_poll(struct napi_struct *napi, int budget)
return work_done;

tx_recovery:
/* work_done is guaranteed to be less than budget. */
netif_rx_complete(tp->dev, napi);
schedule_work(&tp->reset_task);
return 0;
return work_done;
}

static void tg3_irq_quiesce(struct tg3 *tp)
Expand Down

0 comments on commit 4fd7ab5

Please sign in to comment.