Pull in numerous fixes from myself and cognet. With these fixes the

KB9202 eval board is finally stable with a nfs root.
This commit is contained in:
imp 2006-04-06 04:30:23 +00:00
parent 9a23a843f0
commit b8ec0fd91c

View File

@ -86,13 +86,14 @@ struct ate_softc
struct callout tick_ch; /* Tick callout */
bus_dma_tag_t mtag; /* bus dma tag for mbufs */
bus_dmamap_t tx_map[ATE_MAX_TX_BUFFERS];
struct mbuf *sent_mbuf[ATE_MAX_TX_BUFFERS]; /* Sent mbufs */
bus_dma_tag_t rxtag;
bus_dmamap_t rx_map[ATE_MAX_RX_BUFFERS];
void *rx_buf[ATE_MAX_RX_BUFFERS]; /* RX buffer space */
int rx_buf_ptr;
bus_dma_tag_t rx_desc_tag;
bus_dmamap_t rx_desc_map;
int txcur; /* current tx map pointer */
struct mbuf *sent_mbuf[ATE_MAX_TX_BUFFERS]; /* Sent mbufs */
struct mbuf *rx_mbuf[ATE_MAX_RX_BUFFERS]; /* RX mbufs */
bus_addr_t rx_desc_phys;
eth_rx_desc_t *rx_descs;
struct ifmib_iso_8802_3 mibdata; /* stuff for network mgmt */
@ -241,6 +242,30 @@ ate_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
sc->rx_desc_phys = segs[0].ds_addr;
}
static void
ate_load_rx_buf(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
{
struct ate_softc *sc;
int i;
if (error != 0)
return;
sc = (struct ate_softc *)arg;
i = sc->rx_buf_ptr;
/*
* For the last buffer, set the wrap bit so the controller
* restarts from the first descriptor.
*/
if (i == ATE_MAX_RX_BUFFERS - 1)
sc->rx_descs[i].addr = segs[0].ds_addr | ETH_WRAP_BIT;
else
sc->rx_descs[i].addr = segs[0].ds_addr;
sc->rx_descs[i].status = 0;
/* Flush the memory in the mbuf */
bus_dmamap_sync(sc->rxtag, sc->rx_map[i], BUS_DMASYNC_PREREAD);
}
/*
* Compute the multicast filter for this device using the standard
* algorithm. I wonder why this isn't in ether somewhere as a lot
@ -275,10 +300,8 @@ ate_setmcast(struct ate_softc *sc)
* advantage of that. Locks here are to avoid LOR with the
* IF_ADDR_LOCK, but might not be strictly necessary.
*/
ATE_LOCK(sc);
WR4(sc, ETH_HSL, mcaf[0]);
WR4(sc, ETH_HSH, mcaf[1]);
ATE_UNLOCK(sc);
}
static int
@ -342,33 +365,21 @@ ate_activate(device_t dev)
if (bus_dmamem_alloc(sc->rx_desc_tag, (void **)&sc->rx_descs,
BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->rx_desc_map) != 0)
goto errout;
if (bus_dmamap_load(sc->rx_desc_tag, sc->rx_desc_map,
if (bus_dmamap_load(sc->rx_desc_tag, sc->rx_desc_map,
sc->rx_descs, ATE_MAX_RX_BUFFERS * sizeof(eth_rx_desc_t),
ate_getaddr, sc, 0) != 0)
goto errout;
/* XXX TODO(5) Put this in ateinit_locked? */
for (i = 0; i < ATE_MAX_RX_BUFFERS; i++) {
bus_dma_segment_t seg;
int nsegs;
sc->rx_mbuf[i] = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR);
sc->rx_mbuf[i]->m_len = sc->rx_mbuf[i]->m_pkthdr.len =
MCLBYTES;
if (bus_dmamap_load_mbuf_sg(sc->rxtag, sc->rx_map[i],
sc->rx_mbuf[i], &seg, &nsegs, 0) != 0)
sc->rx_buf_ptr = i;
if (bus_dmamem_alloc(sc->rxtag, (void **)&sc->rx_buf[i],
BUS_DMA_NOWAIT, &sc->rx_map[i]) != 0)
goto errout;
if (bus_dmamap_load(sc->rxtag, sc->rx_map[i], sc->rx_buf[i],
MCLBYTES, ate_load_rx_buf, sc, 0) != 0)
goto errout;
/*
* For the last buffer, set the wrap bit so the controller
* restarts from the first descriptor.
*/
if (i == ATE_MAX_RX_BUFFERS - 1)
sc->rx_descs[i].addr = seg.ds_addr | ETH_WRAP_BIT;
else
sc->rx_descs[i].addr = seg.ds_addr;
sc->rx_descs[i].status = 0;
/* Flush the memory in the mbuf */
bus_dmamap_sync(sc->rxtag, sc->rx_map[i], BUS_DMASYNC_PREREAD);
}
sc->rx_buf_ptr = 0;
/* Flush the memory for the EMAC rx descriptor */
bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_PREWRITE);
/* Write the descriptor queue address. */
@ -577,104 +588,47 @@ ate_intr(void *xsc)
struct ate_softc *sc = xsc;
int status;
int i;
struct mbuf *mb, *tmp_mbuf;
bus_dma_segment_t seg;
int rx_stat;
int nsegs;
void *bp;
struct mbuf *mb;
uint32_t rx_stat;
status = RD4(sc, ETH_ISR);
if (status == 0)
return;
if (status & ETH_ISR_RCOM) {
bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map,
BUS_DMASYNC_POSTREAD);
for (i = 0; i < ATE_MAX_RX_BUFFERS; i++) {
if ((sc->rx_descs[i].addr & ETH_CPU_OWNER) == 0)
continue;
mb = sc->rx_mbuf[i];
while (sc->rx_descs[sc->rx_buf_ptr].addr & ETH_CPU_OWNER) {
i = sc->rx_buf_ptr;
sc->rx_buf_ptr = (i + 1) % ATE_MAX_RX_BUFFERS;
bp = sc->rx_buf[i];
rx_stat = sc->rx_descs[i].status;
if ((rx_stat & ETH_LEN_MASK) == 0) {
printf("ignoring bogus 0 len packet\n");
bus_dmamap_load_mbuf_sg(sc->rxtag,
sc->rx_map[i], sc->rx_mbuf[i],
&seg, &nsegs, 0);
sc->rx_descs[i].status = 0;
sc->rx_descs[i].addr = seg.ds_addr;
if (i == ATE_MAX_RX_BUFFERS - 1)
sc->rx_descs[i].addr |=
ETH_WRAP_BIT;
/* Flush memory for mbuf */
bus_dmamap_sync(sc->rxtag, sc->rx_map[i],
BUS_DMASYNC_PREREAD);
/* Flush rx dtor table rx_descs */
sc->rx_descs[i].addr &= ~ETH_CPU_OWNER;
bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map,
BUS_DMASYNC_PREWRITE);
continue;
}
/* Flush memory for mbuf so we don't get stale bytes */
bus_dmamap_sync(sc->rxtag, sc->rx_map[i],
BUS_DMASYNC_POSTREAD);
WR4(sc, ETH_RSR, RD4(sc, ETH_RSR));
/*
* Allocate a new buffer to replace this one.
* if we cannot, then we drop this packet
* and keep the old buffer we had. Once allocated
* the new buffer is loaded for dma.
*/
sc->rx_mbuf[i] = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
if (!sc->rx_mbuf[i]) {
printf("Failed to get another mbuf -- discarding packet\n");
sc->rx_mbuf[i] = mb;
sc->rx_descs[i].addr &= ~ETH_CPU_OWNER;
bus_dmamap_sync(sc->rxtag, sc->rx_map[i],
BUS_DMASYNC_PREREAD);
bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map,
BUS_DMASYNC_PREWRITE);
continue;
}
sc->rx_mbuf[i]->m_len =
sc->rx_mbuf[i]->m_pkthdr.len = MCLBYTES;
bus_dmamap_unload(sc->rxtag, sc->rx_map[i]);
if (bus_dmamap_load_mbuf_sg(sc->rxtag, sc->rx_map[i],
sc->rx_mbuf[i], &seg, &nsegs, 0) != 0) {
printf("Failed to load mbuf -- discarding packet -- reload old?\n");
sc->rx_mbuf[i] = mb;
sc->rx_descs[i].addr &= ~ETH_CPU_OWNER;
bus_dmamap_sync(sc->rxtag, sc->rx_map[i],
BUS_DMASYNC_PREREAD);
bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map,
BUS_DMASYNC_PREWRITE);
continue;
}
WR4(sc, ETH_RSR, RD4(sc, ETH_RSR)); // XXX WHY? XXX imp
/*
* The length returned by the device includes the
* ethernet CRC calculation for the packet, but
* ifnet drivers are supposed to discard it.
*/
mb->m_len = (rx_stat & ETH_LEN_MASK) - ETHER_CRC_LEN;
mb->m_pkthdr.len = mb->m_len;
mb->m_pkthdr.rcvif = sc->ifp;
tmp_mbuf = m_devget(mtod(mb, caddr_t), mb->m_len,
ETHER_ALIGN, sc->ifp, NULL);
m_free(mb);
/*
* For the last buffer, set the wrap bit so
* the controller restarts from the first
* descriptor.
*/
sc->rx_descs[i].status = 0;
sc->rx_descs[i].addr = seg.ds_addr;
if (i == ATE_MAX_RX_BUFFERS - 1)
sc->rx_descs[i].addr |= ETH_WRAP_BIT;
bus_dmamap_sync(sc->rxtag, sc->rx_map[i],
BUS_DMASYNC_PREREAD);
mb = m_devget(sc->rx_buf[i],
(rx_stat & ETH_LEN_MASK) - ETHER_CRC_LEN,
ETHER_ALIGN, sc->ifp, NULL);
sc->rx_descs[i].addr &= ~ETH_CPU_OWNER;
bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map,
BUS_DMASYNC_PREWRITE);
if (tmp_mbuf != NULL)
(*sc->ifp->if_input)(sc->ifp, tmp_mbuf);
bus_dmamap_sync(sc->rxtag, sc->rx_map[i],
BUS_DMASYNC_PREREAD);
if (mb != NULL)
(*sc->ifp->if_input)(sc->ifp, mb);
}
}
if (status & ETH_ISR_TCOM) {
@ -760,7 +714,6 @@ ateinit_locked(void *xsc)
* the byte order is big endian, not little endian, so we have some
* swapping to do. Again, if we need it (which I don't think we do).
*/
ate_setmcast(sc);
/*
@ -926,6 +879,8 @@ static int
ateioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct ate_softc *sc = ifp->if_softc;
struct mii_data *mii;
struct ifreq *ifr = (struct ifreq *)data;
int error = 0;
switch (cmd) {
@ -945,10 +900,17 @@ ateioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCADDMULTI:
case SIOCDELMULTI:
/* update multicast filter list. */
ATE_LOCK(sc);
ate_setmcast(sc);
ATE_UNLOCK(sc);
error = 0;
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
mii = device_get_softc(sc->miibus);
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
break;
default:
error = ether_ioctl(ifp, cmd, data);
break;