Subject: Re: kern/32168
To: None <skrll@netbsd.org, gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: Nick Hudson <skrll@netbsd.org>
List: netbsd-bugs
Date: 12/03/2005 08:12:02
The following reply was made to PR kern/32168; it has been noted by GNATS.

From: Nick Hudson <skrll@netbsd.org>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: kern/32168
Date: Sat, 3 Dec 2005 08:11:34 +0000

 --Boundary-00=_3MVkD1tYz/KcDgc
 Content-Type: text/plain;
   charset="us-ascii"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline
 
 Here's a new patch that adds
 
 	- don't do an iwi_init when doing SIOCADDMULTI/SIOCDELMULTI
 	- marks the i/f IFF_RUNNING before kicking the net80211 state machine
 
 Please test.
 
 Thanks,
 Nick
 
 
 --Boundary-00=_3MVkD1tYz/KcDgc
 Content-Type: text/x-diff;
   charset="us-ascii";
   name="iwi.32168.diffs"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
 	filename="iwi.32168.diffs"
 
 Index: if_iwi.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/pci/if_iwi.c,v
 retrieving revision 1.42
 diff -u -p -u -r1.42 if_iwi.c
 --- if_iwi.c	29 Nov 2005 13:57:00 -0000	1.42
 +++ if_iwi.c	3 Dec 2005 07:57:51 -0000
 @@ -1893,9 +1893,12 @@ iwi_get_radio(struct iwi_softc *sc, int 
  static int
  iwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  {
 +#define	IS_RUNNING(ifp) \
 +	((ifp->if_flags & IFF_UP) && (ifp->if_flags & IFF_RUNNING))
 +
  	struct iwi_softc *sc = ifp->if_softc;
  	struct ieee80211com *ic = &sc->sc_ic;
 -	struct ifreq *ifr;
 +	struct ifreq *ifr = (struct ifreq *)data;
  	int s, error = 0;
  
  	s = splnet();
 @@ -1911,13 +1914,22 @@ iwi_ioctl(struct ifnet *ifp, u_long cmd,
  		}
  		break;
  
 +	case SIOCADDMULTI:
 +	case SIOCDELMULTI:
 +		error = (cmd == SIOCADDMULTI) ?
 +		    ether_addmulti(ifr, &sc->sc_ec) :
 +		    ether_delmulti(ifr, &sc->sc_ec);
 +		if (error == ENETRESET) {
 +			/* setup multicast filter, etc */
 +			error = 0;
 +		}
 +		break;
 +
  	case SIOCGTABLE0:
 -		ifr = (struct ifreq *)data;
  		error = iwi_get_table0(sc, (uint32_t *)ifr->ifr_data);
  		break;
  
  	case SIOCGRADIO:
 -		ifr = (struct ifreq *)data;
  		error = iwi_get_radio(sc, (int *)ifr->ifr_data);
  		break;
  
 @@ -1926,7 +1938,6 @@ iwi_ioctl(struct ifnet *ifp, u_long cmd,
  		if ((error = suser(curproc->p_ucred, &curproc->p_acflag)) != 0)
  			break;
  
 -		ifr = (struct ifreq *)data;
  		error = iwi_cache_firmware(sc, ifr->ifr_data);
  		break;
  
 @@ -1942,18 +1953,18 @@ iwi_ioctl(struct ifnet *ifp, u_long cmd,
  
  	default:
  		error = ieee80211_ioctl(&sc->sc_ic, cmd, data);
 -	}
  
 -	if (error == ENETRESET) {
 -		if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
 -		    (IFF_UP | IFF_RUNNING) &&
 -		    (ic->ic_roaming != IEEE80211_ROAMING_MANUAL))
 -			iwi_init(ifp);
 -		error = 0;
 +		if (error == ENETRESET) {
 +			if (IS_RUNNING(ifp) &&
 +			    (ic->ic_roaming != IEEE80211_ROAMING_MANUAL))
 +				iwi_init(ifp);
 +			error = 0;
 +		}
  	}
  
  	splx(s);
  	return error;
 +#undef IS_RUNNING
  }
  
  static void
 @@ -2711,15 +2722,17 @@ iwi_init(struct ifnet *ifp)
  		goto fail;
  	}
  
 +	ic->ic_state = IEEE80211_S_INIT;
 +
 +	ifp->if_flags &= ~IFF_OACTIVE;
 +	ifp->if_flags |= IFF_RUNNING;
 +
  	if (ic->ic_opmode != IEEE80211_M_MONITOR) {
  		if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
  			ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
  	} else
  		ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
  
 -	ifp->if_flags &= ~IFF_OACTIVE;
 -	ifp->if_flags |= IFF_RUNNING;
 -
  	return 0;
  
  fail:	ifp->if_flags &= ~IFF_UP;
 
 --Boundary-00=_3MVkD1tYz/KcDgc--