[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>
This commit is contained in:
Родитель
c54d7e03c3
Коммит
cd024c8baf
|
@ -2929,6 +2929,7 @@ static int tg3_poll(struct net_device *netdev, int *budget)
|
||||||
if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
|
if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
|
||||||
tp->last_tag = sblk->status_tag;
|
tp->last_tag = sblk->status_tag;
|
||||||
rmb();
|
rmb();
|
||||||
|
sblk->status &= ~SD_STATUS_UPDATED;
|
||||||
|
|
||||||
/* if no more work, tell net stack and NIC we're done */
|
/* if no more work, tell net stack and NIC we're done */
|
||||||
done = !tg3_has_work(tp);
|
done = !tg3_has_work(tp);
|
||||||
|
@ -2964,6 +2965,7 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs)
|
||||||
*/
|
*/
|
||||||
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
|
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
|
||||||
tp->last_tag = sblk->status_tag;
|
tp->last_tag = sblk->status_tag;
|
||||||
|
rmb();
|
||||||
sblk->status &= ~SD_STATUS_UPDATED;
|
sblk->status &= ~SD_STATUS_UPDATED;
|
||||||
if (likely(tg3_has_work(tp)))
|
if (likely(tg3_has_work(tp)))
|
||||||
netif_rx_schedule(dev); /* schedule NAPI poll */
|
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
|
||||||
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
|
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
|
||||||
0x00000001);
|
0x00000001);
|
||||||
tp->last_tag = sblk->status_tag;
|
tp->last_tag = sblk->status_tag;
|
||||||
|
rmb();
|
||||||
sblk->status &= ~SD_STATUS_UPDATED;
|
sblk->status &= ~SD_STATUS_UPDATED;
|
||||||
if (likely(tg3_has_work(tp)))
|
if (likely(tg3_has_work(tp)))
|
||||||
netif_rx_schedule(dev); /* schedule NAPI poll */
|
netif_rx_schedule(dev); /* schedule NAPI poll */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче