Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 382a103b authored by Johannes Berg's avatar Johannes Berg
Browse files

mac80211: fix idle handling sequence



Corey Richardson reported that my idle handling cleanup
(commit fd0f979a, "mac80211: simplify idle handling")
broke ath9k_htc. The reason appears to be that it wants
to go out of idle before switching channels. To fix it,
reimplement that sequence.

Reported-by: default avatarCorey Richardson <corey@octayn.net>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 3fbd45ca
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
		      enum ieee80211_chanctx_mode mode)
{
	struct ieee80211_chanctx *ctx;
	u32 changed;
	int err;

	lockdep_assert_held(&local->chanctx_mtx);
@@ -76,6 +77,13 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
	ctx->conf.rx_chains_dynamic = 1;
	ctx->mode = mode;

	/* acquire mutex to prevent idle from changing */
	mutex_lock(&local->mtx);
	/* turn idle off *before* setting channel -- some drivers need that */
	changed = ieee80211_idle_off(local);
	if (changed)
		ieee80211_hw_config(local, changed);

	if (!local->use_chanctx) {
		local->_oper_channel_type =
			cfg80211_get_chandef_type(chandef);
@@ -85,14 +93,17 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
		err = drv_add_chanctx(local, ctx);
		if (err) {
			kfree(ctx);
			return ERR_PTR(err);
			ctx = ERR_PTR(err);

			ieee80211_recalc_idle(local);
			goto out;
		}
	}

	/* and keep the mutex held until the new chanctx is on the list */
	list_add_rcu(&ctx->list, &local->chanctx_list);

	mutex_lock(&local->mtx);
	ieee80211_recalc_idle(local);
 out:
	mutex_unlock(&local->mtx);

	return ctx;
+1 −0
Original line number Diff line number Diff line
@@ -1362,6 +1362,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
			     enum nl80211_iftype type);
void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata);
void ieee80211_remove_interfaces(struct ieee80211_local *local);
u32 ieee80211_idle_off(struct ieee80211_local *local);
void ieee80211_recalc_idle(struct ieee80211_local *local);
void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
				    const int offset);
+1 −1
Original line number Diff line number Diff line
@@ -78,7 +78,7 @@ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER);
}

static u32 ieee80211_idle_off(struct ieee80211_local *local)
u32 ieee80211_idle_off(struct ieee80211_local *local)
{
	if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
		return 0;