From c8e6bc016002e0cef58574135a444363510697af Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Mon, 18 May 2009 15:21:32 +0000 Subject: Cleanup the ioctl and receive filter code for mec(4). This also significantly reduces the number of times the chip gets wacked at boot. From brad, tested by me. --- sys/arch/sgi/dev/if_mec.c | 92 +++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 55 deletions(-) diff --git a/sys/arch/sgi/dev/if_mec.c b/sys/arch/sgi/dev/if_mec.c index 450bf0f6c02..32fac73a653 100644 --- a/sys/arch/sgi/dev/if_mec.c +++ b/sys/arch/sgi/dev/if_mec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_mec.c,v 1.18 2008/11/28 02:44:17 brad Exp $ */ +/* $OpenBSD: if_mec.c,v 1.19 2009/05/18 15:21:31 jsing Exp $ */ /* $NetBSD: if_mec_mace.c,v 1.5 2004/08/01 06:36:36 tsutsui Exp $ */ /* @@ -340,7 +340,7 @@ void mec_watchdog(struct ifnet *); void mec_tick(void *); int mec_ioctl(struct ifnet *, u_long, caddr_t); void mec_reset(struct mec_softc *); -void mec_setfilter(struct mec_softc *); +void mec_iff(struct mec_softc *); int mec_intr(void *arg); void mec_stop(struct ifnet *); void mec_rxintr(struct mec_softc *, uint32_t); @@ -646,7 +646,7 @@ mec_init(struct ifnet *ifp) mec_reset(sc); /* Setup filter for multicast or promisc mode. */ - mec_setfilter(sc); + mec_iff(sc); /* Set the TX ring pointer to the base address. */ bus_space_write_8(st, sh, MEC_TX_RING_BASE, MEC_CDTXADDR(sc, 0)); @@ -1047,31 +1047,24 @@ mec_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; - - switch (ifa->ifa_addr->sa_family) { -#ifdef INET - case AF_INET: + if (!(ifp->if_flags & IFF_RUNNING)) mec_init(ifp); +#ifdef INET + if (ifa->ifa_addr->sa_family == AF_INET) arp_ifinit(&sc->sc_ac, ifa); - break; #endif - default: - mec_init(ifp); - break; - } break; case SIOCSIFFLAGS: - /* - * If interface is marked up and not running, then start it. - * If it is marked down and running, stop it. - * XXX If it's up then re-initialize it. This is so flags - * such as IFF_PROMISC are handled. - */ - if (ifp->if_flags & IFF_UP) - mec_init(ifp); - else if (ifp->if_flags & IFF_RUNNING) - mec_stop(ifp); + if (ifp->if_flags & IFF_UP) { + if (ifp->if_flags & IFF_RUNNING) + error = ENETRESET; + else + mec_init(ifp); + } else { + if (ifp->if_flags & IFF_RUNNING) + mec_stop(ifp); + } break; case SIOCSIFMEDIA: @@ -1085,7 +1078,7 @@ mec_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) if (error == ENETRESET) { if (ifp->if_flags & IFF_RUNNING) - mec_init(ifp); + mec_iff(sc); error = 0; } @@ -1118,54 +1111,43 @@ mec_tick(void *arg) } void -mec_setfilter(struct mec_softc *sc) +mec_iff(struct mec_softc *sc) { - struct arpcom *ec = &sc->sc_ac; + struct arpcom *ac = &sc->sc_ac; struct ifnet *ifp = &sc->sc_ac.ac_if; struct ether_multi *enm; struct ether_multistep step; bus_space_tag_t st = sc->sc_st; bus_space_handle_t sh = sc->sc_sh; - uint64_t mchash; + uint64_t mchash = 0; uint32_t control, hash; - int mcnt; + int mcnt = 0; control = bus_space_read_8(st, sh, MEC_MAC_CONTROL); control &= ~MEC_MAC_FILTER_MASK; + ifp->if_flags &= ~IFF_ALLMULTI; - if (ifp->if_flags & IFF_PROMISC) { - control |= MEC_MAC_FILTER_PROMISC; - bus_space_write_8(st, sh, MEC_MULTICAST, 0xffffffffffffffffULL); - bus_space_write_8(st, sh, MEC_MAC_CONTROL, control); - return; - } - - mcnt = 0; - mchash = 0; - ETHER_FIRST_MULTI(step, ec, enm); - while (enm != NULL) { - if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { - /* Set allmulti for a range of multicast addresses. */ + if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { + ifp->if_flags |= IFF_ALLMULTI; + if (ifp->if_flags & IFF_PROMISC) + control |= MEC_MAC_FILTER_PROMISC; + else control |= MEC_MAC_FILTER_ALLMULTI; - bus_space_write_8(st, sh, MEC_MULTICAST, - 0xffffffffffffffffULL); - bus_space_write_8(st, sh, MEC_MAC_CONTROL, control); - return; + mchash = 0xffffffffffffffffULL; + } else { + ETHER_FIRST_MULTI(step, ac, enm); + while (enm != NULL) { + hash = ether_crc32_be(enm->enm_addrlo, + ETHER_ADDR_LEN) >> 26; + mchash |= 1 << hash; + mcnt++; + ETHER_NEXT_MULTI(step, enm); } -#define mec_calchash(addr) (ether_crc32_be((addr), ETHER_ADDR_LEN) >> 26) - - hash = mec_calchash(enm->enm_addrlo); - mchash |= 1 << hash; - mcnt++; - ETHER_NEXT_MULTI(step, enm); + if (mcnt > 0) + control |= MEC_MAC_FILTER_MATCHMULTI; } - ifp->if_flags &= ~IFF_ALLMULTI; - - if (mcnt > 0) - control |= MEC_MAC_FILTER_MATCHMULTI; - bus_space_write_8(st, sh, MEC_MULTICAST, mchash); bus_space_write_8(st, sh, MEC_MAC_CONTROL, control); } -- cgit v1.2.3