Simplify the receiver code a bit.
Drain the RX FIFO and continue on failure.
This commit is contained in:
parent
070cadfcc4
commit
8c2df90ac9
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user