diff options
author | np <np@FreeBSD.org> | 2010-02-24 01:44:39 +0000 |
---|---|---|
committer | np <np@FreeBSD.org> | 2010-02-24 01:44:39 +0000 |
commit | 66381a9263e899c350aea8b45cdb9db918f8be85 (patch) | |
tree | 70c471d23825d9622fc58f793077e77411c05ec5 /sys/dev/cxgb/cxgb_sge.c | |
parent | 8e85b4c3727d0ecd8b7562c84598204916227128 (diff) | |
download | FreeBSD-src-66381a9263e899c350aea8b45cdb9db918f8be85.zip FreeBSD-src-66381a9263e899c350aea8b45cdb9db918f8be85.tar.gz |
Accessing an mbuf after it has been handed off to the hardware is a bad
race as it could already have been tx'd and freed by that time. Place
the bpf tap just _before_ writing the gen bit.
This fixes a panic when running tcpdump on a cxgb interface.
Diffstat (limited to 'sys/dev/cxgb/cxgb_sge.c')
-rw-r--r-- | sys/dev/cxgb/cxgb_sge.c | 30 |
1 files changed, 8 insertions, 22 deletions
diff --git a/sys/dev/cxgb/cxgb_sge.c b/sys/dev/cxgb/cxgb_sge.c index 27a7c89..8060da0 100644 --- a/sys/dev/cxgb/cxgb_sge.c +++ b/sys/dev/cxgb/cxgb_sge.c @@ -1477,6 +1477,7 @@ t3_encap(struct sge_qset *qs, struct mbuf **m) V_WR_GEN(txqs.gen)) | htonl(V_WR_TID(txq->token)); set_wr_hdr(wrp, wr_hi, wr_lo); wmb(); + ETHER_BPF_MTAP(pi->ifp, m0); wr_gen2(txd, txqs.gen); check_ring_tx_db(sc, txq); return (0); @@ -1549,8 +1550,10 @@ t3_encap(struct sge_qset *qs, struct mbuf **m) V_WR_GEN(txqs.gen) | V_WR_TID(txq->token)); set_wr_hdr(&hdr->wr, wr_hi, wr_lo); wmb(); + ETHER_BPF_MTAP(pi->ifp, m0); wr_gen2(txd, txqs.gen); check_ring_tx_db(sc, txq); + m_freem(m0); return (0); } flits = 3; @@ -1578,8 +1581,10 @@ t3_encap(struct sge_qset *qs, struct mbuf **m) V_WR_GEN(txqs.gen) | V_WR_TID(txq->token)); set_wr_hdr(&cpl->wr, wr_hi, wr_lo); wmb(); + ETHER_BPF_MTAP(pi->ifp, m0); wr_gen2(txd, txqs.gen); check_ring_tx_db(sc, txq); + m_freem(m0); return (0); } flits = 2; @@ -1590,12 +1595,14 @@ t3_encap(struct sge_qset *qs, struct mbuf **m) sgl_flits = sgl_len(nsegs); + ETHER_BPF_MTAP(pi->ifp, m0); + KASSERT(ndesc <= 4, ("ndesc too large %d", ndesc)); wr_hi = htonl(V_WR_OP(FW_WROPCODE_TUNNEL_TX_PKT) | txqs.compl); wr_lo = htonl(V_WR_TID(txq->token)); write_wr_hdr_sgl(ndesc, txd, &txqs, txq, sgl, flits, sgl_flits, wr_hi, wr_lo); - check_ring_tx_db(pi->adapter, txq); + check_ring_tx_db(sc, txq); return (0); } @@ -1674,16 +1681,6 @@ cxgb_start_locked(struct sge_qset *qs) */ if (t3_encap(qs, &m_head) || m_head == NULL) break; - - /* Send a copy of the frame to the BPF listener */ - ETHER_BPF_MTAP(ifp, m_head); - - /* - * We sent via PIO, no longer need a copy - */ - if (m_head->m_nextpkt == NULL && - m_head->m_pkthdr.len <= PIO_LEN) - m_freem(m_head); m_head = NULL; } @@ -1726,17 +1723,6 @@ cxgb_transmit_locked(struct ifnet *ifp, struct sge_qset *qs, struct mbuf *m) */ txq->txq_direct_packets++; txq->txq_direct_bytes += m->m_pkthdr.len; - /* - ** Send a copy of the frame to the BPF - ** listener and set the watchdog on. - */ - ETHER_BPF_MTAP(ifp, m); - /* - * We sent via PIO, no longer need a copy - */ - if (m->m_pkthdr.len <= PIO_LEN) - m_freem(m); - } } else if ((error = drbr_enqueue(ifp, br, m)) != 0) return (error); |