Simplify the receiver code a bit.

Drain the RX FIFO and continue on failure.
This commit is contained in:
Luiz Otavio O Souza 2015-04-18 00:35:00 +00:00
parent 070cadfcc4
commit 8c2df90ac9
2 changed files with 57 additions and 51 deletions

View File

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

View File

@ -225,6 +225,7 @@
/* Receive status */ /* Receive status */
#define EMAC_CRCERR (1 << 4) #define EMAC_CRCERR (1 << 4)
#define EMAC_LENERR (3 << 5) #define EMAC_LENERR (3 << 5)
#define EMAC_PKT_OK (1 << 7)
#define EMAC_RX_FLUSH_FIFO (1 << 3) #define EMAC_RX_FLUSH_FIFO (1 << 3)
#define EMAC_PHY_RESET (1 << 15) #define EMAC_PHY_RESET (1 << 15)