summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2004-11-14 20:20:28 +0000
committerrwatson <rwatson@FreeBSD.org>2004-11-14 20:20:28 +0000
commit0188f1bf36ef4568e79b40fbe6a65cd179c8330e (patch)
tree3d80496e2696fffb01a74115b98494f71b1c4417
parent36c3b3ee0bf3a94e9f93a2529bc1faebcdf5ed33 (diff)
downloadFreeBSD-src-0188f1bf36ef4568e79b40fbe6a65cd179c8330e.zip
FreeBSD-src-0188f1bf36ef4568e79b40fbe6a65cd179c8330e.tar.gz
Further refine the if_em vlan fix in if_em.c:1.53:
- Because em_encap() can now fail in a way that leaves us without an mbuf chain, potentially set *m_headp to NULL if that happens, so that the caller can do the right thing. This case can occur when we try to prepend the vlan header mbuf but can't allocate additional memory. - Modify the caller of em_encap() to detect a NULL m_head and not try to queue the mbuf if that happens. - When em_encap() fails, make sure to call bus_dmamap_destroy() to clean up.
-rw-r--r--sys/dev/em/if_em.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c
index 51a574e..7d889f5 100644
--- a/sys/dev/em/if_em.c
+++ b/sys/dev/em/if_em.c
@@ -598,8 +598,14 @@ em_start_locked(struct ifnet *ifp)
IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
if (m_head == NULL) break;
-
+
+ /*
+ * em_encap() can modify our pointer, and or make it NULL on
+ * failure. In that event, we can't requeue.
+ */
if (em_encap(adapter, &m_head)) {
+ if (m_head == NULL)
+ break;
ifp->if_flags |= IFF_OACTIVE;
IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
break;
@@ -1248,15 +1254,24 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp)
struct ether_header eh;
m_head = m_pullup(m_head, sizeof(eh));
- if (m_head == NULL)
+ if (m_head == NULL) {
+ *m_headp = NULL;
+ bus_dmamap_destroy(adapter->txtag, q.map);
return (ENOBUFS);
+ }
eh = *mtod(m_head, struct ether_header *);
M_PREPEND(m_head, sizeof(*evl), M_DONTWAIT);
- if (m_head == NULL)
+ if (m_head == NULL) {
+ *m_headp = NULL;
+ bus_dmamap_destroy(adapter->txtag, q.map);
return (ENOBUFS);
+ }
m_head = m_pullup(m_head, sizeof(*evl));
- if (m_head == NULL)
+ if (m_head == NULL) {
+ *m_headp = NULL;
+ bus_dmamap_destroy(adapter->txtag, q.map);
return (ENOBUFS);
+ }
evl = mtod(m_head, struct ether_vlan_header *);
bcopy(&eh, evl, sizeof(*evl));
evl->evl_proto = evl->evl_encap_proto;
OpenPOWER on IntegriCloud