diff options
author | 2013-01-29 11:06:38 +0000 | |
---|---|---|
committer | 2013-01-29 11:06:38 +0000 | |
commit | d9e90947122e8e38065fdd4772fa2035c0d85b7b (patch) | |
tree | f5107f6e456c91d90ebcbf7f37dee50b35ea581b /sys/dev/usb/if_url.c | |
parent | - Set ENETRESET within myx_ioctl() instead of calling myx_iff() directly, to be (diff) | |
download | wireguard-openbsd-d9e90947122e8e38065fdd4772fa2035c0d85b7b.tar.xz wireguard-openbsd-d9e90947122e8e38065fdd4772fa2035c0d85b7b.zip |
Rewrite the receive filter handling code and cleanup the ioctl bits.
ok sthen@
Diffstat (limited to 'sys/dev/usb/if_url.c')
-rw-r--r-- | sys/dev/usb/if_url.c | 129 |
1 files changed, 49 insertions, 80 deletions
diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index 3a21c8b7aa5..3aec42fc4d6 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_url.c,v 1.63 2011/07/03 15:47:17 matthew Exp $ */ +/* $OpenBSD: if_url.c,v 1.64 2013/01/29 11:06:38 brad Exp $ */ /* $NetBSD: if_url.c,v 1.6 2002/09/29 10:19:21 martin Exp $ */ /* * Copyright (c) 2001, 2002 @@ -123,7 +123,7 @@ int url_int_miibus_readreg(struct device *, int, int); void url_int_miibus_writereg(struct device *, int, int, int); void url_miibus_statchg(struct device *); int url_init(struct ifnet *); -void url_setmulti(struct url_softc *); +void url_iff(struct url_softc *); void url_reset(struct url_softc *); int url_csr_read_1(struct url_softc *, int); @@ -505,18 +505,7 @@ url_init(struct ifnet *ifp) URL_TCR_NOCRC); /* Init receive control register */ - URL_SETBIT2(sc, URL_RCR, URL_RCR_TAIL | URL_RCR_AD); - if (ifp->if_flags & IFF_BROADCAST) - URL_SETBIT2(sc, URL_RCR, URL_RCR_AB); - else - URL_CLRBIT2(sc, URL_RCR, URL_RCR_AB); - - /* If we want promiscuous mode, accept all physical frames. */ - if (ifp->if_flags & IFF_PROMISC) - URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); - else - URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); - + URL_SETBIT2(sc, URL_RCR, URL_RCR_TAIL); /* Initialize transmit ring */ if (url_tx_list_init(sc) == ENOBUFS) { @@ -532,8 +521,8 @@ url_init(struct ifnet *ifp) return (EIO); } - /* Load the multicast filter */ - url_setmulti(sc); + /* Program promiscuous mode and multicast filters */ + url_iff(sc); /* Enable RX and TX */ URL_SETBIT(sc, URL_CR, URL_CR_TE | URL_CR_RE); @@ -595,68 +584,60 @@ url_activate(struct device *self, int act) return (0); } -#define url_calchash(addr) (ether_crc32_be((addr), ETHER_ADDR_LEN) >> 26) - - void -url_setmulti(struct url_softc *sc) +url_iff(struct url_softc *sc) { - struct ifnet *ifp; + struct ifnet *ifp = GET_IFP(sc); + struct arpcom *ac = &sc->sc_ac; struct ether_multi *enm; struct ether_multistep step; - u_int32_t hashes[2] = { 0, 0 }; + u_int32_t hashes[2]; + u_int16_t rcr; int h = 0; - int mcnt = 0; DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); if (usbd_is_dying(sc->sc_udev)) return; - ifp = GET_IFP(sc); + rcr = url_csr_read_2(sc, URL_RCR); + rcr &= ~(URL_RCR_AAM | URL_RCR_AAP | URL_RCR_AB | URL_RCR_AD | + URL_RCR_AM); + bzero(hashes, sizeof(hashes)); + ifp->if_flags &= ~IFF_ALLMULTI; - if (ifp->if_flags & IFF_PROMISC) { - URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); - return; - } else if (ifp->if_flags & IFF_ALLMULTI) { - allmulti: - ifp->if_flags |= IFF_ALLMULTI; - URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM); - URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAP); - return; - } + /* + * Always accept broadcast frames. + * Always accept frames destined to our station address. + */ + rcr |= URL_RCR_AB | URL_RCR_AD; - /* first, zot all the existing hash bits */ - url_csr_write_4(sc, URL_MAR0, 0); - url_csr_write_4(sc, URL_MAR4, 0); - - /* now program new ones */ - ETHER_FIRST_MULTI(step, &sc->sc_ac, enm); - while (enm != NULL) { - if (memcmp(enm->enm_addrlo, enm->enm_addrhi, - ETHER_ADDR_LEN) != 0) - goto allmulti; - - h = url_calchash(enm->enm_addrlo); - if (h < 32) - hashes[0] |= (1 << h); - else - hashes[1] |= (1 << (h -32)); - mcnt++; - ETHER_NEXT_MULTI(step, enm); - } + if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { + ifp->if_flags |= IFF_ALLMULTI; + rcr |= URL_RCR_AAM; + if (ifp->if_flags & IFF_PROMISC) + rcr |= URL_RCR_AAP; + } else { + rcr |= URL_RCR_AM; - ifp->if_flags &= ~IFF_ALLMULTI; + /* now program new ones */ + ETHER_FIRST_MULTI(step, ac, enm); + while (enm != NULL) { + h = ether_crc32_be(enm->enm_addrlo, + ETHER_ADDR_LEN) >> 26; - URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); + if (h < 32) + hashes[0] |= (1 << h); + else + hashes[1] |= (1 << (h - 32)); - if (mcnt){ - URL_SETBIT2(sc, URL_RCR, URL_RCR_AM); - } else { - URL_CLRBIT2(sc, URL_RCR, URL_RCR_AM); + ETHER_NEXT_MULTI(step, enm); + } } + url_csr_write_4(sc, URL_MAR0, hashes[0]); url_csr_write_4(sc, URL_MAR4, hashes[1]); + url_csr_write_2(sc, URL_RCR, rcr); } int @@ -1059,7 +1040,6 @@ url_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct url_softc *sc = ifp->if_softc; struct ifaddr *ifa = (struct ifaddr *)data; struct ifreq *ifr = (struct ifreq *)data; - struct mii_data *mii; int s, error = 0; DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); @@ -1072,40 +1052,29 @@ url_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; - url_init(ifp); - - switch (ifa->ifa_addr->sa_family) { + if (!(ifp->if_flags & IFF_RUNNING)) + url_init(ifp); #ifdef INET - case AF_INET: + if (ifa->ifa_addr->sa_family == AF_INET) arp_ifinit(&sc->sc_ac, ifa); - break; -#endif /* INET */ - } +#endif break; case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { - if (ifp->if_flags & IFF_RUNNING && - ifp->if_flags & IFF_PROMISC) { - URL_SETBIT2(sc, URL_RCR, - URL_RCR_AAM|URL_RCR_AAP); - } else if (ifp->if_flags & IFF_RUNNING && - !(ifp->if_flags & IFF_PROMISC)) { - URL_CLRBIT2(sc, URL_RCR, - URL_RCR_AAM|URL_RCR_AAP); - } else if (!(ifp->if_flags & IFF_RUNNING)) + if (ifp->if_flags & IFF_RUNNING) + error = ENETRESET; + else url_init(ifp); } else { if (ifp->if_flags & IFF_RUNNING) url_stop(ifp, 1); } - error = 0; break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: - mii = GET_MII(sc); - error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); + error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd); break; default: @@ -1114,7 +1083,7 @@ url_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) if (error == ENETRESET) { if (ifp->if_flags & IFF_RUNNING) - url_setmulti(sc); + url_iff(sc); error = 0; } |