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

Commit 85220d71 authored by Johannes Berg's avatar Johannes Berg
Browse files

mac80211: support secondary channel offset in CSA



Add support for the secondary channel offset IE in channel
switch announcements. This is necessary for proper handling
of CSA on HT access points.

For this to work it is also necessary to convert everything
here to use chandef structs instead of just channels. The
driver updates aren't really correct though. In particular,
the TI wl18xx driver update can't possibly be right since
it just ignores the new channel width for lack of firmware
API.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent b4f286a1
Loading
Loading
Loading
Loading
+15 −17
Original line number Diff line number Diff line
@@ -6057,7 +6057,7 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw,
	struct il_priv *il = hw->priv;
	const struct il_channel_info *ch_info;
	struct ieee80211_conf *conf = &hw->conf;
	struct ieee80211_channel *channel = ch_switch->channel;
	struct ieee80211_channel *channel = ch_switch->chandef.chan;
	struct il_ht_config *ht_conf = &il->current_ht_config;
	u16 ch;

@@ -6094,23 +6094,21 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw,
	il->current_ht_config.smps = conf->smps_mode;

	/* Configure HT40 channels */
	il->ht.enabled = conf_is_ht(conf);
	if (il->ht.enabled) {
		if (conf_is_ht40_minus(conf)) {
			il->ht.extension_chan_offset =
			    IEEE80211_HT_PARAM_CHA_SEC_BELOW;
	switch (cfg80211_get_chandef_type(&ch_switch->chandef)) {
	case NL80211_CHAN_NO_HT:
	case NL80211_CHAN_HT20:
		il->ht.is_40mhz = false;
		il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
		break;
	case NL80211_CHAN_HT40MINUS:
		il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
		il->ht.is_40mhz = true;
		} else if (conf_is_ht40_plus(conf)) {
			il->ht.extension_chan_offset =
			    IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
		break;
	case NL80211_CHAN_HT40PLUS:
		il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
		il->ht.is_40mhz = true;
		} else {
			il->ht.extension_chan_offset =
			    IEEE80211_HT_PARAM_CHA_SEC_NONE;
			il->ht.is_40mhz = false;
		break;
	}
	} else
		il->ht.is_40mhz = false;

	if ((le16_to_cpu(il->staging.channel) != ch))
		il->staging.flags = 0;
+1 −1
Original line number Diff line number Diff line
@@ -1493,7 +1493,7 @@ il4965_hw_channel_switch(struct il_priv *il,

	cmd.band = band;
	cmd.expect_beacon = 0;
	ch = ch_switch->channel->hw_value;
	ch = ch_switch->chandef.chan->hw_value;
	cmd.channel = cpu_to_le16(ch);
	cmd.rxon_flags = il->staging.flags;
	cmd.rxon_filter_flags = il->staging.filter_flags;
+6 −4
Original line number Diff line number Diff line
@@ -379,7 +379,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
	};

	cmd.band = priv->band == IEEE80211_BAND_2GHZ;
	ch = ch_switch->channel->hw_value;
	ch = ch_switch->chandef.chan->hw_value;
	IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
		      ctx->active.channel, ch);
	cmd.channel = cpu_to_le16(ch);
@@ -414,7 +414,8 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
	}
	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
		      cmd.switch_time);
	cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
	cmd.expect_beacon =
		ch_switch->chandef.chan->flags & IEEE80211_CHAN_RADAR;

	return iwl_dvm_send_cmd(priv, &hcmd);
}
@@ -540,7 +541,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
	hcmd.data[0] = cmd;

	cmd->band = priv->band == IEEE80211_BAND_2GHZ;
	ch = ch_switch->channel->hw_value;
	ch = ch_switch->chandef.chan->hw_value;
	IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
		      ctx->active.channel, ch);
	cmd->channel = cpu_to_le16(ch);
@@ -575,7 +576,8 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
	}
	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
		      cmd->switch_time);
	cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
	cmd->expect_beacon =
		ch_switch->chandef.chan->flags & IEEE80211_CHAN_RADAR;

	err = iwl_dvm_send_cmd(priv, &hcmd);
	kfree(cmd);
+15 −5
Original line number Diff line number Diff line
@@ -967,7 +967,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
{
	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
	struct ieee80211_conf *conf = &hw->conf;
	struct ieee80211_channel *channel = ch_switch->channel;
	struct ieee80211_channel *channel = ch_switch->chandef.chan;
	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
	/*
	 * MULTI-FIXME
@@ -1005,11 +1005,21 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
	priv->current_ht_config.smps = conf->smps_mode;

	/* Configure HT40 channels */
	ctx->ht.enabled = conf_is_ht(conf);
	if (ctx->ht.enabled)
		iwlagn_config_ht40(conf, ctx);
	else
	switch (cfg80211_get_chandef_type(&ch_switch->chandef)) {
	case NL80211_CHAN_NO_HT:
	case NL80211_CHAN_HT20:
		ctx->ht.is_40mhz = false;
		ctx->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
		break;
	case NL80211_CHAN_HT40MINUS:
		ctx->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
		ctx->ht.is_40mhz = true;
		break;
	case NL80211_CHAN_HT40PLUS:
		ctx->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
		ctx->ht.is_40mhz = true;
		break;
	}

	if ((le16_to_cpu(ctx->staging.channel) != ch))
		ctx->staging.flags = 0;
+1 −1
Original line number Diff line number Diff line
@@ -301,7 +301,7 @@ int wl12xx_cmd_channel_switch(struct wl1271 *wl,
	}

	cmd->role_id = wlvif->role_id;
	cmd->channel = ch_switch->channel->hw_value;
	cmd->channel = ch_switch->chandef.chan->hw_value;
	cmd->switch_time = ch_switch->count;
	cmd->stop_tx = ch_switch->block_tx;

Loading