aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2005-06-24 23:17:10 -0400
committerDavid S. Miller <davem@davemloft.net>2005-06-24 23:17:10 -0400
commitcd024c8baf9756759c57f0a19be639da8d3d4f8c (patch)
treedbbb56422f949a85291383600472d869a8d08765 /drivers
parentc54d7e03c3a21b38c587f671704c5a12aa3987fc (diff)
[TG3]: Fix missing memory barriers and SD_STATUS_UPDATED bit clearing.
There must be a rmb() between reading the status block tag and calling tg3_has_work(). This was missing in tg3_mis() and tg3_interrupt_tagged(). tg3_poll() got it right. Also, SD_STATUS_UPDATED must be cleared in the status block right before we call tg3_has_work(). Only tg3_poll() got this wrong. Based upon patches and commentary from Grant Grundler and Michael Chan. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/tg3.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index a0b8848049c9..fef1d087107c 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -2929,6 +2929,7 @@ static int tg3_poll(struct net_device *netdev, int *budget)
2929 if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) 2929 if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
2930 tp->last_tag = sblk->status_tag; 2930 tp->last_tag = sblk->status_tag;
2931 rmb(); 2931 rmb();
2932 sblk->status &= ~SD_STATUS_UPDATED;
2932 2933
2933 /* if no more work, tell net stack and NIC we're done */ 2934 /* if no more work, tell net stack and NIC we're done */
2934 done = !tg3_has_work(tp); 2935 done = !tg3_has_work(tp);
@@ -2964,6 +2965,7 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs)
2964 */ 2965 */
2965 tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); 2966 tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
2966 tp->last_tag = sblk->status_tag; 2967 tp->last_tag = sblk->status_tag;
2968 rmb();
2967 sblk->status &= ~SD_STATUS_UPDATED; 2969 sblk->status &= ~SD_STATUS_UPDATED;
2968 if (likely(tg3_has_work(tp))) 2970 if (likely(tg3_has_work(tp)))
2969 netif_rx_schedule(dev); /* schedule NAPI poll */ 2971 netif_rx_schedule(dev); /* schedule NAPI poll */
@@ -3051,6 +3053,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r
3051 tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 3053 tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
3052 0x00000001); 3054 0x00000001);
3053 tp->last_tag = sblk->status_tag; 3055 tp->last_tag = sblk->status_tag;
3056 rmb();
3054 sblk->status &= ~SD_STATUS_UPDATED; 3057 sblk->status &= ~SD_STATUS_UPDATED;
3055 if (likely(tg3_has_work(tp))) 3058 if (likely(tg3_has_work(tp)))
3056 netif_rx_schedule(dev); /* schedule NAPI poll */ 3059 netif_rx_schedule(dev); /* schedule NAPI poll */