Date: Thu, 25 Oct 2012 04:37:47 +0000 (UTC) From: Tim Kientzle <kientzle@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r242068 - head/sys/arm/ti/cpsw Message-ID: <201210250437.q9P4blcV074467@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kientzle Date: Thu Oct 25 04:37:47 2012 New Revision: 242068 URL: http://svn.freebsd.org/changeset/base/242068 Log: Do proper padding of runt packets using code copied from bge(4). Reviewed by: gnn Modified: head/sys/arm/ti/cpsw/if_cpsw.c Modified: head/sys/arm/ti/cpsw/if_cpsw.c ============================================================================== --- head/sys/arm/ti/cpsw/if_cpsw.c Thu Oct 25 04:33:47 2012 (r242067) +++ head/sys/arm/ti/cpsw/if_cpsw.c Thu Oct 25 04:37:47 2012 (r242068) @@ -581,8 +581,8 @@ cpsw_encap(struct cpsw_softc *sc, struct bd.next = 0; bd.bufptr = seg->ds_addr; bd.bufoff = 0; - bd.buflen = (seg->ds_len < 64 ? 64 : seg->ds_len); - bd.pktlen = (seg->ds_len < 64 ? 64 : seg->ds_len); + bd.buflen = seg->ds_len; + bd.pktlen = seg->ds_len; /* Set OWNERSHIP, SOP, EOP */ bd.flags = (7<<13); @@ -599,6 +599,49 @@ cpsw_encap(struct cpsw_softc *sc, struct return (0); } +/* + * Pad the packet to the minimum length for Ethernet. + * (CPSW hardware doesn't do this for us.) + */ +static int +cpsw_pad(struct mbuf *m) +{ + int padlen = ETHER_MIN_LEN - m->m_pkthdr.len; + struct mbuf *last, *n; + + if (padlen <= 0) + return (0); + + /* If there's only the packet-header and we can pad there, use it. */ + if (m->m_pkthdr.len == m->m_len && M_WRITABLE(m) && + M_TRAILINGSPACE(m) >= padlen) { + last = m; + } else { + /* + * Walk packet chain to find last mbuf. We will either + * pad there, or append a new mbuf and pad it. + */ + for (last = m; last->m_next != NULL; last = last->m_next) + ; + if (!(M_WRITABLE(last) && M_TRAILINGSPACE(last) >= padlen)) { + /* Allocate new empty mbuf, pad it. Compact later. */ + MGET(n, M_DONTWAIT, MT_DATA); + if (n == NULL) + return (ENOBUFS); + n->m_len = 0; + last->m_next = n; + last = n; + } + } + + /* Now zero the pad area. */ + memset(mtod(last, caddr_t) + last->m_len, 0, padlen); + last->m_len += padlen; + m->m_pkthdr.len += padlen; + + return (0); +} + static void cpsw_start(struct ifnet *ifp) { @@ -615,6 +658,7 @@ cpsw_start_locked(struct ifnet *ifp) struct cpsw_softc *sc = ifp->if_softc; struct mbuf *m0, *mtmp; uint32_t queued = 0; + int error; CPSW_TX_LOCK_ASSERT(sc); @@ -628,6 +672,11 @@ cpsw_start_locked(struct ifnet *ifp) if (m0 == NULL) break; + if ((error = cpsw_pad(m0))) { + m_freem(m0); + continue; + } + mtmp = m_defrag(m0, M_NOWAIT); if (mtmp) m0 = mtmp;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201210250437.q9P4blcV074467>