Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/ic multicast hash filter support



details:   https://anonhg.NetBSD.org/src/rev/a6334129355c
branches:  trunk
changeset: 333161:a6334129355c
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Tue Oct 21 00:01:01 2014 +0000

description:
multicast hash filter support

diffstat:

 sys/dev/ic/dwc_gmac.c     |  84 +++++++++++++++++++++++++++++++++++++++++++---
 sys/dev/ic/dwc_gmac_reg.h |  16 ++++++--
 2 files changed, 88 insertions(+), 12 deletions(-)

diffs (167 lines):

diff -r 79dd5aa99a95 -r a6334129355c sys/dev/ic/dwc_gmac.c
--- a/sys/dev/ic/dwc_gmac.c     Mon Oct 20 23:49:14 2014 +0000
+++ b/sys/dev/ic/dwc_gmac.c     Tue Oct 21 00:01:01 2014 +0000
@@ -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_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 @@
        /*
         * 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 @@
 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 @@
                if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI)
                        ;
                else if (ifp->if_flags & IFF_RUNNING)
-                       /* setmulti */;
+                       dwc_gmac_setmulti(sc);
                break;
        }
 
@@ -1121,6 +1134,63 @@
 
 }
 
+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)
 {
diff -r 79dd5aa99a95 -r a6334129355c sys/dev/ic/dwc_gmac_reg.h
--- a/sys/dev/ic/dwc_gmac_reg.h Mon Oct 20 23:49:14 2014 +0000
+++ b/sys/dev/ic/dwc_gmac_reg.h Tue Oct 21 00:01:01 2014 +0000
@@ -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)



Home | Main Index | Thread Index | Old Index