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.
This commit is contained in:
Robert Watson 2004-11-14 20:20:28 +00:00
parent acebe0cb2c
commit 1eef0330d9

View File

@ -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;