1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-24 11:29:10 +00:00

Handle all error cases from bus_dmamap_load_mbuf_sg(). Those are:

- EFBIG means the mbuf chain was too long and bus_dma ran out of segments.
   Defragment the mbuf chain and try again. (Already existed, not changed.)
 - ENOMEM means bus_dma could not obtain enough bounce buffers at this point
   in time.  Defer sending and try again later.
 - All other errors, in particular EINVAL, are fatal and prevent the mbuf
   chain from ever going through.  Drop it and report error.
 - Checking (nsegs == 0) is unnecessary as bus_dmamap_load_mbuf_sg() always
   reports an error if it is < 1.

This prevents broken packets from clogging the interface queue indefinately.

Discussed with:	scottl
Reviewed by:	jfv
This commit is contained in:
Andre Oppermann 2006-09-29 13:12:38 +00:00
parent aa805a5eb7
commit 5c335b1cc8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=162782

View File

@ -1526,8 +1526,19 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp)
tx_buffer = &adapter->tx_buffer_area[adapter->next_avail_tx_desc];
tx_buffer_last = tx_buffer;
map = tx_buffer->map;
error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, *m_headp, segs,
&nsegs, BUS_DMA_NOWAIT);
/*
* There are two types of errors we can (try) to handle:
* - EFBIG means the mbuf chain was too long and bus_dma ran
* out of segments. Defragment the mbuf chain and try again.
* - ENOMEM means bus_dma could not obtain enough bounce buffers
* at this point in time. Defer sending and try again later.
* All other errors, in particular EINVAL, are fatal and prevent the
* mbuf chain from ever going through. Drop it and report error.
*/
if (error == EFBIG) {
struct mbuf *m;
@ -1540,22 +1551,27 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp)
return (ENOBUFS);
}
*m_headp = m;
error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, *m_headp,
segs, &nsegs, BUS_DMA_NOWAIT);
if (error != 0) {
if (error == ENOMEM) {
adapter->no_tx_dma_setup++;
m_freem(*m_headp);
*m_headp = NULL;
return (error);
}
} else if (error != 0) {
adapter->no_tx_dma_setup++;
return (error);
}
if (nsegs == 0) {
m_freem(*m_headp);
*m_headp = NULL;
return (EIO);
return (error);
}
} else if (error == ENOMEM) {
adapter->no_tx_dma_setup++;
return (error);
} else if (error != 0) {
adapter->no_tx_dma_setup++;
m_freem(*m_headp);
*m_headp = NULL;
return (error);
}
/*