From nobody@FreeBSD.org  Wed Sep 29 16:58:26 2010
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id A384710656F7
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 29 Sep 2010 16:58:26 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 7755F8FC15
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 29 Sep 2010 16:58:26 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id o8TGwQYv099202
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 29 Sep 2010 16:58:26 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id o8TGwQDT099201;
	Wed, 29 Sep 2010 16:58:26 GMT
	(envelope-from nobody)
Message-Id: <201009291658.o8TGwQDT099201@www.freebsd.org>
Date: Wed, 29 Sep 2010 16:58:26 GMT
From: Larry Baird <lab@gta.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: Bridging with rl(4) broken in FreeBSD 8 stable
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         151079
>Category:       kern
>Synopsis:       Bridging with rl(4) broken in FreeBSD 8 stable
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    yongari
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Sep 29 17:00:10 UTC 2010
>Closed-Date:    Fri Oct 08 18:37:58 UTC 2010
>Last-Modified:  Fri Oct 08 18:37:58 UTC 2010
>Originator:     Larry Baird
>Release:        8.1-STABLE FreeBSD 8.1-STABLE
>Organization:
GTA, Inc.
>Environment:
FreeBSD draco.gta.com 8.1-STABLE FreeBSD 8.1-STABLE #0: Mon Sep 27 07:23:05 EDT 2010     root@draco.gta.com:/usr/src/sys/i386/compile/DRACO  i386

>Description:
Revision 213130 breaks bridging with rl(4) driver.
>How-To-Repeat:

>Fix:
Revert to previous version of sys/pci/if_rl.c

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->yongari 
Responsible-Changed-By: yongari 
Responsible-Changed-When: Wed Sep 29 18:20:02 UTC 2010 
Responsible-Changed-Why:  
Grab. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=151079 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/151079: commit references a PR
Date: Thu, 30 Sep 2010 17:37:13 +0000 (UTC)

 Author: yongari
 Date: Thu Sep 30 17:37:08 2010
 New Revision: 213306
 URL: http://svn.freebsd.org/changeset/base/213306
 
 Log:
   Rename rl_setmulti() to rl_rxfilter() as rl_rxfilter() will handle
   IFF_ALLMULTI/IFF_PROMISC as well as multicast filter configuration.
   Rewrite RX filter logic to reduce number of register accesses and
   make it handle promiscuous/allmulti toggling without controller
   reinitialization.
   
   Previously rl(4) counted on controller reinitialization to reprogram
   promiscuous configuration but r211767 resulted in avoiding
   controller reinitialization whenever promiscuous mode is toggled.
   To address this, keep track of driver's view of interface state and
   handle IFF_ALLMULTI/IFF_PROMISC changes without reinitializing
   controller. This should fix a regression introduced in r211267.
   
   While I'm here remove unnecessary variable reassignment in ioctl
   handler.
   
   PR:		kern/151079
   MFC after:	1 week
 
 Modified:
   head/sys/pci/if_rl.c
 
 Modified: head/sys/pci/if_rl.c
 ==============================================================================
 --- head/sys/pci/if_rl.c	Thu Sep 30 17:05:23 2010	(r213305)
 +++ head/sys/pci/if_rl.c	Thu Sep 30 17:37:08 2010	(r213306)
 @@ -203,7 +203,7 @@ static void rl_read_eeprom(struct rl_sof
  static void rl_reset(struct rl_softc *);
  static int rl_resume(device_t);
  static int rl_rxeof(struct rl_softc *);
 -static void rl_setmulti(struct rl_softc *);
 +static void rl_rxfilter(struct rl_softc *);
  static int rl_shutdown(device_t);
  static void rl_start(struct ifnet *);
  static void rl_start_locked(struct ifnet *);
 @@ -655,54 +655,51 @@ rl_miibus_statchg(device_t dev)
   * Program the 64-bit multicast hash filter.
   */
  static void
 -rl_setmulti(struct rl_softc *sc)
 +rl_rxfilter(struct rl_softc *sc)
  {
  	struct ifnet		*ifp = sc->rl_ifp;
  	int			h = 0;
  	uint32_t		hashes[2] = { 0, 0 };
  	struct ifmultiaddr	*ifma;
  	uint32_t		rxfilt;
 -	int			mcnt = 0;
  
  	RL_LOCK_ASSERT(sc);
  
  	rxfilt = CSR_READ_4(sc, RL_RXCFG);
 -
 +	rxfilt &= ~(RL_RXCFG_RX_ALLPHYS | RL_RXCFG_RX_BROAD |
 +	    RL_RXCFG_RX_MULTI);
 +	/* Always accept frames destined for this host. */
 +	rxfilt |= RL_RXCFG_RX_INDIV;
 +	/* Set capture broadcast bit to capture broadcast frames. */
 +	if (ifp->if_flags & IFF_BROADCAST)
 +		rxfilt |= RL_RXCFG_RX_BROAD;
  	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
  		rxfilt |= RL_RXCFG_RX_MULTI;
 -		CSR_WRITE_4(sc, RL_RXCFG, rxfilt);
 -		CSR_WRITE_4(sc, RL_MAR0, 0xFFFFFFFF);
 -		CSR_WRITE_4(sc, RL_MAR4, 0xFFFFFFFF);
 -		return;
 -	}
 -
 -	/* first, zot all the existing hash bits */
 -	CSR_WRITE_4(sc, RL_MAR0, 0);
 -	CSR_WRITE_4(sc, RL_MAR4, 0);
 -
 -	/* 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;
 -		h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
 -		    ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
 -		if (h < 32)
 -			hashes[0] |= (1 << h);
 -		else
 -			hashes[1] |= (1 << (h - 32));
 -		mcnt++;
 +		if (ifp->if_flags & IFF_PROMISC)
 +			rxfilt |= RL_RXCFG_RX_ALLPHYS;
 +		hashes[0] = 0xFFFFFFFF;
 +		hashes[1] = 0xFFFFFFFF;
 +	} else {
 +		/* 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;
 +			h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
 +			    ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
 +			if (h < 32)
 +				hashes[0] |= (1 << h);
 +			else
 +				hashes[1] |= (1 << (h - 32));
 +		}
 +		if_maddr_runlock(ifp);
 +		if (hashes[0] != 0 || hashes[1] != 0)
 +			rxfilt |= RL_RXCFG_RX_MULTI;
  	}
 -	if_maddr_runlock(ifp);
 -
 -	if (mcnt)
 -		rxfilt |= RL_RXCFG_RX_MULTI;
 -	else
 -		rxfilt &= ~RL_RXCFG_RX_MULTI;
  
 -	CSR_WRITE_4(sc, RL_RXCFG, rxfilt);
  	CSR_WRITE_4(sc, RL_MAR0, hashes[0]);
  	CSR_WRITE_4(sc, RL_MAR4, hashes[1]);
 +	CSR_WRITE_4(sc, RL_RXCFG, rxfilt);
  }
  
  static void
 @@ -1807,7 +1804,6 @@ rl_init_locked(struct rl_softc *sc)
  {
  	struct ifnet		*ifp = sc->rl_ifp;
  	struct mii_data		*mii;
 -	uint32_t		rxcfg = 0;
  	uint32_t		eaddr[2];
  
  	RL_LOCK_ASSERT(sc);
 @@ -1864,30 +1860,8 @@ rl_init_locked(struct rl_softc *sc)
  	CSR_WRITE_4(sc, RL_TXCFG, RL_TXCFG_CONFIG);
  	CSR_WRITE_4(sc, RL_RXCFG, RL_RXCFG_CONFIG);
  
 -	/* Set the individual bit to receive frames for this host only. */
 -	rxcfg = CSR_READ_4(sc, RL_RXCFG);
 -	rxcfg |= RL_RXCFG_RX_INDIV;
 -
 -	/* If we want promiscuous mode, set the allframes bit. */
 -	if (ifp->if_flags & IFF_PROMISC) {
 -		rxcfg |= RL_RXCFG_RX_ALLPHYS;
 -		CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
 -	} else {
 -		rxcfg &= ~RL_RXCFG_RX_ALLPHYS;
 -		CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
 -	}
 -
 -	/* Set capture broadcast bit to capture broadcast frames. */
 -	if (ifp->if_flags & IFF_BROADCAST) {
 -		rxcfg |= RL_RXCFG_RX_BROAD;
 -		CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
 -	} else {
 -		rxcfg &= ~RL_RXCFG_RX_BROAD;
 -		CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
 -	}
 -
 -	/* Program the multicast filter, if necessary. */
 -	rl_setmulti(sc);
 +	/* Set RX filter. */
 +	rl_rxfilter(sc);
  
  #ifdef DEVICE_POLLING
  	/* Disable interrupts if we are polling. */
 @@ -1966,20 +1940,22 @@ rl_ioctl(struct ifnet *ifp, u_long comma
  	case SIOCSIFFLAGS:
  		RL_LOCK(sc);
  		if (ifp->if_flags & IFF_UP) {
 -			rl_init_locked(sc);
 -		} else {
 -			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
 -				rl_stop(sc);
 -		}
 +			if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
 +			    ((ifp->if_flags ^ sc->rl_if_flags) &
 +                            (IFF_PROMISC | IFF_ALLMULTI)))
 +				rl_rxfilter(sc);
 +                        else
 +				rl_init_locked(sc);
 +                } else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
 +			rl_stop(sc);
 +		sc->rl_if_flags = ifp->if_flags;
  		RL_UNLOCK(sc);
 -		error = 0;
  		break;
  	case SIOCADDMULTI:
  	case SIOCDELMULTI:
  		RL_LOCK(sc);
 -		rl_setmulti(sc);
 +		rl_rxfilter(sc);
  		RL_UNLOCK(sc);
 -		error = 0;
  		break;
  	case SIOCGIFMEDIA:
  	case SIOCSIFMEDIA:
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: yongari 
State-Changed-When: Thu Sep 30 17:46:37 UTC 2010 
State-Changed-Why:  
Submitter confirms that r213306 fixed the issue. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=151079 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/151079: commit references a PR
Date: Fri,  8 Oct 2010 18:19:13 +0000 (UTC)

 Author: yongari
 Date: Fri Oct  8 18:19:05 2010
 New Revision: 213590
 URL: http://svn.freebsd.org/changeset/base/213590
 
 Log:
   MFC r213306:
     Rename rl_setmulti() to rl_rxfilter() as rl_rxfilter() will handle
     IFF_ALLMULTI/IFF_PROMISC as well as multicast filter configuration.
     Rewrite RX filter logic to reduce number of register accesses and
     make it handle promiscuous/allmulti toggling without controller
     reinitialization.
   
     Previously rl(4) counted on controller reinitialization to reprogram
     promiscuous configuration but r211767 resulted in avoiding
     controller reinitialization whenever promiscuous mode is toggled.
     To address this, keep track of driver's view of interface state and
     handle IFF_ALLMULTI/IFF_PROMISC changes without reinitializing
     controller. This should fix a regression introduced in r211267.
   
     While I'm here remove unnecessary variable reassignment in ioctl
     handler.
   
     PR:	kern/151079
 
 Modified:
   stable/8/sys/pci/if_rl.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)
   stable/8/sys/dev/xen/xenpci/   (props changed)
 
 Modified: stable/8/sys/pci/if_rl.c
 ==============================================================================
 --- stable/8/sys/pci/if_rl.c	Fri Oct  8 18:06:30 2010	(r213589)
 +++ stable/8/sys/pci/if_rl.c	Fri Oct  8 18:19:05 2010	(r213590)
 @@ -203,7 +203,7 @@ static void rl_read_eeprom(struct rl_sof
  static void rl_reset(struct rl_softc *);
  static int rl_resume(device_t);
  static int rl_rxeof(struct rl_softc *);
 -static void rl_setmulti(struct rl_softc *);
 +static void rl_rxfilter(struct rl_softc *);
  static int rl_shutdown(device_t);
  static void rl_start(struct ifnet *);
  static void rl_start_locked(struct ifnet *);
 @@ -655,54 +655,51 @@ rl_miibus_statchg(device_t dev)
   * Program the 64-bit multicast hash filter.
   */
  static void
 -rl_setmulti(struct rl_softc *sc)
 +rl_rxfilter(struct rl_softc *sc)
  {
  	struct ifnet		*ifp = sc->rl_ifp;
  	int			h = 0;
  	uint32_t		hashes[2] = { 0, 0 };
  	struct ifmultiaddr	*ifma;
  	uint32_t		rxfilt;
 -	int			mcnt = 0;
  
  	RL_LOCK_ASSERT(sc);
  
  	rxfilt = CSR_READ_4(sc, RL_RXCFG);
 -
 +	rxfilt &= ~(RL_RXCFG_RX_ALLPHYS | RL_RXCFG_RX_BROAD |
 +	    RL_RXCFG_RX_MULTI);
 +	/* Always accept frames destined for this host. */
 +	rxfilt |= RL_RXCFG_RX_INDIV;
 +	/* Set capture broadcast bit to capture broadcast frames. */
 +	if (ifp->if_flags & IFF_BROADCAST)
 +		rxfilt |= RL_RXCFG_RX_BROAD;
  	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
  		rxfilt |= RL_RXCFG_RX_MULTI;
 -		CSR_WRITE_4(sc, RL_RXCFG, rxfilt);
 -		CSR_WRITE_4(sc, RL_MAR0, 0xFFFFFFFF);
 -		CSR_WRITE_4(sc, RL_MAR4, 0xFFFFFFFF);
 -		return;
 -	}
 -
 -	/* first, zot all the existing hash bits */
 -	CSR_WRITE_4(sc, RL_MAR0, 0);
 -	CSR_WRITE_4(sc, RL_MAR4, 0);
 -
 -	/* 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;
 -		h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
 -		    ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
 -		if (h < 32)
 -			hashes[0] |= (1 << h);
 -		else
 -			hashes[1] |= (1 << (h - 32));
 -		mcnt++;
 +		if (ifp->if_flags & IFF_PROMISC)
 +			rxfilt |= RL_RXCFG_RX_ALLPHYS;
 +		hashes[0] = 0xFFFFFFFF;
 +		hashes[1] = 0xFFFFFFFF;
 +	} else {
 +		/* 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;
 +			h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
 +			    ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
 +			if (h < 32)
 +				hashes[0] |= (1 << h);
 +			else
 +				hashes[1] |= (1 << (h - 32));
 +		}
 +		if_maddr_runlock(ifp);
 +		if (hashes[0] != 0 || hashes[1] != 0)
 +			rxfilt |= RL_RXCFG_RX_MULTI;
  	}
 -	if_maddr_runlock(ifp);
 -
 -	if (mcnt)
 -		rxfilt |= RL_RXCFG_RX_MULTI;
 -	else
 -		rxfilt &= ~RL_RXCFG_RX_MULTI;
  
 -	CSR_WRITE_4(sc, RL_RXCFG, rxfilt);
  	CSR_WRITE_4(sc, RL_MAR0, hashes[0]);
  	CSR_WRITE_4(sc, RL_MAR4, hashes[1]);
 +	CSR_WRITE_4(sc, RL_RXCFG, rxfilt);
  }
  
  static void
 @@ -1807,7 +1804,6 @@ rl_init_locked(struct rl_softc *sc)
  {
  	struct ifnet		*ifp = sc->rl_ifp;
  	struct mii_data		*mii;
 -	uint32_t		rxcfg = 0;
  	uint32_t		eaddr[2];
  
  	RL_LOCK_ASSERT(sc);
 @@ -1864,30 +1860,8 @@ rl_init_locked(struct rl_softc *sc)
  	CSR_WRITE_4(sc, RL_TXCFG, RL_TXCFG_CONFIG);
  	CSR_WRITE_4(sc, RL_RXCFG, RL_RXCFG_CONFIG);
  
 -	/* Set the individual bit to receive frames for this host only. */
 -	rxcfg = CSR_READ_4(sc, RL_RXCFG);
 -	rxcfg |= RL_RXCFG_RX_INDIV;
 -
 -	/* If we want promiscuous mode, set the allframes bit. */
 -	if (ifp->if_flags & IFF_PROMISC) {
 -		rxcfg |= RL_RXCFG_RX_ALLPHYS;
 -		CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
 -	} else {
 -		rxcfg &= ~RL_RXCFG_RX_ALLPHYS;
 -		CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
 -	}
 -
 -	/* Set capture broadcast bit to capture broadcast frames. */
 -	if (ifp->if_flags & IFF_BROADCAST) {
 -		rxcfg |= RL_RXCFG_RX_BROAD;
 -		CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
 -	} else {
 -		rxcfg &= ~RL_RXCFG_RX_BROAD;
 -		CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
 -	}
 -
 -	/* Program the multicast filter, if necessary. */
 -	rl_setmulti(sc);
 +	/* Set RX filter. */
 +	rl_rxfilter(sc);
  
  #ifdef DEVICE_POLLING
  	/* Disable interrupts if we are polling. */
 @@ -1966,20 +1940,22 @@ rl_ioctl(struct ifnet *ifp, u_long comma
  	case SIOCSIFFLAGS:
  		RL_LOCK(sc);
  		if (ifp->if_flags & IFF_UP) {
 -			rl_init_locked(sc);
 -		} else {
 -			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
 -				rl_stop(sc);
 -		}
 +			if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
 +			    ((ifp->if_flags ^ sc->rl_if_flags) &
 +                            (IFF_PROMISC | IFF_ALLMULTI)))
 +				rl_rxfilter(sc);
 +                        else
 +				rl_init_locked(sc);
 +                } else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
 +			rl_stop(sc);
 +		sc->rl_if_flags = ifp->if_flags;
  		RL_UNLOCK(sc);
 -		error = 0;
  		break;
  	case SIOCADDMULTI:
  	case SIOCDELMULTI:
  		RL_LOCK(sc);
 -		rl_setmulti(sc);
 +		rl_rxfilter(sc);
  		RL_UNLOCK(sc);
 -		error = 0;
  		break;
  	case SIOCGIFMEDIA:
  	case SIOCSIFMEDIA:
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/151079: commit references a PR
Date: Fri,  8 Oct 2010 18:26:21 +0000 (UTC)

 Author: yongari
 Date: Fri Oct  8 18:26:14 2010
 New Revision: 213591
 URL: http://svn.freebsd.org/changeset/base/213591
 
 Log:
   MFC r213306:
     Rename rl_setmulti() to rl_rxfilter() as rl_rxfilter() will handle
     IFF_ALLMULTI/IFF_PROMISC as well as multicast filter configuration.
     Rewrite RX filter logic to reduce number of register accesses and
     make it handle promiscuous/allmulti toggling without controller
     reinitialization.
   
     Previously rl(4) counted on controller reinitialization to reprogram
     promiscuous configuration but r211767 resulted in avoiding
     controller reinitialization whenever promiscuous mode is toggled.
     To address this, keep track of driver's view of interface state and
     handle IFF_ALLMULTI/IFF_PROMISC changes without reinitializing
     controller. This should fix a regression introduced in r211267.
   
     While I'm here remove unnecessary variable reassignment in ioctl
     handler.
   
     PR:	kern/151079
 
 Modified:
   stable/7/sys/pci/if_rl.c
 Directory Properties:
   stable/7/sys/   (props changed)
   stable/7/sys/cddl/contrib/opensolaris/   (props changed)
   stable/7/sys/contrib/dev/acpica/   (props changed)
   stable/7/sys/contrib/pf/   (props changed)
 
 Modified: stable/7/sys/pci/if_rl.c
 ==============================================================================
 --- stable/7/sys/pci/if_rl.c	Fri Oct  8 18:19:05 2010	(r213590)
 +++ stable/7/sys/pci/if_rl.c	Fri Oct  8 18:26:14 2010	(r213591)
 @@ -203,7 +203,7 @@ static void rl_read_eeprom(struct rl_sof
  static void rl_reset(struct rl_softc *);
  static int rl_resume(device_t);
  static void rl_rxeof(struct rl_softc *);
 -static void rl_setmulti(struct rl_softc *);
 +static void rl_rxfilter(struct rl_softc *);
  static int rl_shutdown(device_t);
  static void rl_start(struct ifnet *);
  static void rl_start_locked(struct ifnet *);
 @@ -655,54 +655,51 @@ rl_miibus_statchg(device_t dev)
   * Program the 64-bit multicast hash filter.
   */
  static void
 -rl_setmulti(struct rl_softc *sc)
 +rl_rxfilter(struct rl_softc *sc)
  {
  	struct ifnet		*ifp = sc->rl_ifp;
  	int			h = 0;
  	uint32_t		hashes[2] = { 0, 0 };
  	struct ifmultiaddr	*ifma;
  	uint32_t		rxfilt;
 -	int			mcnt = 0;
  
  	RL_LOCK_ASSERT(sc);
  
  	rxfilt = CSR_READ_4(sc, RL_RXCFG);
 -
 +	rxfilt &= ~(RL_RXCFG_RX_ALLPHYS | RL_RXCFG_RX_BROAD |
 +	    RL_RXCFG_RX_MULTI);
 +	/* Always accept frames destined for this host. */
 +	rxfilt |= RL_RXCFG_RX_INDIV;
 +	/* Set capture broadcast bit to capture broadcast frames. */
 +	if (ifp->if_flags & IFF_BROADCAST)
 +		rxfilt |= RL_RXCFG_RX_BROAD;
  	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
  		rxfilt |= RL_RXCFG_RX_MULTI;
 -		CSR_WRITE_4(sc, RL_RXCFG, rxfilt);
 -		CSR_WRITE_4(sc, RL_MAR0, 0xFFFFFFFF);
 -		CSR_WRITE_4(sc, RL_MAR4, 0xFFFFFFFF);
 -		return;
 -	}
 -
 -	/* first, zot all the existing hash bits */
 -	CSR_WRITE_4(sc, RL_MAR0, 0);
 -	CSR_WRITE_4(sc, RL_MAR4, 0);
 -
 -	/* now program new ones */
 -	IF_ADDR_LOCK(ifp);
 -	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 -		if (ifma->ifma_addr->sa_family != AF_LINK)
 -			continue;
 -		h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
 -		    ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
 -		if (h < 32)
 -			hashes[0] |= (1 << h);
 -		else
 -			hashes[1] |= (1 << (h - 32));
 -		mcnt++;
 +		if (ifp->if_flags & IFF_PROMISC)
 +			rxfilt |= RL_RXCFG_RX_ALLPHYS;
 +		hashes[0] = 0xFFFFFFFF;
 +		hashes[1] = 0xFFFFFFFF;
 +	} else {
 +		/* Now program new ones. */
 +		IF_ADDR_LOCK(ifp);
 +		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 +			if (ifma->ifma_addr->sa_family != AF_LINK)
 +				continue;
 +			h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
 +			    ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
 +			if (h < 32)
 +				hashes[0] |= (1 << h);
 +			else
 +				hashes[1] |= (1 << (h - 32));
 +		}
 +		IF_ADDR_UNLOCK(ifp);
 +		if (hashes[0] != 0 || hashes[1] != 0)
 +			rxfilt |= RL_RXCFG_RX_MULTI;
  	}
 -	IF_ADDR_UNLOCK(ifp);
 -
 -	if (mcnt)
 -		rxfilt |= RL_RXCFG_RX_MULTI;
 -	else
 -		rxfilt &= ~RL_RXCFG_RX_MULTI;
  
 -	CSR_WRITE_4(sc, RL_RXCFG, rxfilt);
  	CSR_WRITE_4(sc, RL_MAR0, hashes[0]);
  	CSR_WRITE_4(sc, RL_MAR4, hashes[1]);
 +	CSR_WRITE_4(sc, RL_RXCFG, rxfilt);
  }
  
  static void
 @@ -1800,7 +1797,6 @@ rl_init_locked(struct rl_softc *sc)
  {
  	struct ifnet		*ifp = sc->rl_ifp;
  	struct mii_data		*mii;
 -	uint32_t		rxcfg = 0;
  	uint32_t		eaddr[2];
  
  	RL_LOCK_ASSERT(sc);
 @@ -1857,30 +1853,8 @@ rl_init_locked(struct rl_softc *sc)
  	CSR_WRITE_4(sc, RL_TXCFG, RL_TXCFG_CONFIG);
  	CSR_WRITE_4(sc, RL_RXCFG, RL_RXCFG_CONFIG);
  
 -	/* Set the individual bit to receive frames for this host only. */
 -	rxcfg = CSR_READ_4(sc, RL_RXCFG);
 -	rxcfg |= RL_RXCFG_RX_INDIV;
 -
 -	/* If we want promiscuous mode, set the allframes bit. */
 -	if (ifp->if_flags & IFF_PROMISC) {
 -		rxcfg |= RL_RXCFG_RX_ALLPHYS;
 -		CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
 -	} else {
 -		rxcfg &= ~RL_RXCFG_RX_ALLPHYS;
 -		CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
 -	}
 -
 -	/* Set capture broadcast bit to capture broadcast frames. */
 -	if (ifp->if_flags & IFF_BROADCAST) {
 -		rxcfg |= RL_RXCFG_RX_BROAD;
 -		CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
 -	} else {
 -		rxcfg &= ~RL_RXCFG_RX_BROAD;
 -		CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
 -	}
 -
 -	/* Program the multicast filter, if necessary. */
 -	rl_setmulti(sc);
 +	/* Set RX filter. */
 +	rl_rxfilter(sc);
  
  #ifdef DEVICE_POLLING
  	/* Disable interrupts if we are polling. */
 @@ -1959,20 +1933,22 @@ rl_ioctl(struct ifnet *ifp, u_long comma
  	case SIOCSIFFLAGS:
  		RL_LOCK(sc);
  		if (ifp->if_flags & IFF_UP) {
 -			rl_init_locked(sc);
 -		} else {
 -			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
 -				rl_stop(sc);
 -		}
 +			if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
 +			    ((ifp->if_flags ^ sc->rl_if_flags) &
 +                            (IFF_PROMISC | IFF_ALLMULTI)))
 +				rl_rxfilter(sc);
 +                        else
 +				rl_init_locked(sc);
 +                } else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
 +			rl_stop(sc);
 +		sc->rl_if_flags = ifp->if_flags;
  		RL_UNLOCK(sc);
 -		error = 0;
  		break;
  	case SIOCADDMULTI:
  	case SIOCDELMULTI:
  		RL_LOCK(sc);
 -		rl_setmulti(sc);
 +		rl_rxfilter(sc);
  		RL_UNLOCK(sc);
 -		error = 0;
  		break;
  	case SIOCGIFMEDIA:
  	case SIOCSIFMEDIA:
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: yongari 
State-Changed-When: Fri Oct 8 18:37:12 UTC 2010 
State-Changed-Why:  
MFC to stable/8 and stable/7 done. 
Thanks for reporting! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=151079 
>Unformatted:
