Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 May 2011 19:26:12 +0000 (UTC)
From:      Pyun YongHyeon <yongari@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r222377 - stable/8/sys/dev/xl
Message-ID:  <201105271926.p4RJQCtA049317@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201105271926.p4RJQCtA049317>