Simplify the handling of small packets padding in cpsw:

- Pad small packets to 60 bytes and not 64 (exclude the CRC bytes);
 - Pad the packet using m_append(9), if the packet has enough space for
   padding, which is usually true, it will not be necessary append a newly
   allocated mbuf to the chain.

Suggested by:	yongari
MFC after:	3 days
Sponsored by:	Rubicon Communications, LLC (Netgate)
This commit is contained in:
Luiz Otavio O Souza 2017-01-21 19:49:39 +00:00
parent 0c629e2884
commit 904e8e891b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=312604

View File

@ -783,8 +783,7 @@ cpsw_get_fdt_data(struct cpsw_softc *sc, int port)
static int
cpsw_attach(device_t dev)
{
bus_dma_segment_t segs[1];
int error, i, nsegs;
int error, i;
struct cpsw_softc *sc;
uint32_t reg;
@ -859,15 +858,8 @@ cpsw_attach(device_t dev)
return (error);
}
/* Allocate the null mbuf and pre-sync it. */
sc->null_mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
memset(sc->null_mbuf->m_data, 0, sc->null_mbuf->m_ext.ext_size);
bus_dmamap_create(sc->mbuf_dtag, 0, &sc->null_mbuf_dmamap);
bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, sc->null_mbuf_dmamap,
sc->null_mbuf, segs, &nsegs, BUS_DMA_NOWAIT);
bus_dmamap_sync(sc->mbuf_dtag, sc->null_mbuf_dmamap,
BUS_DMASYNC_PREWRITE);
sc->null_mbuf_paddr = segs[0].ds_addr;
/* Allocate a NULL buffer for padding. */
sc->nullpad = malloc(ETHER_MIN_LEN, M_DEVBUF, M_WAITOK | M_ZERO);
cpsw_init_slots(sc);
@ -946,13 +938,9 @@ cpsw_detach(device_t dev)
for (i = 0; i < nitems(sc->_slots); ++i)
cpsw_free_slot(sc, &sc->_slots[i]);
/* Free null mbuf. */
if (sc->null_mbuf_dmamap) {
bus_dmamap_unload(sc->mbuf_dtag, sc->null_mbuf_dmamap);
error = bus_dmamap_destroy(sc->mbuf_dtag, sc->null_mbuf_dmamap);
KASSERT(error == 0, ("Mapping still active"));
m_freem(sc->null_mbuf);
}
/* Free null padding buffer. */
if (sc->nullpad)
free(sc->nullpad, M_DEVBUF);
/* Free DMA tag */
if (sc->mbuf_dtag) {
@ -1829,21 +1817,19 @@ cpswp_tx_enqueue(struct cpswp_softc *sc)
break;
slot->mbuf = m0;
padlen = ETHER_MIN_LEN - slot->mbuf->m_pkthdr.len;
padlen = ETHER_MIN_LEN - ETHER_CRC_LEN - m0->m_pkthdr.len;
if (padlen < 0)
padlen = 0;
else if (padlen > 0)
m_append(slot->mbuf, padlen, sc->swsc->nullpad);
/* Create mapping in DMA memory */
error = bus_dmamap_load_mbuf_sg(sc->swsc->mbuf_dtag,
slot->dmamap, slot->mbuf, segs, &nsegs, BUS_DMA_NOWAIT);
/* If the packet is too fragmented, try to simplify. */
if (error == EFBIG ||
(error == 0 &&
nsegs + (padlen > 0 ? 1 : 0) > sc->swsc->tx.avail_queue_len)) {
(error == 0 && nsegs > sc->swsc->tx.avail_queue_len)) {
bus_dmamap_unload(sc->swsc->mbuf_dtag, slot->dmamap);
if (padlen > 0) /* May as well add padding. */
m_append(slot->mbuf, padlen,
sc->swsc->null_mbuf->m_data);
m0 = m_defrag(slot->mbuf, M_NOWAIT);
if (m0 == NULL) {
device_printf(sc->dev,
@ -1895,7 +1881,7 @@ cpswp_tx_enqueue(struct cpswp_softc *sc)
bd.bufptr = segs[0].ds_addr;
bd.bufoff = 0;
bd.buflen = segs[0].ds_len;
bd.pktlen = m_length(slot->mbuf, NULL) + padlen;
bd.pktlen = m_length(slot->mbuf, NULL);
bd.flags = CPDMA_BD_SOP | CPDMA_BD_OWNER;
if (sc->swsc->dualemac) {
bd.flags |= CPDMA_BD_TO_PORT;
@ -1920,42 +1906,18 @@ cpswp_tx_enqueue(struct cpswp_softc *sc)
bd.pktlen = 0;
bd.flags = CPDMA_BD_OWNER;
}
/* Save the final buffer. */
if (padlen <= 0)
bd.flags |= CPDMA_BD_EOP;
else {
next = STAILQ_NEXT(slot, next);
bd.next = cpsw_cpdma_bd_paddr(sc->swsc, next);
}
bd.flags |= CPDMA_BD_EOP;
cpsw_cpdma_write_bd(sc->swsc, slot, &bd);
STAILQ_REMOVE_HEAD(&sc->swsc->tx.avail, next);
STAILQ_INSERT_TAIL(&sc->swsc->tx.active, slot, next);
if (padlen > 0) {
slot = STAILQ_FIRST(&sc->swsc->tx.avail);
/* Setup buffer of null pad bytes (definitely EOP). */
bd.next = 0;
bd.bufptr = sc->swsc->null_mbuf_paddr;
bd.bufoff = 0;
bd.buflen = padlen;
bd.pktlen = 0;
bd.flags = CPDMA_BD_EOP | CPDMA_BD_OWNER;
cpsw_cpdma_write_bd(sc->swsc, slot, &bd);
++nsegs;
STAILQ_REMOVE_HEAD(&sc->swsc->tx.avail, next);
STAILQ_INSERT_TAIL(&sc->swsc->tx.active, slot, next);
}
last = slot;
added += nsegs;
if (nsegs > sc->swsc->tx.longest_chain)
sc->swsc->tx.longest_chain = nsegs;
// TODO: Should we defer the BPF tap until
// after all packets are queued?
BPF_MTAP(sc->ifp, m0);
}