From owner-svn-src-all@freebsd.org Sun Aug 23 01:17:53 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 46A719BF729; Sun, 23 Aug 2015 01:17:53 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1AE3C1F25; Sun, 23 Aug 2015 01:17:53 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id t7N1HqNl017110; Sun, 23 Aug 2015 01:17:52 GMT (envelope-from adrian@FreeBSD.org) Received: (from adrian@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id t7N1Hqj8017109; Sun, 23 Aug 2015 01:17:52 GMT (envelope-from adrian@FreeBSD.org) Message-Id: <201508230117.t7N1Hqj8017109@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: adrian set sender to adrian@FreeBSD.org using -f From: Adrian Chadd Date: Sun, 23 Aug 2015 01:17:52 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r287029 - head/sys/net80211 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 23 Aug 2015 01:17:53 -0000 Author: adrian Date: Sun Aug 23 01:17:52 2015 New Revision: 287029 URL: https://svnweb.freebsd.org/changeset/base/287029 Log: Reset the channel to the first available channel if the interface is configured on a channel that isn't valid in the new operating mode. This isn't strictly true - it should find the first channel that is available for the given operating mode. However, I think defaulting to the first channel is fine - it's typically available for all modes. If someone would like to correctly implement this feature - try to find a channel that is valid for the given operating mode and error out if we can't find one. This prevents various NICs (eg wpi(4)) from throwing a firmware error. Tested: * ath(4), STA/AP mode * iwn(4), STA/adhoc mode PR: kern/202502 Submitted by: Andriy Voskoboinyk Modified: head/sys/net80211/ieee80211_proto.c Modified: head/sys/net80211/ieee80211_proto.c ============================================================================== --- head/sys/net80211/ieee80211_proto.c Sat Aug 22 23:09:19 2015 (r287028) +++ head/sys/net80211/ieee80211_proto.c Sun Aug 23 01:17:52 2015 (r287029) @@ -1215,6 +1215,41 @@ ieee80211_waitfor_parent(struct ieee8021 } /* + * Check to see whether the current channel needs reset. + * + * Some devices don't handle being given an invalid channel + * in their operating mode very well (eg wpi(4) will throw a + * firmware exception.) + * + * Return 0 if we're ok, 1 if the channel needs to be reset. + * + * See PR kern/202502. + */ +static int +ieee80211_start_check_reset_chan(struct ieee80211vap *vap) +{ + struct ieee80211com *ic = vap->iv_ic; + + if ((vap->iv_opmode == IEEE80211_M_IBSS && + IEEE80211_IS_CHAN_NOADHOC(ic->ic_curchan)) || + (vap->iv_opmode == IEEE80211_M_HOSTAP && + IEEE80211_IS_CHAN_NOHOSTAP(ic->ic_curchan))) + return (1); + return (0); +} + +/* + * Reset the curchan to a known good state. + */ +static void +ieee80211_start_reset_chan(struct ieee80211vap *vap) +{ + struct ieee80211com *ic = vap->iv_ic; + + ic->ic_curchan = &ic->ic_channels[0]; +} + +/* * Start a vap running. If this is the first vap to be * set running on the underlying device then we * automatically bring the device up. @@ -1248,6 +1283,11 @@ ieee80211_start_locked(struct ieee80211v */ if (ic->ic_nrunning++ == 0 && (parent->if_drv_flags & IFF_DRV_RUNNING) == 0) { + + /* reset the channel to a known good channel */ + if (ieee80211_start_check_reset_chan(vap)) + ieee80211_start_reset_chan(vap); + IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, "%s: up parent %s\n", __func__, parent->if_xname);