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

Commit c0f17eb9 authored by Chun-Yeow Yeoh's avatar Chun-Yeow Yeoh Committed by Johannes Berg
Browse files

mac80211: refactor the parsing of chan switch ie



Refactor the channel switch IE parsing to reduce the number
of function parameters.

Signed-off-by: default avatarChun-Yeow Yeoh <yeohchunyeow@cozybit.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 06be6b14
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -836,13 +836,13 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
				  bool beacon)
{
	struct cfg80211_csa_settings params;
	struct ieee80211_csa_ie csa_ie;
	struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
	struct ieee80211_chanctx_conf *chanctx_conf;
	struct ieee80211_chanctx *chanctx;
	enum nl80211_channel_type ch_type;
	int err, num_chanctx;
	u32 sta_flags;
	u8 mode;

	if (sdata->vif.csa_active)
		return true;
@@ -865,12 +865,10 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
	}

	memset(&params, 0, sizeof(params));
	memset(&csa_ie, 0, sizeof(csa_ie));
	err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon,
					   ifibss->chandef.chan->band,
					   sta_flags, ifibss->bssid,
					   &params.count, &mode,
					   &params.chandef);

					   sta_flags, ifibss->bssid, &csa_ie);
	/* can't switch to destination channel, fail */
	if (err < 0)
		goto disconnect;
@@ -879,6 +877,9 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
	if (err)
		return false;

	params.count = csa_ie.count;
	params.chandef = csa_ie.chandef;

	if (ifibss->chandef.chan->band != params.chandef.chan->band)
		goto disconnect;

@@ -965,7 +966,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
		 "received channel switch announcement to go to channel %d MHz\n",
		 params.chandef.chan->center_freq);

	params.block_tx = !!mode;
	params.block_tx = !!csa_ie.mode;

	ieee80211_ibss_csa_beacon(sdata, &params);
	sdata->csa_radar_required = params.radar_required;
+12 −5
Original line number Diff line number Diff line
@@ -1208,6 +1208,14 @@ struct ieee80211_ra_tid {
	u16 tid;
};

/* this struct holds the value parsing from channel switch IE  */
struct ieee80211_csa_ie {
	struct cfg80211_chan_def chandef;
	u8 mode;
	u8 count;
	u8 ttl;
};

/* Parsed Information Elements */
struct ieee802_11_elems {
	const u8 *ie_start;
@@ -1505,17 +1513,16 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
 *	%IEEE80211_STA_DISABLE_HT, %IEEE80211_STA_DISABLE_VHT,
 *	%IEEE80211_STA_DISABLE_40MHZ, %IEEE80211_STA_DISABLE_80P80MHZ,
 *	%IEEE80211_STA_DISABLE_160MHZ.
 * @count: to be filled with the counter until the switch (on success only)
 * @bssid: the currently connected bssid (for reporting)
 * @mode: to be filled with CSA mode (on success only)
 * @new_chandef: to be filled with destination chandef (on success only)
 * @csa_ie: parsed 802.11 csa elements on count, mode, chandef and mesh ttl.
	All of them will be filled with if success only.
 * Return: 0 on success, <0 on error and >0 if there is nothing to parse.
 */
int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
				 struct ieee802_11_elems *elems, bool beacon,
				 enum ieee80211_band current_band,
				 u32 sta_flags, u8 *bssid, u8 *count, u8 *mode,
				 struct cfg80211_chan_def *new_chandef);
				 u32 sta_flags, u8 *bssid,
				 struct ieee80211_csa_ie *csa_ie);

/* Suspend/resume and hw reconfiguration */
int ieee80211_reconfig(struct ieee80211_local *local);
+15 −17
Original line number Diff line number Diff line
@@ -958,9 +958,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
	struct cfg80211_bss *cbss = ifmgd->associated;
	struct ieee80211_chanctx *chanctx;
	enum ieee80211_band current_band;
	u8 count;
	u8 mode;
	struct cfg80211_chan_def new_chandef = {};
	struct ieee80211_csa_ie csa_ie;
	int res;

	sdata_assert_lock(sdata);
@@ -976,24 +974,24 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
		return;

	current_band = cbss->channel->band;
	memset(&csa_ie, 0, sizeof(csa_ie));
	res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band,
					   ifmgd->flags,
					   ifmgd->associated->bssid, &count,
					   &mode, &new_chandef);
					   ifmgd->associated->bssid, &csa_ie);
	if (res	< 0)
		ieee80211_queue_work(&local->hw,
				     &ifmgd->csa_connection_drop_work);
	if (res)
		return;

	if (!cfg80211_chandef_usable(local->hw.wiphy, &new_chandef,
	if (!cfg80211_chandef_usable(local->hw.wiphy, &csa_ie.chandef,
				     IEEE80211_CHAN_DISABLED)) {
		sdata_info(sdata,
			   "AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
			   ifmgd->associated->bssid,
			   new_chandef.chan->center_freq,
			   new_chandef.width, new_chandef.center_freq1,
			   new_chandef.center_freq2);
			   csa_ie.chandef.chan->center_freq,
			   csa_ie.chandef.width, csa_ie.chandef.center_freq1,
			   csa_ie.chandef.center_freq2);
		ieee80211_queue_work(&local->hw,
				     &ifmgd->csa_connection_drop_work);
		return;
@@ -1037,9 +1035,9 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
	}
	mutex_unlock(&local->chanctx_mtx);

	local->csa_chandef = new_chandef;
	local->csa_chandef = csa_ie.chandef;

	if (mode)
	if (csa_ie.mode)
		ieee80211_stop_queues_by_reason(&local->hw,
				IEEE80211_MAX_QUEUE_MAP,
				IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -1048,9 +1046,9 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
		/* use driver's channel switch callback */
		struct ieee80211_channel_switch ch_switch = {
			.timestamp = timestamp,
			.block_tx = mode,
			.chandef = new_chandef,
			.count = count,
			.block_tx = csa_ie.mode,
			.chandef = csa_ie.chandef,
			.count = csa_ie.count,
		};

		drv_channel_switch(local, &ch_switch);
@@ -1058,11 +1056,11 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
	}

	/* channel switch handled in software */
	if (count <= 1)
	if (csa_ie.count <= 1)
		ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work);
	else
		mod_timer(&ifmgd->chswitch_timer,
			  TU_TO_EXP_TIME(count * cbss->beacon_interval));
			  TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval));
}

static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
+14 −13
Original line number Diff line number Diff line
@@ -24,8 +24,8 @@
int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
				 struct ieee802_11_elems *elems, bool beacon,
				 enum ieee80211_band current_band,
				 u32 sta_flags, u8 *bssid, u8 *count, u8 *mode,
				 struct cfg80211_chan_def *new_chandef)
				 u32 sta_flags, u8 *bssid,
				 struct ieee80211_csa_ie *csa_ie)
{
	enum ieee80211_band new_band;
	int new_freq;
@@ -62,13 +62,13 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
			return -EINVAL;
		}
		new_chan_no = elems->ext_chansw_ie->new_ch_num;
		*count = elems->ext_chansw_ie->count;
		*mode = elems->ext_chansw_ie->mode;
		csa_ie->count = elems->ext_chansw_ie->count;
		csa_ie->mode = elems->ext_chansw_ie->mode;
	} else if (elems->ch_switch_ie) {
		new_band = current_band;
		new_chan_no = elems->ch_switch_ie->new_ch_num;
		*count = elems->ch_switch_ie->count;
		*mode = elems->ch_switch_ie->mode;
		csa_ie->count = elems->ch_switch_ie->count;
		csa_ie->mode = elems->ch_switch_ie->mode;
	} else {
		/* nothing here we understand */
		return 1;
@@ -103,25 +103,26 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
	default:
		/* secondary_channel_offset was present but is invalid */
	case IEEE80211_HT_PARAM_CHA_SEC_NONE:
		cfg80211_chandef_create(new_chandef, new_chan,
		cfg80211_chandef_create(&csa_ie->chandef, new_chan,
					NL80211_CHAN_HT20);
		break;
	case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
		cfg80211_chandef_create(new_chandef, new_chan,
		cfg80211_chandef_create(&csa_ie->chandef, new_chan,
					NL80211_CHAN_HT40PLUS);
		break;
	case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
		cfg80211_chandef_create(new_chandef, new_chan,
		cfg80211_chandef_create(&csa_ie->chandef, new_chan,
					NL80211_CHAN_HT40MINUS);
		break;
	case -1:
		cfg80211_chandef_create(new_chandef, new_chan,
		cfg80211_chandef_create(&csa_ie->chandef, new_chan,
					NL80211_CHAN_NO_HT);
		/* keep width for 5/10 MHz channels */
		switch (sdata->vif.bss_conf.chandef.width) {
		case NL80211_CHAN_WIDTH_5:
		case NL80211_CHAN_WIDTH_10:
			new_chandef->width = sdata->vif.bss_conf.chandef.width;
			csa_ie->chandef.width =
				sdata->vif.bss_conf.chandef.width;
			break;
		default:
			break;
@@ -171,13 +172,13 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
	/* if VHT data is there validate & use it */
	if (new_vht_chandef.chan) {
		if (!cfg80211_chandef_compatible(&new_vht_chandef,
						 new_chandef)) {
						 &csa_ie->chandef)) {
			sdata_info(sdata,
				   "BSS %pM: CSA has inconsistent channel data, disconnecting\n",
				   bssid);
			return -EINVAL;
		}
		*new_chandef = new_vht_chandef;
		csa_ie->chandef = new_vht_chandef;
	}

	return 0;