From owner-svn-src-stable@FreeBSD.ORG Fri May 27 19:26:12 2011 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C34B11065697; Fri, 27 May 2011 19:26:12 +0000 (UTC) (envelope-from yongari@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id A861F8FC08; Fri, 27 May 2011 19:26:12 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p4RJQC3t049319; Fri, 27 May 2011 19:26:12 GMT (envelope-from yongari@svn.freebsd.org) Received: (from yongari@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p4RJQCtA049317; Fri, 27 May 2011 19:26:12 GMT (envelope-from yongari@svn.freebsd.org) Message-Id: <201105271926.p4RJQCtA049317@svn.freebsd.org> From: Pyun YongHyeon Date: Fri, 27 May 2011 19:26:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r222377 - stable/8/sys/dev/xl X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 27 May 2011 19:26:13 -0000 Author: yongari Date: Fri May 27 19:26:12 2011 New Revision: 222377 URL: http://svn.freebsd.org/changeset/base/222377 Log: MFC r221555: Rewrite RX filter logic and provide controller specific filter handler for 3C90x and 3C90xB/C respectively. This simplifies ioctl handler as well as enhancing readability. While I'm here don't reprogram multicast filter when driver is not running. Modified: stable/8/sys/dev/xl/if_xl.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) Modified: stable/8/sys/dev/xl/if_xl.c ============================================================================== --- stable/8/sys/dev/xl/if_xl.c Fri May 27 19:06:03 2011 (r222376) +++ stable/8/sys/dev/xl/if_xl.c Fri May 27 19:26:12 2011 (r222377) @@ -263,10 +263,11 @@ static void xl_mii_send(struct xl_softc static int xl_mii_readreg(struct xl_softc *, struct xl_mii_frame *); static int xl_mii_writereg(struct xl_softc *, struct xl_mii_frame *); +static void xl_rxfilter(struct xl_softc *); +static void xl_rxfilter_90x(struct xl_softc *); +static void xl_rxfilter_90xB(struct xl_softc *); static void xl_setcfg(struct xl_softc *); static void xl_setmode(struct xl_softc *, int); -static void xl_setmulti(struct xl_softc *); -static void xl_setmulti_hash(struct xl_softc *); static void xl_reset(struct xl_softc *); static int xl_list_rx_init(struct xl_softc *); static int xl_list_tx_init(struct xl_softc *); @@ -701,101 +702,133 @@ xl_read_eeprom(struct xl_softc *sc, cadd return (err ? 1 : 0); } +static void +xl_rxfilter(struct xl_softc *sc) +{ + + if (sc->xl_type == XL_TYPE_905B) + xl_rxfilter_90xB(sc); + else + xl_rxfilter_90x(sc); +} + /* * NICs older than the 3c905B have only one multicast option, which * is to enable reception of all multicast frames. */ static void -xl_setmulti(struct xl_softc *sc) +xl_rxfilter_90x(struct xl_softc *sc) { - struct ifnet *ifp = sc->xl_ifp; + struct ifnet *ifp; struct ifmultiaddr *ifma; u_int8_t rxfilt; - int mcnt = 0; XL_LOCK_ASSERT(sc); + ifp = sc->xl_ifp; + XL_SEL_WIN(5); rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); + rxfilt &= ~(XL_RXFILTER_ALLFRAMES | XL_RXFILTER_ALLMULTI | + XL_RXFILTER_BROADCAST | XL_RXFILTER_INDIVIDUAL); - if (ifp->if_flags & IFF_ALLMULTI) { - rxfilt |= XL_RXFILTER_ALLMULTI; - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); - return; - } - - if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) - mcnt++; - if_maddr_runlock(ifp); + /* Set the individual bit to receive frames for this host only. */ + rxfilt |= XL_RXFILTER_INDIVIDUAL; + /* Set capture broadcast bit to capture broadcast frames. */ + if (ifp->if_flags & IFF_BROADCAST) + rxfilt |= XL_RXFILTER_BROADCAST; - if (mcnt) - rxfilt |= XL_RXFILTER_ALLMULTI; - else - rxfilt &= ~XL_RXFILTER_ALLMULTI; + /* If we want promiscuous mode, set the allframes bit. */ + if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) { + if (ifp->if_flags & IFF_PROMISC) + rxfilt |= XL_RXFILTER_ALLFRAMES; + if (ifp->if_flags & IFF_ALLMULTI) + rxfilt |= XL_RXFILTER_ALLMULTI; + } else { + if_maddr_rlock(ifp); + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + rxfilt |= XL_RXFILTER_ALLMULTI; + break; + } + if_maddr_runlock(ifp); + } - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); + CSR_WRITE_2(sc, XL_COMMAND, rxfilt | XL_CMD_RX_SET_FILT); + XL_SEL_WIN(7); } /* * 3c905B adapters have a hash filter that we can program. */ static void -xl_setmulti_hash(struct xl_softc *sc) +xl_rxfilter_90xB(struct xl_softc *sc) { - struct ifnet *ifp = sc->xl_ifp; - int h = 0, i; + struct ifnet *ifp; struct ifmultiaddr *ifma; + int i, mcnt; + u_int16_t h; u_int8_t rxfilt; - int mcnt = 0; XL_LOCK_ASSERT(sc); + ifp = sc->xl_ifp; + XL_SEL_WIN(5); rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); + rxfilt &= ~(XL_RXFILTER_ALLFRAMES | XL_RXFILTER_ALLMULTI | + XL_RXFILTER_BROADCAST | XL_RXFILTER_INDIVIDUAL | + XL_RXFILTER_MULTIHASH); - if (ifp->if_flags & IFF_ALLMULTI) { - rxfilt |= XL_RXFILTER_ALLMULTI; - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); - return; - } else - rxfilt &= ~XL_RXFILTER_ALLMULTI; + /* Set the individual bit to receive frames for this host only. */ + rxfilt |= XL_RXFILTER_INDIVIDUAL; + /* Set capture broadcast bit to capture broadcast frames. */ + if (ifp->if_flags & IFF_BROADCAST) + rxfilt |= XL_RXFILTER_BROADCAST; - /* first, zot all the existing hash bits */ - for (i = 0; i < XL_HASHFILT_SIZE; i++) - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH|i); - - /* now program new ones */ - if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - /* - * Note: the 3c905B currently only supports a 64-bit hash - * table, which means we really only need 6 bits, but the - * manual indicates that future chip revisions will have a - * 256-bit hash table, hence the routine is set up to - * calculate 8 bits of position info in case we need it some - * day. - * Note II, The Sequel: _CURRENT_ versions of the 3c905B have - * a 256 bit hash table. This means we have to use all 8 bits - * regardless. On older cards, the upper 2 bits will be - * ignored. Grrrr.... - */ - h = ether_crc32_be(LLADDR((struct sockaddr_dl *) - ifma->ifma_addr), ETHER_ADDR_LEN) & 0xFF; - CSR_WRITE_2(sc, XL_COMMAND, - h | XL_CMD_RX_SET_HASH | XL_HASH_SET); - mcnt++; + /* If we want promiscuous mode, set the allframes bit. */ + if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) { + if (ifp->if_flags & IFF_PROMISC) + rxfilt |= XL_RXFILTER_ALLFRAMES; + if (ifp->if_flags & IFF_ALLMULTI) + rxfilt |= XL_RXFILTER_ALLMULTI; + } else { + /* First, zot all the existing hash bits. */ + for (i = 0; i < XL_HASHFILT_SIZE; i++) + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH | i); + + /* Now program new ones. */ + mcnt = 0; + if_maddr_rlock(ifp); + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + /* + * Note: the 3c905B currently only supports a 64-bit + * hash table, which means we really only need 6 bits, + * but the manual indicates that future chip revisions + * will have a 256-bit hash table, hence the routine + * is set up to calculate 8 bits of position info in + * case we need it some day. + * Note II, The Sequel: _CURRENT_ versions of the + * 3c905B have a 256 bit hash table. This means we have + * to use all 8 bits regardless. On older cards, the + * upper 2 bits will be ignored. Grrrr.... + */ + h = ether_crc32_be(LLADDR((struct sockaddr_dl *) + ifma->ifma_addr), ETHER_ADDR_LEN) & 0xFF; + CSR_WRITE_2(sc, XL_COMMAND, + h | XL_CMD_RX_SET_HASH | XL_HASH_SET); + mcnt++; + } + if_maddr_runlock(ifp); + if (mcnt > 0) + rxfilt |= XL_RXFILTER_MULTIHASH; } - if_maddr_runlock(ifp); - - if (mcnt) - rxfilt |= XL_RXFILTER_MULTIHASH; - else - rxfilt &= ~XL_RXFILTER_MULTIHASH; CSR_WRITE_2(sc, XL_COMMAND, rxfilt | XL_CMD_RX_SET_FILT); + XL_SEL_WIN(7); } static void @@ -2763,7 +2796,6 @@ xl_init_locked(struct xl_softc *sc) { struct ifnet *ifp = sc->xl_ifp; int error, i; - u_int16_t rxfilt = 0; struct mii_data *mii = NULL; XL_LOCK_ASSERT(sc); @@ -2862,39 +2894,7 @@ xl_init_locked(struct xl_softc *sc) } /* Set RX filter bits. */ - XL_SEL_WIN(5); - rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); - - /* Set the individual bit to receive frames for this host only. */ - rxfilt |= XL_RXFILTER_INDIVIDUAL; - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) { - rxfilt |= XL_RXFILTER_ALLFRAMES; - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); - } else { - rxfilt &= ~XL_RXFILTER_ALLFRAMES; - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); - } - - /* - * Set capture broadcast bit to capture broadcast frames. - */ - if (ifp->if_flags & IFF_BROADCAST) { - rxfilt |= XL_RXFILTER_BROADCAST; - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); - } else { - rxfilt &= ~XL_RXFILTER_BROADCAST; - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); - } - - /* - * Program the multicast filter, if necessary. - */ - if (sc->xl_type == XL_TYPE_905B) - xl_setmulti_hash(sc); - else - xl_setmulti(sc); + xl_rxfilter(sc); /* * Load the address of the RX list. We have to @@ -3123,30 +3123,16 @@ xl_ioctl(struct ifnet *ifp, u_long comma struct ifreq *ifr = (struct ifreq *) data; int error = 0, mask; struct mii_data *mii = NULL; - u_int8_t rxfilt; switch (command) { case SIOCSIFFLAGS: XL_LOCK(sc); - - XL_SEL_WIN(5); - rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); if (ifp->if_flags & IFF_UP) { if (ifp->if_drv_flags & IFF_DRV_RUNNING && - ifp->if_flags & IFF_PROMISC && - !(sc->xl_if_flags & IFF_PROMISC)) { - rxfilt |= XL_RXFILTER_ALLFRAMES; - CSR_WRITE_2(sc, XL_COMMAND, - XL_CMD_RX_SET_FILT|rxfilt); - XL_SEL_WIN(7); - } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && - !(ifp->if_flags & IFF_PROMISC) && - sc->xl_if_flags & IFF_PROMISC) { - rxfilt &= ~XL_RXFILTER_ALLFRAMES; - CSR_WRITE_2(sc, XL_COMMAND, - XL_CMD_RX_SET_FILT|rxfilt); - XL_SEL_WIN(7); - } else + (ifp->if_flags ^ sc->xl_if_flags) & + (IFF_PROMISC | IFF_ALLMULTI)) + xl_rxfilter(sc); + else xl_init_locked(sc); } else { if (ifp->if_drv_flags & IFF_DRV_RUNNING) @@ -3154,18 +3140,14 @@ xl_ioctl(struct ifnet *ifp, u_long comma } sc->xl_if_flags = ifp->if_flags; XL_UNLOCK(sc); - error = 0; break; case SIOCADDMULTI: case SIOCDELMULTI: /* XXX Downcall from if_addmulti() possibly with locks held. */ XL_LOCK(sc); - if (sc->xl_type == XL_TYPE_905B) - xl_setmulti_hash(sc); - else - xl_setmulti(sc); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + xl_rxfilter(sc); XL_UNLOCK(sc); - error = 0; break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: