Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 18 Apr 2015 00:35:01 +0000 (UTC)
From:      Luiz Otavio O Souza <loos@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r281675 - head/sys/arm/allwinner
Message-ID:  <201504180035.t3I0Z1i1094769@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: loos
Date: Sat Apr 18 00:35:00 2015
New Revision: 281675
URL: https://svnweb.freebsd.org/changeset/base/281675

Log:
  Simplify the receiver code a bit.
  
  Drain the RX FIFO and continue on failure.

Modified:
  head/sys/arm/allwinner/if_emac.c
  head/sys/arm/allwinner/if_emacreg.h

Modified: head/sys/arm/allwinner/if_emac.c
==============================================================================
--- head/sys/arm/allwinner/if_emac.c	Sat Apr 18 00:30:36 2015	(r281674)
+++ head/sys/arm/allwinner/if_emac.c	Sat Apr 18 00:35:00 2015	(r281675)
@@ -254,6 +254,15 @@ emac_reset(struct emac_softc *sc)
 }
 
 static void
+emac_drain_rxfifo(struct emac_softc *sc)
+{
+	uint32_t data;
+
+	while (EMAC_READ_REG(sc, EMAC_RX_FBC) > 0)
+		data = EMAC_READ_REG(sc, EMAC_RX_IO_DATA);
+}
+
+static void
 emac_txeof(struct emac_softc *sc, uint32_t status)
 {
 	struct ifnet *ifp;
@@ -281,7 +290,7 @@ emac_rxeof(struct emac_softc *sc, int co
 	uint32_t reg_val, rxcount;
 	int16_t len;
 	uint16_t status;
-	int good_packet, i;
+	int i;
 
 	ifp = sc->emac_ifp;
 	for (; count > 0 &&
@@ -333,20 +342,19 @@ emac_rxeof(struct emac_softc *sc, int co
 			return;
 		}
 
-		good_packet = 1;
-
 		/* Get packet size and status */
 		reg_val = EMAC_READ_REG(sc, EMAC_RX_IO_DATA);
 		len = reg_val & 0xffff;
 		status = (reg_val >> 16) & 0xffff;
 
-		if (len < 64) {
-			good_packet = 0;
+		if (len < 64 || (status & EMAC_PKT_OK) == 0) {
 			if (bootverbose)
 				if_printf(ifp,
 				    "bad packet: len = %i status = %i\n",
 				    len, status);
 			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+			emac_drain_rxfifo(sc);
+			continue;
 		}
 #if 0
 		if (status & (EMAC_CRCERR | EMAC_LENERR)) {
@@ -358,61 +366,58 @@ emac_rxeof(struct emac_softc *sc, int co
 				if_printf(ifp, "length error\n");
 		}
 #endif
-		if (good_packet) {
-			m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
-			if (m == NULL)
-				return;
-			m->m_len = m->m_pkthdr.len = MCLBYTES;
+		m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+		if (m == NULL) {
+			emac_drain_rxfifo(sc);
+			return;
+		}
+		m->m_len = m->m_pkthdr.len = MCLBYTES;
 
-			/* Copy entire frame to mbuf first. */
-			bus_space_read_multi_4(sc->emac_tag, sc->emac_handle,
-			    EMAC_RX_IO_DATA, mtod(m, uint32_t *),
-			    roundup2(len, 4) / 4);
-
-			m->m_pkthdr.rcvif = ifp;
-			m->m_len = m->m_pkthdr.len = len - ETHER_CRC_LEN;
-
-			/*
-			 * Emac controller needs strict aligment, so to avoid
-			 * copying over an entire frame to align, we allocate
-			 * a new mbuf and copy ethernet header + IP header to
-			 * the new mbuf. The new mbuf is prepended into the
-			 * existing mbuf chain.
-			 */
-			if (m->m_len <= (MHLEN - ETHER_HDR_LEN)) {
-				bcopy(m->m_data, m->m_data + ETHER_HDR_LEN,
-				    m->m_len);
-				m->m_data += ETHER_HDR_LEN;
-			} else if (m->m_len <= (MCLBYTES - ETHER_HDR_LEN) &&
-			    m->m_len > (MHLEN - ETHER_HDR_LEN)) {
-				MGETHDR(m0, M_NOWAIT, MT_DATA);
-				if (m0 != NULL) {
-					len = ETHER_HDR_LEN +
-					    m->m_pkthdr.l2hlen;
-					bcopy(m->m_data, m0->m_data, len);
-					m->m_data += len;
-					m->m_len -= len;
-					m0->m_len = len;
-					M_MOVE_PKTHDR(m0, m);
-					m0->m_next = m;
-					m = m0;
-				} else {
-					if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
-					m_freem(m);
-					m = NULL;
-					continue;
-				}
-			} else if (m->m_len > EMAC_MAC_MAXF) {
+		/* Copy entire frame to mbuf first. */
+		bus_space_read_multi_4(sc->emac_tag, sc->emac_handle,
+		    EMAC_RX_IO_DATA, mtod(m, uint32_t *), roundup2(len, 4) / 4);
+
+		m->m_pkthdr.rcvif = ifp;
+		m->m_len = m->m_pkthdr.len = len - ETHER_CRC_LEN;
+
+		/*
+		 * Emac controller needs strict aligment, so to avoid
+		 * copying over an entire frame to align, we allocate
+		 * a new mbuf and copy ethernet header + IP header to
+		 * the new mbuf. The new mbuf is prepended into the
+		 * existing mbuf chain.
+		 */
+		if (m->m_len <= (MHLEN - ETHER_HDR_LEN)) {
+			bcopy(m->m_data, m->m_data + ETHER_HDR_LEN, m->m_len);
+			m->m_data += ETHER_HDR_LEN;
+		} else if (m->m_len <= (MCLBYTES - ETHER_HDR_LEN) &&
+		    m->m_len > (MHLEN - ETHER_HDR_LEN)) {
+			MGETHDR(m0, M_NOWAIT, MT_DATA);
+			if (m0 != NULL) {
+				len = ETHER_HDR_LEN + m->m_pkthdr.l2hlen;
+				bcopy(m->m_data, m0->m_data, len);
+				m->m_data += len;
+				m->m_len -= len;
+				m0->m_len = len;
+				M_MOVE_PKTHDR(m0, m);
+				m0->m_next = m;
+				m = m0;
+			} else {
 				if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
 				m_freem(m);
 				m = NULL;
 				continue;
 			}
-			if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
-			EMAC_UNLOCK(sc);
-			(*ifp->if_input)(ifp, m);
-			EMAC_LOCK(sc);
+		} else if (m->m_len > EMAC_MAC_MAXF) {
+			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+			m_freem(m);
+			m = NULL;
+			continue;
 		}
+		if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
+		EMAC_UNLOCK(sc);
+		(*ifp->if_input)(ifp, m);
+		EMAC_LOCK(sc);
 	}
 }
 

Modified: head/sys/arm/allwinner/if_emacreg.h
==============================================================================
--- head/sys/arm/allwinner/if_emacreg.h	Sat Apr 18 00:30:36 2015	(r281674)
+++ head/sys/arm/allwinner/if_emacreg.h	Sat Apr 18 00:35:00 2015	(r281675)
@@ -225,6 +225,7 @@
 /* Receive status */
 #define	EMAC_CRCERR		(1 << 4)
 #define	EMAC_LENERR		(3 << 5)
+#define	EMAC_PKT_OK		(1 << 7)
 
 #define	EMAC_RX_FLUSH_FIFO	(1 << 3)
 #define	EMAC_PHY_RESET		(1 << 15)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201504180035.t3I0Z1i1094769>