Module Name:    src
Committed By:   jmcneill
Date:           Tue Oct 21 00:01:01 UTC 2014

Modified Files:
        src/sys/dev/ic: dwc_gmac.c dwc_gmac_reg.h

Log Message:
multicast hash filter support


To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/sys/dev/ic/dwc_gmac.c
cvs rdiff -u -r1.10 -r1.11 src/sys/dev/ic/dwc_gmac_reg.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/ic/dwc_gmac.c
diff -u src/sys/dev/ic/dwc_gmac.c:1.19 src/sys/dev/ic/dwc_gmac.c:1.20
--- src/sys/dev/ic/dwc_gmac.c:1.19	Mon Oct 20 23:41:46 2014
+++ src/sys/dev/ic/dwc_gmac.c	Tue Oct 21 00:01:01 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_gmac.c,v 1.19 2014/10/20 23:41:46 matt Exp $ */
+/* $NetBSD: dwc_gmac.c,v 1.20 2014/10/21 00:01:01 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2013, 2014 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.19 2014/10/20 23:41:46 matt Exp $");
+__KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.20 2014/10/21 00:01:01 jmcneill Exp $");
 
 /* #define	DWC_GMAC_DEBUG	1 */
 
@@ -90,6 +90,7 @@ static int dwc_gmac_queue(struct dwc_gma
 static int dwc_gmac_ioctl(struct ifnet *, u_long, void *);
 static void dwc_gmac_tx_intr(struct dwc_gmac_softc *sc);
 static void dwc_gmac_rx_intr(struct dwc_gmac_softc *sc);
+static void dwc_gmac_setmulti(struct dwc_gmac_softc *sc);
 
 #define	TX_DESC_OFFSET(N)	((AWGE_RX_RING_COUNT+(N)) \
 				    *sizeof(struct dwc_gmac_dev_dmadesc))
@@ -722,14 +723,25 @@ dwc_gmac_init(struct ifnet *ifp)
 	/*
 	 * Set up address filter
 	 */
-	ffilt = 0;
-	if (ifp->if_flags & IFF_PROMISC)
+	ffilt = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT);
+	if (ifp->if_flags & IFF_PROMISC) {
 		ffilt |= AWIN_GMAC_MAC_FFILT_PR;
-	else if (ifp->if_flags & IFF_ALLMULTI)
-		ffilt |= AWIN_GMAC_MAC_FFILT_PM;
+	} else {
+		ffilt &= ~AWIN_GMAC_MAC_FFILT_PR;
+	}
+	if (ifp->if_flags & IFF_BROADCAST) {
+		ffilt &= ~AWIN_GMAC_MAC_FFILT_DBF;
+	} else {
+		ffilt |= AWIN_GMAC_MAC_FFILT_DBF;
+	}
 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT, ffilt);
 
 	/*
+	 * Set up multicast filter
+	 */
+	dwc_gmac_setmulti(sc);
+
+	/*
 	 * Set up dma pointer for RX and TX ring
 	 */
 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_RX_ADDR,
@@ -888,6 +900,7 @@ dwc_gmac_queue(struct dwc_gmac_softc *sc
 static int
 dwc_gmac_ioctl(struct ifnet *ifp, u_long cmd, void *data)
 {
+	struct dwc_gmac_softc *sc = ifp->if_softc;
 	struct ifaddr *ifa = (struct ifaddr *)data;
 	int s, error = 0;
 
@@ -950,7 +963,7 @@ dwc_gmac_ioctl(struct ifnet *ifp, u_long
 		if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI)
 			;
 		else if (ifp->if_flags & IFF_RUNNING)
-			/* setmulti */;
+			dwc_gmac_setmulti(sc);
 		break;
 	}
 
@@ -1121,6 +1134,63 @@ skip:
 
 }
 
+static void
+dwc_gmac_setmulti(struct dwc_gmac_softc *sc)
+{
+	struct ifnet * const ifp = &sc->sc_ec.ec_if;
+	struct ether_multi *enm;
+	struct ether_multistep step;
+	uint32_t hashes[2] = { 0, 0 };
+	uint32_t ffilt;
+	int h, mcnt;
+
+	ffilt = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT);
+	
+	if (ifp->if_flags & IFF_PROMISC) {
+allmulti:
+		ifp->if_flags |= IFF_ALLMULTI;
+		ffilt |= AWIN_GMAC_MAC_FFILT_PM;
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT,
+		    ffilt);
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTLOW,
+		    0xffffffff);
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTHIGH,
+		    0xffffffff);
+		return;
+	}
+
+	ifp->if_flags &= ~IFF_ALLMULTI;
+	ffilt &= ~AWIN_GMAC_MAC_FFILT_PM;
+
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTLOW, 0);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTHIGH, 0);
+
+	ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
+	mcnt = 0;
+	while (enm != NULL) {
+		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
+		    ETHER_ADDR_LEN) != 0)
+			goto allmulti;
+
+		h = (~ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN)) >> 26;
+		hashes[h >> 5] |= (1 << (h & 0x1f));
+
+		mcnt++;
+		ETHER_NEXT_MULTI(step, enm);
+	}
+
+	if (mcnt)
+		ffilt |= AWIN_GMAC_MAC_FFILT_HMC;
+	else
+		ffilt &= ~AWIN_GMAC_MAC_FFILT_HMC;
+
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT, ffilt);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTLOW,
+	    hashes[0]);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTHIGH,
+	    hashes[1]);
+}
+
 int
 dwc_gmac_intr(struct dwc_gmac_softc *sc)
 {

Index: src/sys/dev/ic/dwc_gmac_reg.h
diff -u src/sys/dev/ic/dwc_gmac_reg.h:1.10 src/sys/dev/ic/dwc_gmac_reg.h:1.11
--- src/sys/dev/ic/dwc_gmac_reg.h:1.10	Mon Oct 20 20:10:05 2014
+++ src/sys/dev/ic/dwc_gmac_reg.h	Tue Oct 21 00:01:01 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_gmac_reg.h,v 1.10 2014/10/20 20:10:05 jmcneill Exp $ */
+/* $NetBSD: dwc_gmac_reg.h,v 1.11 2014/10/21 00:01:01 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2013, 2014 The NetBSD Foundation, Inc.
@@ -55,10 +55,16 @@
 #define	AWIN_GMAC_MAC_CONF_TXENABLE	__BIT(3)  /* enable TX dma engine */
 #define	AWIN_GMAC_MAC_CONF_RXENABLE	__BIT(2)  /* enable RX dma engine */
 
-#define	AWIN_GMAC_MAC_FFILT_PM		__BIT(4) /* promiscious multicast */
-#define	AWIN_GMAC_MAC_FFILT_HMC		__BIT(2) /* multicast hash compare */
-#define	AWIN_GMAC_MAC_FFILT_HUC		__BIT(1) /* unicast hash compare */
-#define	AWIN_GMAC_MAC_FFILT_PR		__BIT(0) /* promiscious mode */
+#define	AWIN_GMAC_MAC_FFILT_RA		__BIT(31) /* receive all mode */
+#define	AWIN_GMAC_MAC_FFILT_HPF		__BIT(10) /* hash or perfect filter */
+#define	AWIN_GMAC_MAC_FFILT_SAF		__BIT(9)  /* source address filter */
+#define	AWIN_GMAC_MAC_FFILT_SAIF	__BIT(8)  /* inverse filtering */
+#define	AWIN_GMAC_MAC_FFILT_DBF		__BIT(5)  /* disable broadcast frames */
+#define	AWIN_GMAC_MAC_FFILT_PM		__BIT(4)  /* promiscious multicast */
+#define	AWIN_GMAC_MAC_FFILT_DAIF	__BIT(3)  /* DA inverse filtering */
+#define	AWIN_GMAC_MAC_FFILT_HMC		__BIT(2)  /* multicast hash compare */
+#define	AWIN_GMAC_MAC_FFILT_HUC		__BIT(1)  /* unicast hash compare */
+#define	AWIN_GMAC_MAC_FFILT_PR		__BIT(0)  /* promiscious mode */
 
 #define	AWIN_GMAC_MAC_INT_LPI		__BIT(10)
 #define	AWIN_GMAC_MAC_INT_TSI		__BIT(9)

Reply via email to