Skip site navigation (1)Skip section navigation (2)
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>