Module Name: src
Committed By: jakllsch
Date: Tue Feb 1 23:40:13 UTC 2011
Modified Files:
src/sys/dev/marvell: if_mvgbe.c mvgbereg.h
Log Message:
Various improvements to mvgbe(4). Notable is improved multicast filtering.
To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/sys/dev/marvell/if_mvgbe.c
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/marvell/mvgbereg.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/marvell/if_mvgbe.c
diff -u src/sys/dev/marvell/if_mvgbe.c:1.4 src/sys/dev/marvell/if_mvgbe.c:1.5
--- src/sys/dev/marvell/if_mvgbe.c:1.4 Sat Jan 29 01:53:18 2011
+++ src/sys/dev/marvell/if_mvgbe.c Tue Feb 1 23:40:12 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: if_mvgbe.c,v 1.4 2011/01/29 01:53:18 jakllsch Exp $ */
+/* $NetBSD: if_mvgbe.c,v 1.5 2011/02/01 23:40:12 jakllsch Exp $ */
/*
* Copyright (c) 2007, 2008 KIYOHARA Takashi
* All rights reserved.
@@ -25,7 +25,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_mvgbe.c,v 1.4 2011/01/29 01:53:18 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_mvgbe.c,v 1.5 2011/02/01 23:40:12 jakllsch Exp $");
#include "rnd.h"
@@ -75,10 +75,10 @@
bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))
#define MVGBE_WRITE(sc, reg, val) \
bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
-#define MVGBE_READ_FILTER(sc, reg) \
- bus_space_read_4((sc)->sc_iot, (sc)->sc_dafh, (reg))
+#define MVGBE_READ_FILTER(sc, reg, val, c) \
+ bus_space_read_region_4((sc)->sc_iot, (sc)->sc_dafh, (reg), (val), (c))
#define MVGBE_WRITE_FILTER(sc, reg, val, c) \
- bus_space_set_region_4((sc)->sc_iot, (sc)->sc_dafh, (reg), (val), (c))
+ bus_space_write_region_4((sc)->sc_iot, (sc)->sc_dafh, (reg), (val), (c))
#define MVGBE_TX_RING_CNT 256
#define MVGBE_TX_RING_MSK (MVGBE_TX_RING_CNT - 1)
@@ -93,7 +93,7 @@
(MVGBE_RX_RING_CNT + 1) % MVGBE_RX_RING_CNT);
#define MVGBE_JSLOTS 384 /* XXXX */
-#define MVGBE_JLEN (MVGBE_MRU + MVGBE_BUF_ALIGN)
+#define MVGBE_JLEN ((MVGBE_MRU + MVGBE_RXBUF_ALIGN)&~MVGBE_RXBUF_MASK)
#define MVGBE_NTXSEG 30
#define MVGBE_JPAGESZ PAGE_SIZE
#define MVGBE_RESID \
@@ -249,9 +249,10 @@
static void mvgbe_stop(struct ifnet *, int);
static void mvgbe_watchdog(struct ifnet *);
-/* MII funcstions */
-static int mvgbe_ifmedia_upd(struct ifnet *);
-static void mvgbe_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+static int mvgbe_ifflags_cb(struct ethercom *);
+
+static int mvgbe_mediachange(struct ifnet *);
+static void mvgbe_mediastatus(struct ifnet *, struct ifmediareq *);
static int mvgbe_init_rx_ring(struct mvgbe_softc *);
static int mvgbe_init_tx_ring(struct mvgbe_softc *);
@@ -262,7 +263,8 @@
static int mvgbe_encap(struct mvgbe_softc *, struct mbuf *, uint32_t *);
static void mvgbe_rxeof(struct mvgbe_softc *);
static void mvgbe_txeof(struct mvgbe_softc *);
-static void mvgbe_setmulti(struct mvgbe_softc *);
+static uint8_t mvgbe_crc8(const uint8_t *, size_t);
+static void mvgbe_filter_setup(struct mvgbe_softc *);
#ifdef MVGBE_DEBUG
static void mvgbe_dump_txdesc(struct mvgbe_tx_desc *, int);
#endif
@@ -697,17 +699,12 @@
sc->sc_rdata = (struct mvgbe_ring_data *)kva;
memset(sc->sc_rdata, 0, sizeof(struct mvgbe_ring_data));
-#if 0
/*
* We can support 802.1Q VLAN-sized frames and jumbo
* Ethernet frames.
*/
sc->sc_ethercom.ec_capabilities |=
- ETHERCAP_VLAN_MTU | ETHERCAP_VLAN_HWTAGGING | ETHERCAP_JUMBO_MTU;
-#else
- /* XXXX: We don't know the usage of VLAN. */
- sc->sc_ethercom.ec_capabilities |= ETHERCAP_JUMBO_MTU;
-#endif
+ ETHERCAP_VLAN_MTU | ETHERCAP_JUMBO_MTU;
/* Try to allocate memory for jumbo buffers. */
if (mvgbe_alloc_jumbo_mem(sc)) {
@@ -730,6 +727,10 @@
IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx |
IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx |
IFCAP_CSUM_UDPv4_Tx | IFCAP_CSUM_UDPv4_Rx;
+ /*
+ * But, IPv6 packets in the stream can cause incorrect TCPv4 Tx sums.
+ */
+ sc->sc_ethercom.ec_if.if_capabilities &= ~IFCAP_CSUM_TCPv4_Tx;
IFQ_SET_MAXLEN(&ifp->if_snd, max(MVGBE_TX_RING_CNT - 1, IFQ_MAXLEN));
IFQ_SET_READY(&ifp->if_snd);
strcpy(ifp->if_xname, device_xname(sc->sc_dev));
@@ -746,7 +747,7 @@
sc->sc_ethercom.ec_mii = &sc->sc_mii;
ifmedia_init(&sc->sc_mii.mii_media, 0,
- mvgbe_ifmedia_upd, mvgbe_ifmedia_sts);
+ mvgbe_mediachange, mvgbe_mediastatus);
mii_attach(self, &sc->sc_mii, 0xffffffff,
MII_PHY_ANY, MII_OFFSET_ANY, 0);
if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
@@ -763,6 +764,7 @@
if_attach(ifp);
ether_ifattach(ifp, sc->sc_enaddr);
+ ether_set_ifflags_cb(&sc->sc_ethercom, mvgbe_ifflags_cb);
#if NRND > 0
rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dev),
@@ -898,42 +900,26 @@
}
static int
-mvgbe_ioctl(struct ifnet *ifp, u_long command, void *data)
+mvgbe_ioctl(struct ifnet *ifp, u_long cmd, void *data)
{
struct mvgbe_softc *sc = ifp->if_softc;
struct ifreq *ifr = data;
- struct mii_data *mii;
int s, error = 0;
s = splnet();
- switch (command) {
- case SIOCSIFFLAGS:
- DPRINTFN(2, ("mvgbe_ioctl IFFLAGS\n"));
- if (ifp->if_flags & IFF_UP)
- mvgbe_init(ifp);
- else
- if (ifp->if_flags & IFF_RUNNING)
- mvgbe_stop(ifp, 0);
- sc->sc_if_flags = ifp->if_flags;
- error = 0;
- break;
-
+ switch (cmd) {
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
DPRINTFN(2, ("mvgbe_ioctl MEDIA\n"));
- mii = &sc->sc_mii;
- error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
+ error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
break;
-
default:
DPRINTFN(2, ("mvgbe_ioctl ETHER\n"));
- error = ether_ioctl(ifp, command, data);
+ error = ether_ioctl(ifp, cmd, data);
if (error == ENETRESET) {
if (ifp->if_flags & IFF_RUNNING) {
- mvgbe_setmulti(sc);
- DPRINTFN(2,
- ("mvgbe_ioctl setmulti called\n"));
+ mvgbe_filter_setup(sc);
}
error = 0;
}
@@ -945,6 +931,9 @@
return error;
}
+int mvgbe_rximt = 0;
+int mvgbe_tximt = 0;
+
static int
mvgbe_init(struct ifnet *ifp)
{
@@ -952,17 +941,10 @@
struct mvgbec_softc *csc = device_private(device_parent(sc->sc_dev));
struct mii_data *mii = &sc->sc_mii;
uint32_t reg;
- int i, s;
+ int i;
DPRINTFN(2, ("mvgbe_init\n"));
- s = splnet();
-
- if (ifp->if_flags & IFF_RUNNING) {
- splx(s);
- return 0;
- }
-
/* Cancel pending I/O and free all RX/TX buffers. */
mvgbe_stop(ifp, 0);
@@ -974,13 +956,11 @@
if (mvgbe_init_tx_ring(sc) == ENOBUFS) {
aprint_error_ifnet(ifp,
"initialization failed: no memory for tx buffers\n");
- splx(s);
return ENOBUFS;
}
if (mvgbe_init_rx_ring(sc) == ENOBUFS) {
aprint_error_ifnet(ifp,
"initialization failed: no memory for rx buffers\n");
- splx(s);
return ENOBUFS;
}
@@ -988,7 +968,7 @@
MVGBE_PSC_ANFC | /* Enable Auto-Neg Flow Ctrl */
MVGBE_PSC_RESERVED | /* Must be set to 1 */
MVGBE_PSC_FLFAIL | /* Do NOT Force Link Fail */
- MVGBE_PSC_MRU(MVGBE_PSC_MRU_9700) | /* Always 9700 OK */
+ MVGBE_PSC_MRU(MVGBE_PSC_MRU_9022) | /* we want 9k */
MVGBE_PSC_SETFULLDX); /* Set_FullDx */
/* XXXX: mvgbe(4) always use RGMII. */
MVGBE_WRITE(sc, MVGBE_PSC1,
@@ -1026,7 +1006,11 @@
MVGBE_SDC_BLMR | /* Big/Little Endian Receive Mode: No swap */
MVGBE_SDC_BLMT | /* Big/Little Endian Transmit Mode: No swap */
#endif
+ MVGBE_SDC_IPGINTRX(mvgbe_rximt) |
MVGBE_SDC_TXBSZ_16_64BITWORDS);
+ MVGBE_WRITE(sc, MVGBE_PTFUT, MVGBE_PTFUT_IPGINTTX(mvgbe_tximt));
+
+ mvgbe_filter_setup(sc);
mii_mediachg(mii);
@@ -1056,8 +1040,6 @@
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
- splx(s);
-
return 0;
}
@@ -1178,30 +1160,41 @@
}
}
+static int
+mvgbe_ifflags_cb(struct ethercom *ec)
+{
+ struct ifnet *ifp = &ec->ec_if;
+ struct mvgbe_softc *sc = ifp->if_softc;
+ int change = ifp->if_flags ^ sc->sc_if_flags;
+
+ if (change != 0)
+ sc->sc_if_flags = ifp->if_flags;
+
+ if ((change & ~(IFF_CANTCHANGE|IFF_DEBUG)) != 0)
+ return ENETRESET;
+
+ if ((change & IFF_PROMISC) != 0)
+ mvgbe_filter_setup(sc);
+
+ return 0;
+}
/*
* Set media options.
*/
static int
-mvgbe_ifmedia_upd(struct ifnet *ifp)
+mvgbe_mediachange(struct ifnet *ifp)
{
- struct mvgbe_softc *sc = ifp->if_softc;
-
- mii_mediachg(&sc->sc_mii);
- return 0;
+ return ether_mediachange(ifp);
}
/*
* Report current media status.
*/
static void
-mvgbe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+mvgbe_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
{
- struct mvgbe_softc *sc = ifp->if_softc;
-
- mii_pollstat(&sc->sc_mii);
- ifmr->ifm_active = sc->sc_mii.mii_media_active;
- ifmr->ifm_status = sc->sc_mii.mii_media_status;
+ ether_mediastatus(ifp, ifmr);
}
@@ -1212,7 +1205,7 @@
struct mvgbe_ring_data *rd = sc->sc_rdata;
int i;
- bzero((char *)rd->mvgbe_rx_ring,
+ memset(rd->mvgbe_rx_ring, 0,
sizeof(struct mvgbe_rx_desc) * MVGBE_RX_RING_CNT);
for (i = 0; i < MVGBE_RX_RING_CNT; i++) {
@@ -1252,7 +1245,7 @@
struct mvgbe_ring_data *rd = sc->sc_rdata;
int i;
- bzero((char *)sc->sc_rdata->mvgbe_tx_ring,
+ memset(sc->sc_rdata->mvgbe_tx_ring, 0,
sizeof(struct mvgbe_tx_desc) * MVGBE_TX_RING_CNT);
for (i = 0; i < MVGBE_TX_RING_CNT; i++) {
@@ -1323,16 +1316,18 @@
m_new->m_len = m_new->m_pkthdr.len = MVGBE_JLEN;
m_new->m_data = m_new->m_ext.ext_buf;
}
- align = (u_long)m_new->m_data & MVGBE_BUF_MASK;
- if (align != 0)
- m_adj(m_new, MVGBE_BUF_ALIGN - align);
+ align = (u_long)m_new->m_data & MVGBE_RXBUF_MASK;
+ if (align != 0) {
+ DPRINTFN(1,("align = %d\n", align));
+ m_adj(m_new, MVGBE_RXBUF_ALIGN - align);
+ }
c = &sc->sc_cdata.mvgbe_rx_chain[i];
r = c->mvgbe_desc;
c->mvgbe_mbuf = m_new;
r->bufptr = dmamap->dm_segs[0].ds_addr +
(((vaddr_t)m_new->m_data - (vaddr_t)sc->sc_cdata.mvgbe_jumbo_buf));
- r->bufsize = MVGBE_JLEN & ~MVGBE_BUF_MASK;
+ r->bufsize = MVGBE_JLEN & ~MVGBE_RXBUF_MASK;
r->cmdsts = MVGBE_BUFFER_OWNED_BY_DMA | MVGBE_RX_ENABLE_INTERRUPT;
MVGBE_CDRXSYNC(sc, i, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -1388,7 +1383,7 @@
state = 4;
sc->sc_cdata.mvgbe_jumbo_buf = (void *)kva;
- DPRINTFN(1,("mvgbe_jumbo_buf = 0x%p\n", sc->sc_cdata.mvgbe_jumbo_buf));
+ DPRINTFN(1,("mvgbe_jumbo_buf = %p\n", sc->sc_cdata.mvgbe_jumbo_buf));
LIST_INIT(&sc->sc_jfree_listhead);
LIST_INIT(&sc->sc_jinuse_listhead);
@@ -1680,22 +1675,26 @@
continue;
}
- if (total_len > MVGBE_RX_CSUM_MIN_BYTE) {
- /* Check IP header checksum */
- if (rxstat & MVGBE_RX_IP_FRAME_TYPE) {
- m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
- if (!(rxstat & MVGBE_RX_IP_HEADER_OK))
- m->m_pkthdr.csum_flags |=
- M_CSUM_IPv4_BAD;
- }
- /* Check TCP/UDP checksum */
- if (rxstat & MVGBE_RX_L4_TYPE_TCP)
+ if (total_len <= MVGBE_RX_CSUM_MIN_BYTE) /* XXX documented? */
+ goto sw_csum;
+
+ if (rxstat & MVGBE_RX_IP_FRAME_TYPE) {
+ /* Check IPv4 header checksum */
+ m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
+ if (!(rxstat & MVGBE_RX_IP_HEADER_OK))
+ m->m_pkthdr.csum_flags |=
+ M_CSUM_IPv4_BAD;
+ /* Check TCPv4/UDPv4 checksum */
+ if ((rxstat & MVGBE_RX_L4_TYPE_MASK) ==
+ MVGBE_RX_L4_TYPE_TCP)
m->m_pkthdr.csum_flags |= M_CSUM_TCPv4;
- else if (rxstat & MVGBE_RX_L4_TYPE_UDP)
+ else if ((rxstat & MVGBE_RX_L4_TYPE_MASK) ==
+ MVGBE_RX_L4_TYPE_UDP)
m->m_pkthdr.csum_flags |= M_CSUM_UDPv4;
if (!(rxstat & MVGBE_RX_L4_CHECKSUM))
m->m_pkthdr.csum_flags |= M_CSUM_TCP_UDP_BAD;
}
+sw_csum:
/*
* Try to allocate a new jumbo buffer. If that
@@ -1803,49 +1802,99 @@
cdata->mvgbe_tx_cons = idx;
}
+static uint8_t
+mvgbe_crc8(const uint8_t *data, size_t size)
+{
+ int bit;
+ uint8_t byte;
+ uint8_t crc = 0;
+ const uint8_t poly = 0x07;
+
+ while(size--)
+ for (byte = *data++, bit = NBBY-1; bit >= 0; bit--)
+ crc = (crc << 1) ^ ((((crc >> 7) ^ (byte >> bit)) & 1) ? poly : 0);
+
+ return crc;
+}
+
+CTASSERT(MVGBE_NDFSMT == MVGBE_NDFOMT);
+
static void
-mvgbe_setmulti(struct mvgbe_softc *sc)
+mvgbe_filter_setup(struct mvgbe_softc *sc)
{
+ struct ethercom *ec = &sc->sc_ethercom;
struct ifnet *ifp= &sc->sc_ethercom.ec_if;
- uint32_t pxc, dfut, upm = 0, filter = 0;
- uint8_t ln = sc->sc_enaddr[5] & 0xf; /* last nibble */
+ struct ether_multi *enm;
+ struct ether_multistep step;
+ uint32_t *dfut, *dfsmt, *dfomt;
+ uint32_t pxc;
+ int i;
+ const uint8_t special[ETHER_ADDR_LEN] = {0x01,0x00,0x5e,0x00,0x00,0x00};
- if (ifp->if_flags & IFF_PROMISC) {
- upm = MVGBE_PXC_UPM;
- filter =
- MVGBE_DF(0, MVGBE_DF_QUEUE(0) | MVGBE_DF_PASS) |
- MVGBE_DF(1, MVGBE_DF_QUEUE(0) | MVGBE_DF_PASS) |
- MVGBE_DF(2, MVGBE_DF_QUEUE(0) | MVGBE_DF_PASS) |
- MVGBE_DF(3, MVGBE_DF_QUEUE(0) | MVGBE_DF_PASS);
- } else if (ifp->if_flags & IFF_ALLMULTI) {
- filter =
- MVGBE_DF(0, MVGBE_DF_QUEUE(0) | MVGBE_DF_PASS) |
- MVGBE_DF(1, MVGBE_DF_QUEUE(0) | MVGBE_DF_PASS) |
- MVGBE_DF(2, MVGBE_DF_QUEUE(0) | MVGBE_DF_PASS) |
- MVGBE_DF(3, MVGBE_DF_QUEUE(0) | MVGBE_DF_PASS);
+ dfut = kmem_zalloc(sizeof(*dfut) * MVGBE_NDFUT, KM_SLEEP);
+ dfsmt = kmem_zalloc(sizeof(*dfsmt) * MVGBE_NDFSMT, KM_SLEEP);
+ dfomt = kmem_zalloc(sizeof(*dfomt) * MVGBE_NDFOMT, KM_SLEEP);
+
+ if (ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC)) {
+ goto allmulti;
+ }
+
+ ETHER_FIRST_MULTI(step, ec, enm);
+ while (enm != NULL) {
+ if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
+ /* ranges are complex and somewhat rare */
+ goto allmulti;
+ }
+ /* chip handles some IPv4 multicast specially */
+ if (memcmp(enm->enm_addrlo, special, 5) == 0) {
+ i = enm->enm_addrlo[5];
+ dfsmt[i>>2] =
+ MVGBE_DF(i&3, MVGBE_DF_QUEUE(0) | MVGBE_DF_PASS);
+ } else {
+ i = mvgbe_crc8(enm->enm_addrlo, ETHER_ADDR_LEN);
+ dfomt[i>>2] =
+ MVGBE_DF(i&3, MVGBE_DF_QUEUE(0) | MVGBE_DF_PASS);
+ }
+
+ ETHER_NEXT_MULTI(step, enm);
+ }
+ goto set;
+
+allmulti:
+ if (ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC)) {
+ for (i = 0; i < MVGBE_NDFSMT; i++) {
+ dfsmt[i] = dfomt[i] =
+ MVGBE_DF(0, MVGBE_DF_QUEUE(0) | MVGBE_DF_PASS) |
+ MVGBE_DF(1, MVGBE_DF_QUEUE(0) | MVGBE_DF_PASS) |
+ MVGBE_DF(2, MVGBE_DF_QUEUE(0) | MVGBE_DF_PASS) |
+ MVGBE_DF(3, MVGBE_DF_QUEUE(0) | MVGBE_DF_PASS);
+ }
}
- /* Set Unicast Promiscuous mode */
+set:
pxc = MVGBE_READ(sc, MVGBE_PXC);
pxc &= ~MVGBE_PXC_UPM;
- pxc |= upm;
- MVGBE_WRITE(sc, MVGBE_PXC, pxc);
-
- /* Set Destination Address Filter Multicast Tables */
- MVGBE_WRITE_FILTER(sc, MVGBE_DFSMT, filter, MVGBE_NDFSMT);
- MVGBE_WRITE_FILTER(sc, MVGBE_DFOMT, filter, MVGBE_NDFOMT);
-
+ pxc |= MVGBE_PXC_RB | MVGBE_PXC_RBIP | MVGBE_PXC_RBARP;
+ if (ifp->if_flags & IFF_BROADCAST) {
+ pxc &= ~(MVGBE_PXC_RB | MVGBE_PXC_RBIP | MVGBE_PXC_RBARP);
+ }
if (ifp->if_flags & IFF_PROMISC) {
- /* necessary ? */
- MVGBE_WRITE_FILTER(sc, MVGBE_DFUT, filter, MVGBE_NDFUT);
- return;
+ pxc |= MVGBE_PXC_UPM;
}
+ MVGBE_WRITE(sc, MVGBE_PXC, pxc);
/* Set Destination Address Filter Unicast Table */
- dfut = MVGBE_READ_FILTER(sc, MVGBE_DFUT + (ln & 0x0c));
- dfut &= ~MVGBE_DF(ln & 0x03, MVGBE_DF_QUEUE_MASK);;
- dfut |= MVGBE_DF(ln & 0x03, MVGBE_DF_QUEUE(0) | MVGBE_DF_PASS);
- MVGBE_WRITE_FILTER(sc, MVGBE_DFUT + (ln & 0x0c), dfut, 1);
+ i = sc->sc_enaddr[5] & 0xf; /* last nibble */
+ dfut[i>>2] = MVGBE_DF(i&3, MVGBE_DF_QUEUE(0) | MVGBE_DF_PASS);
+ MVGBE_WRITE_FILTER(sc, MVGBE_DFUT, dfut, MVGBE_NDFUT);
+
+ /* Set Destination Address Filter Multicast Tables */
+ MVGBE_WRITE_FILTER(sc, MVGBE_DFSMT, dfsmt, MVGBE_NDFSMT);
+ MVGBE_WRITE_FILTER(sc, MVGBE_DFOMT, dfomt, MVGBE_NDFOMT);
+
+ kmem_free(dfut, sizeof(dfut[0]) * MVGBE_NDFUT);
+ kmem_free(dfsmt, sizeof(dfsmt[0]) * MVGBE_NDFSMT);
+ kmem_free(dfomt, sizeof(dfsmt[0]) * MVGBE_NDFOMT);
}
#ifdef MVGBE_DEBUG
@@ -1870,7 +1919,5 @@
DESC_PRINT(desc->nextdescptr);
#endif
#undef DESC_PRINT
- printf("txdesc[%d].desc->returninfo=%#lx\n", idx, desc->returninfo);
- printf("txdesc[%d].desc->alignbufptr=%p\n", idx, desc->alignbufptr);
}
#endif
Index: src/sys/dev/marvell/mvgbereg.h
diff -u src/sys/dev/marvell/mvgbereg.h:1.2 src/sys/dev/marvell/mvgbereg.h:1.3
--- src/sys/dev/marvell/mvgbereg.h:1.2 Sat Oct 2 05:57:42 2010
+++ src/sys/dev/marvell/mvgbereg.h Tue Feb 1 23:40:12 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: mvgbereg.h,v 1.2 2010/10/02 05:57:42 kiyohara Exp $ */
+/* $NetBSD: mvgbereg.h,v 1.3 2011/02/01 23:40:12 jakllsch Exp $ */
/*
* Copyright (c) 2007 KIYOHARA Takashi
* All rights reserved.
@@ -236,8 +236,8 @@
#define MVGBE_SDC_BLMR (1 << 4)
#define MVGBE_SDC_BLMT (1 << 5)
#define MVGBE_SDC_SWAPMODE (1 << 6)
-#define MVGBE_SDC_IPGINTRX(n) ((n) << 8)
-#define MVGBE_SDC_IPGINTRX_MASK MVGBE_SDC_IPGINTRX(0x3fff)
+#define MVGBE_SDC_IPGINTRX_MASK __BITS(21, 8)
+#define MVGBE_SDC_IPGINTRX(x) __SHIFTIN(x, MVGBE_SDC_IPGINTRX_MASK)
#define MVGBE_SDC_TXBSZ(x) ((x) << 22)
#define MVGBE_SDC_TXBSZ_MASK MVGBE_SDC_TXBSZ(7)
#define MVGBE_SDC_TXBSZ_1_64BITWORDS MVGBE_SDC_TXBSZ(0)
@@ -310,6 +310,10 @@
#define MVGBE_ICE_INTADDRERR (1 << 23)
#define MVGBE_ICE_ETHERINTSUM (1 << 31)
+/* Port Tx FIFO Urgent Threshold (MVGBE_PTFUT) */
+#define MVGBE_PTFUT_IPGINTTX_MASK __BITS(17, 4)
+#define MVGBE_PTFUT_IPGINTTX(x) __SHIFTIN(x, MVGBE_PTFUT_IPGINTTX_MASK)
+
/* Port Rx Minimal Frame Size (MVGBE_PMFS) */
#define MVGBE_PMFS_RXMFS(rxmfs) (((rxmfs) - 40) & 0x7c)
/* RxMFS = 40,44,48,52,56,60,64 bytes */
@@ -331,16 +335,22 @@
#define MVGBE_DF_QUEUE_MASK ((7) << 1)
-#define MVGBE_MRU 9700 /* The Maximal Receive Packet Size */
+/*
+ * Set the chip's packet size limit to 9022.
+ * (ETHER_MAX_LEN_JUMBO + ETHER_VLAN_ENCAP_LEN)
+ */
+#define MVGBE_MRU 9022
-#define MVGBE_BUF_ALIGN 8
-#define MVGBE_BUF_MASK (MVGBE_BUF_ALIGN - 1)
+#define MVGBE_RXBUF_ALIGN 8
+#define MVGBE_RXBUF_MASK (MVGBE_RXBUF_ALIGN - 1)
#define MVGBE_HWHEADER_SIZE 2
/*
* DMA descriptors
- * It is 32byte alignment.
+ * Despite the documentation saying these descriptors only need to be
+ * aligned to 16-byte bondaries, 32-byte alignment seems to be required
+ * by the hardware. We'll just pad them out to that to make it easier.
*/
struct mvgbe_tx_desc {
#if BYTE_ORDER == BIG_ENDIAN
@@ -356,10 +366,7 @@
uint32_t bufptr; /* Descriptor buffer pointer */
uint32_t nextdescptr; /* Next descriptor pointer */
#endif
- u_long returninfo; /* User resource return information */
- uint8_t *alignbufptr; /* Pointer to 8 byte aligned buffer */
-
- uint32_t padding[2]; /* XXXX: required */
+ uint32_t _padding[4];
} __packed;
struct mvgbe_rx_desc {
@@ -376,9 +383,7 @@
uint32_t bufptr; /* Descriptor buffer pointer */
uint32_t nextdescptr; /* Next descriptor pointer */
#endif
- u_long returninfo; /* User resource return information */
-
- uint32_t padding[3]; /* XXXX: required */
+ uint32_t _padding[4];
} __packed;
#define MVGBE_ERROR_SUMMARY (1 << 0)