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)

Reply via email to