Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/arm/rockchip add multicast filter support



details:   https://anonhg.NetBSD.org/src/rev/6c6b81ee36a6
branches:  trunk
changeset: 805542:6c6b81ee36a6
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Mon Jan 05 22:16:49 2015 +0000

description:
add multicast filter support

diffstat:

 sys/arch/arm/rockchip/rockchip_emac.c |  91 ++++++++++++++++++++++------------
 1 files changed, 58 insertions(+), 33 deletions(-)

diffs (157 lines):

diff -r 14164cce8a55 -r 6c6b81ee36a6 sys/arch/arm/rockchip/rockchip_emac.c
--- a/sys/arch/arm/rockchip/rockchip_emac.c     Mon Jan 05 21:57:49 2015 +0000
+++ b/sys/arch/arm/rockchip/rockchip_emac.c     Mon Jan 05 22:16:49 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rockchip_emac.c,v 1.3 2015/01/05 21:57:49 jmcneill Exp $ */
+/* $NetBSD: rockchip_emac.c,v 1.4 2015/01/05 22:16:49 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
 #include "opt_rkemac.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rockchip_emac.c,v 1.3 2015/01/05 21:57:49 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rockchip_emac.c,v 1.4 2015/01/05 22:16:49 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -144,6 +144,7 @@
 static void    rkemac_txdesc_sync(struct rkemac_softc *, int, int, int);
 static void    rkemac_txintr(struct rkemac_softc *);
 static void    rkemac_rxintr(struct rkemac_softc *);
+static void    rkemac_setmulti(struct rkemac_softc *);
 
 CFATTACH_DECL_NEW(rkemac, sizeof(struct rkemac_softc),
        rkemac_match, rkemac_attach, NULL, NULL);
@@ -502,8 +503,6 @@
 rkemac_init(struct ifnet *ifp)
 {
        struct rkemac_softc *sc = ifp->if_softc;
-       struct ether_multi *em;
-       struct ether_multistep ems;
        uint32_t control;
 
        if (ifp->if_flags & IFF_RUNNING)
@@ -511,6 +510,11 @@
 
        rkemac_stop(ifp, 0);
 
+       EMAC_WRITE(sc, EMAC_POLLRATE_REG, RKEMAC_POLLRATE);
+       EMAC_WRITE(sc, EMAC_RXRINGPTR_REG, sc->sc_rxq.r_physaddr);
+       EMAC_WRITE(sc, EMAC_TXRINGPTR_REG, sc->sc_txq.t_physaddr);
+
+       control &= ~EMAC_CONTROL_RXBDTLEN;
        control = EMAC_READ(sc, EMAC_CONTROL_REG);
        if (ifp->if_flags & IFF_PROMISC) {
                control |= EMAC_CONTROL_PROM;
@@ -522,24 +526,16 @@
        } else {
                control |= EMAC_CONTROL_DISBC;
        }
-       ETHER_FIRST_MULTI(ems, &sc->sc_ec, em);
-       if (em) {
-               ifp->if_flags |= IFF_ALLMULTI;
-               control |= EMAC_CONTROL_PROM;
-       } else {
-               ifp->if_flags &= ~IFF_ALLMULTI;
-       }
 
-       EMAC_WRITE(sc, EMAC_POLLRATE_REG, RKEMAC_POLLRATE);
-       EMAC_WRITE(sc, EMAC_RXRINGPTR_REG, sc->sc_rxq.r_physaddr);
-       EMAC_WRITE(sc, EMAC_TXRINGPTR_REG, sc->sc_txq.t_physaddr);
-
-       control &= ~EMAC_CONTROL_RXBDTLEN;
        control |= __SHIFTIN(RKEMAC_RX_RING_COUNT, EMAC_CONTROL_RXBDTLEN);
        control &= ~EMAC_CONTROL_TXBDTLEN;
        control |= __SHIFTIN(RKEMAC_TX_RING_COUNT, EMAC_CONTROL_TXBDTLEN);
        control |= EMAC_CONTROL_RXRN;
        control |= EMAC_CONTROL_TXRN;
+       EMAC_WRITE(sc, EMAC_CONTROL_REG, control);
+
+       rkemac_setmulti(sc);
+
        control |= EMAC_CONTROL_EN;
        EMAC_WRITE(sc, EMAC_CONTROL_REG, control);
 
@@ -630,30 +626,16 @@
 rkemac_ioctl(struct ifnet *ifp, u_long cmd, void *data)
 {
        struct rkemac_softc *sc = ifp->if_softc;
-       struct ether_multi *em;
-       struct ether_multistep ems;
-       uint32_t control;
        int s, error;
 
        s = splnet();
 
        if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
                error = 0;
-               if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI)
-                       ;
-               else if (ifp->if_flags & IFF_RUNNING) {
-                       control = EMAC_READ(sc, EMAC_CONTROL_REG);
-                       ETHER_FIRST_MULTI(ems, &sc->sc_ec, em);
-                       if (em) {
-                               ifp->if_flags |= IFF_ALLMULTI;
-                               control |= EMAC_CONTROL_PROM;
-                       } else {
-                               ifp->if_flags &= ~IFF_ALLMULTI;
-                               if ((ifp->if_flags & IFF_PROMISC) == 0) {
-                                       control &= ~EMAC_CONTROL_PROM;
-                               }
+               if (ifp->if_flags & IFF_RUNNING) {
+                       if (cmd == SIOCADDMULTI || cmd == SIOCDELMULTI) {
+                               rkemac_setmulti(sc);
                        }
-                       EMAC_WRITE(sc, EMAC_CONTROL_REG, control);
                }
        }
 
@@ -895,3 +877,46 @@
        sc->sc_rxq.r_cur = i;
 }
 
+static void
+rkemac_setmulti(struct rkemac_softc *sc)
+{
+       struct ifnet *ifp = &sc->sc_ec.ec_if;
+       struct ether_multi *enm;
+       struct ether_multistep step;
+       uint32_t hashes[2] = { 0, 0 };
+       uint32_t control, h;
+       int s;
+
+       s = splnet();
+
+       control = EMAC_READ(sc, EMAC_CONTROL_REG);
+
+       if (ifp->if_flags & IFF_PROMISC) {
+               control |= EMAC_CONTROL_PROM;
+               hashes[0] = hashes[1] = 0xffffffff;
+               goto done;
+       }
+
+       ifp->if_flags &= ~IFF_ALLMULTI;
+       control &= ~EMAC_CONTROL_PROM;
+
+       ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
+       while (enm != NULL) {
+               if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
+                       control |= EMAC_CONTROL_PROM;
+                       ifp->if_flags |= IFF_ALLMULTI;
+                       hashes[0] = hashes[1] = 0xffffffff;
+                       goto done;
+               }
+               h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
+               hashes[h >> 5] |= (1 << (h & 0x1f));
+               ETHER_NEXT_MULTI(step, enm);
+       }
+
+done:
+       EMAC_WRITE(sc, EMAC_CONTROL_REG, control);
+       EMAC_WRITE(sc, EMAC_LAFL_REG, hashes[0]);
+       EMAC_WRITE(sc, EMAC_LAFH_REG, hashes[1]);
+
+       splx(s);
+}



Home | Main Index | Thread Index | Old Index