diff options
author | jfv <jfv@FreeBSD.org> | 2009-04-27 17:22:14 +0000 |
---|---|---|
committer | jfv <jfv@FreeBSD.org> | 2009-04-27 17:22:14 +0000 |
commit | 6554abda25227ccc6555c01fac641f8d87049fa0 (patch) | |
tree | df0fd2ab6e954ad28b5a52b4e3d7cee49ed4be79 /sys/dev/e1000 | |
parent | 4b9dbf472da5f546dbd62e12cafd5d7941e4eefb (diff) | |
download | FreeBSD-src-6554abda25227ccc6555c01fac641f8d87049fa0.zip FreeBSD-src-6554abda25227ccc6555c01fac641f8d87049fa0.tar.gz |
Thanks for Michael Tuexen for tracking down a path where
the watchdog timer was not being rearmed in txeof, and also
a missing case in the new code.
MFC after: 2 weeks
Diffstat (limited to 'sys/dev/e1000')
-rw-r--r-- | sys/dev/e1000/if_em.c | 35 |
1 files changed, 21 insertions, 14 deletions
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index aca92eb..9229d50 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -1013,12 +1013,15 @@ em_transmit_locked(struct ifnet *ifp, struct mbuf *m) if (ADAPTER_RING_EMPTY(adapter) && (adapter->num_tx_desc_avail > EM_TX_OP_THRESHOLD)) { if (em_xmit(adapter, &m)) { - if (m && (error = drbr_enqueue(ifp, adapter->br, m)) != 0) { + if (m && (error = drbr_enqueue(ifp, adapter->br, m)) != 0) return (error); - } - } else{ - /* Send a copy of the frame to the BPF listener */ + } else { + /* + ** Send a copy of the frame to the BPF + ** listener and set the watchdog on. + */ ETHER_BPF_MTAP(ifp, m); + addapter->watchdog_timer = EM_TX_TIMEOUT; } } else if ((error = drbr_enqueue(ifp, adapter->br, m)) != 0) return (error); @@ -1086,6 +1089,8 @@ em_start_locked(struct ifnet *ifp) if (em_xmit(adapter, &m_head)) { if (m_head == NULL) break; + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + IFQ_DRV_PREPEND(&ifp->if_snd, m_head); break; } @@ -4029,6 +4034,7 @@ static void em_txeof(struct adapter *adapter) { int first, last, done, num_avail; + u32 cleaned = 0; struct em_buffer *tx_buffer; struct e1000_tx_desc *tx_desc, *eop_desc; struct ifnet *ifp = adapter->ifp; @@ -4064,7 +4070,7 @@ em_txeof(struct adapter *adapter) tx_desc->upper.data = 0; tx_desc->lower.data = 0; tx_desc->buffer_addr = 0; - num_avail++; + ++num_avail; ++cleaned; if (tx_buffer->m_head) { ifp->if_opackets++; @@ -4101,21 +4107,22 @@ em_txeof(struct adapter *adapter) adapter->next_tx_to_clean = first; /* - * If we have enough room, clear IFF_DRV_OACTIVE to tell the stack - * that it is OK to send packets. - * If there are no pending descriptors, clear the timeout. Otherwise, - * if some descriptors have been freed, restart the timeout. + * If we have enough room, clear IFF_DRV_OACTIVE to + * tell the stack that it is OK to send packets. + * If there are no pending descriptors, clear the timeout. */ if (num_avail > EM_TX_CLEANUP_THRESHOLD) { ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - /* All clean, turn off the timer */ if (num_avail == adapter->num_tx_desc) { adapter->watchdog_timer = 0; - } else - /* Some cleaned, reset the timer */ - if (num_avail != adapter->num_tx_desc_avail) - adapter->watchdog_timer = EM_TX_TIMEOUT; + adapter->num_tx_desc_avail = num_avail; + return; + } } + + /* If any descriptors cleaned, reset the watchdog */ + if (cleaned) + adapter->watchdog_timer = EM_TX_TIMEOUT; adapter->num_tx_desc_avail = num_avail; return; } |