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 <s3erios@gmail.com>
This commit is contained in:
parent
18803951d5
commit
24034ddb3e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=287029
@ -1214,6 +1214,41 @@ ieee80211_waitfor_parent(struct ieee80211com *ic)
|
||||
taskqueue_unblock(ic->ic_tq);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
@ -1248,6 +1283,11 @@ ieee80211_start_locked(struct ieee80211vap *vap)
|
||||
*/
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user