Module Name: src
Committed By: jmcneill
Date: Mon Jan 5 21:57:49 UTC 2015
Modified Files:
src/sys/arch/arm/rockchip: rockchip_emac.c
Log Message:
various fixes from FUKAUMI Naoki <[email protected]> and martin@
To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/rockchip/rockchip_emac.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/arm/rockchip/rockchip_emac.c
diff -u src/sys/arch/arm/rockchip/rockchip_emac.c:1.2 src/sys/arch/arm/rockchip/rockchip_emac.c:1.3
--- src/sys/arch/arm/rockchip/rockchip_emac.c:1.2 Sun Jan 4 11:54:43 2015
+++ src/sys/arch/arm/rockchip/rockchip_emac.c Mon Jan 5 21:57:49 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: rockchip_emac.c,v 1.2 2015/01/04 11:54:43 jmcneill Exp $ */
+/* $NetBSD: rockchip_emac.c,v 1.3 2015/01/05 21:57:49 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -29,7 +29,7 @@
#include "opt_rkemac.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rockchip_emac.c,v 1.2 2015/01/04 11:54:43 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rockchip_emac.c,v 1.3 2015/01/05 21:57:49 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -119,6 +119,7 @@ struct rkemac_softc {
bus_dma_segment_t sc_ring_dmaseg;
struct rkemac_txring sc_txq;
struct rkemac_rxring sc_rxq;
+ bus_addr_t sc_pad_physaddr;
};
static int rkemac_match(device_t, cfdata_t, void *);
@@ -186,8 +187,8 @@ rkemac_attach(device_t parent, device_t
} else {
soc_con1_reg = 0x0154;
}
- bus_space_subregion(obio->obio_bst, obio->obio_bsh,
- ROCKCHIP_GRF_OFFSET + soc_con1_reg, 4, &sc->sc_soc_con1_bsh);
+ bus_space_subregion(obio->obio_bst, obio->obio_grf_bsh, soc_con1_reg,
+ 4, &sc->sc_soc_con1_bsh);
aprint_naive("\n");
aprint_normal(": Ethernet controller\n");
@@ -275,7 +276,8 @@ static int
rkemac_dma_init(struct rkemac_softc *sc)
{
size_t descsize = RKEMAC_RX_RING_COUNT * sizeof(struct rkemac_rxdesc) +
- RKEMAC_TX_RING_COUNT * sizeof(struct rkemac_txdesc);
+ RKEMAC_TX_RING_COUNT * sizeof(struct rkemac_txdesc) +
+ ETHER_MIN_LEN;
bus_addr_t physaddr;
int error, nsegs;
void *descs;
@@ -310,6 +312,9 @@ rkemac_dma_init(struct rkemac_softc *sc)
sc->sc_txq.t_physaddr = sc->sc_rxq.r_physaddr +
RKEMAC_RX_RING_COUNT * sizeof(struct rkemac_rxdesc);
+ sc->sc_pad_physaddr = sc->sc_txq.t_physaddr +
+ RKEMAC_TX_RING_COUNT * sizeof(struct rkemac_txdesc);
+
/*
* Setup RX ring
*/
@@ -538,6 +543,8 @@ rkemac_init(struct ifnet *ifp)
control |= EMAC_CONTROL_EN;
EMAC_WRITE(sc, EMAC_CONTROL_REG, control);
+ callout_schedule(&sc->sc_mii_tick, hz);
+
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
@@ -548,7 +555,8 @@ static void
rkemac_start(struct ifnet *ifp)
{
struct rkemac_softc *sc = ifp->if_softc;
- int old = sc->sc_txq.t_queued;
+ const int old = sc->sc_txq.t_queued;
+ const int start = sc->sc_txq.t_cur;
struct mbuf *m0;
if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
@@ -567,10 +575,9 @@ rkemac_start(struct ifnet *ifp)
}
if (sc->sc_txq.t_queued != old) {
- rkemac_txdesc_sync(sc, old, sc->sc_txq.t_cur,
+ rkemac_txdesc_sync(sc, start, sc->sc_txq.t_cur,
BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
- EMAC_WRITE(sc, EMAC_STAT_REG,
- EMAC_READ(sc, EMAC_STAT_REG) | EMAC_STAT_TXPL);
+ EMAC_WRITE(sc, EMAC_STAT_REG, EMAC_STAT_TXPL);
}
}
@@ -694,8 +701,6 @@ rkemac_queue(struct rkemac_softc *sc, st
map = sc->sc_txq.t_data[first].td_map;
info = 0;
- KASSERT(map->dm_nsegs > 0);
-
error = bus_dmamap_load_mbuf(sc->sc_dmat, map, m0,
BUS_DMA_WRITE | BUS_DMA_NOWAIT);
if (error) {
@@ -703,7 +708,12 @@ rkemac_queue(struct rkemac_softc *sc, st
return error;
}
- if (sc->sc_txq.t_queued + map->dm_nsegs >= RKEMAC_TX_RING_COUNT - 1) {
+ KASSERT(map->dm_nsegs > 0);
+
+ const u_int nbufs = map->dm_nsegs +
+ ((m0->m_pkthdr.len < ETHER_MIN_LEN) ? 1 : 0);
+
+ if (sc->sc_txq.t_queued + nbufs >= RKEMAC_TX_RING_COUNT - 1) {
bus_dmamap_unload(sc->sc_dmat, map);
return ENOBUFS;
}
@@ -715,11 +725,23 @@ rkemac_queue(struct rkemac_softc *sc, st
tx->tx_ptr = htole32(map->dm_segs[i].ds_addr);
len = __SHIFTIN(map->dm_segs[i].ds_len, EMAC_TXDESC_TXLEN);
- if (i == map->dm_nsegs - 1)
- info |= EMAC_TXDESC_LAST;
tx->tx_info = htole32(info | len);
- if (i > 0)
- tx->tx_info |= EMAC_TXDESC_OWN;
+ info &= ~EMAC_TXDESC_FIRST;
+ info |= EMAC_TXDESC_OWN;
+ if (i == map->dm_nsegs - 1) {
+ if (m0->m_pkthdr.len < ETHER_MIN_LEN) {
+ sc->sc_txq.t_queued++;
+ sc->sc_txq.t_cur = (sc->sc_txq.t_cur + 1)
+ % RKEMAC_TX_RING_COUNT;
+ td = &sc->sc_txq.t_data[sc->sc_txq.t_cur];
+ tx = &sc->sc_txq.t_desc[sc->sc_txq.t_cur];
+ tx->tx_ptr = htole32(sc->sc_pad_physaddr);
+ len = __SHIFTIN(ETHER_MIN_LEN -
+ m0->m_pkthdr.len , EMAC_TXDESC_TXLEN);
+ tx->tx_info = htole32(info | len);
+ }
+ tx->tx_info |= htole32(EMAC_TXDESC_LAST);
+ }
sc->sc_txq.t_queued++;
sc->sc_txq.t_cur =
@@ -815,7 +837,7 @@ rkemac_rxintr(struct rkemac_softc *sc)
goto skip;
}
- const u_int len = __SHIFTOUT(info, EMAC_RXDESC_LAST);
+ const u_int len = __SHIFTOUT(info, EMAC_RXDESC_RXLEN);
MGETHDR(mnew, M_DONTWAIT, MT_DATA);
if (mnew == NULL) {