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

Commit 7ca15a0a authored by Simon Wunderlich's avatar Simon Wunderlich Committed by Johannes Berg
Browse files

mac80211: allow scanning for 5/10 MHz channels in IBSS



Use a chandef instead of just the channel for scanning, and enable
5/10 Mhz scanning for IBSS mode. Also reporting is changed to the new
inform_bss functions.

Signed-off-by: default avatarSimon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: default avatarMathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
parent 0430c883
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
	u32 bss_change, rate_flags, rates = 0, rates_added = 0;
	u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
	struct cfg80211_chan_def chandef;
	enum nl80211_bss_scan_width scan_width;
	struct beacon_data *presp;
	int frame_len;
	int shift;
@@ -271,8 +272,10 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
	mod_timer(&ifibss->timer,
		  round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));

	bss = cfg80211_inform_bss_frame(local->hw.wiphy, chan,
					mgmt, presp->head_len, 0, GFP_KERNEL);
	scan_width = cfg80211_chandef_to_scan_width(&chandef);
	bss = cfg80211_inform_bss_width_frame(local->hw.wiphy, chan,
					      scan_width, mgmt,
					      presp->head_len, 0, GFP_KERNEL);
	cfg80211_put_bss(local->hw.wiphy, bss);
	netif_carrier_on(sdata->dev);
	cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
@@ -726,6 +729,7 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
	enum nl80211_bss_scan_width scan_width;

	sdata_assert_lock(sdata);

@@ -747,8 +751,9 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
	sdata_info(sdata,
		   "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n");

	scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef);
	ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len,
				    NULL);
				    NULL, scan_width);
}

static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
@@ -798,6 +803,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
	struct cfg80211_bss *cbss;
	struct ieee80211_channel *chan = NULL;
	const u8 *bssid = NULL;
	enum nl80211_bss_scan_width scan_width;
	int active_ibss;
	u16 capability;

@@ -846,8 +852,10 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
					IEEE80211_SCAN_INTERVAL)) {
		sdata_info(sdata, "Trigger new scan to find an IBSS to join\n");

		scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef);
		ieee80211_request_ibss_scan(sdata, ifibss->ssid,
					    ifibss->ssid_len, chan);
					    ifibss->ssid_len, chan,
					    scan_width);
	} else {
		int interval = IEEE80211_SCAN_INTERVAL;

+3 −2
Original line number Diff line number Diff line
@@ -1057,7 +1057,7 @@ struct ieee80211_local {
	struct cfg80211_ssid scan_ssid;
	struct cfg80211_scan_request *int_scan_req;
	struct cfg80211_scan_request *scan_req, *hw_scan_req;
	struct ieee80211_channel *scan_channel;
	struct cfg80211_chan_def scan_chandef;
	enum ieee80211_band hw_scan_band;
	int scan_channel_idx;
	int scan_ies_len;
@@ -1337,7 +1337,8 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
void ieee80211_scan_work(struct work_struct *work);
int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
				const u8 *ssid, u8 ssid_len,
				struct ieee80211_channel *chan);
				struct ieee80211_channel *chan,
				enum nl80211_bss_scan_width scan_width);
int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
			   struct cfg80211_scan_request *req);
void ieee80211_scan_cancel(struct ieee80211_local *local);
+2 −11
Original line number Diff line number Diff line
@@ -102,17 +102,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)

	offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;

	if (local->scan_channel) {
		chandef.chan = local->scan_channel;
		/* If scanning on oper channel, use whatever channel-type
		 * is currently in use.
		 */
		if (chandef.chan == local->_oper_chandef.chan) {
			chandef = local->_oper_chandef;
		} else {
			chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
			chandef.center_freq1 = chandef.chan->center_freq;
		}
	if (local->scan_chandef.chan) {
		chandef = local->scan_chandef;
	} else if (local->tmp_channel) {
		chandef.chan = local->tmp_channel;
		chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
+39 −6
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
	struct cfg80211_bss *cbss;
	struct ieee80211_bss *bss;
	int clen, srlen;
	enum nl80211_bss_scan_width scan_width;
	s32 signal = 0;

	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
@@ -73,8 +74,15 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
	else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
		signal = (rx_status->signal * 100) / local->hw.max_signal;

	cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel,
					 mgmt, len, signal, GFP_ATOMIC);
	scan_width = NL80211_BSS_CHAN_WIDTH_20;
	if (rx_status->flag & RX_FLAG_5MHZ)
		scan_width = NL80211_BSS_CHAN_WIDTH_5;
	if (rx_status->flag & RX_FLAG_10MHZ)
		scan_width = NL80211_BSS_CHAN_WIDTH_10;

	cbss = cfg80211_inform_bss_width_frame(local->hw.wiphy, channel,
					       scan_width, mgmt, len, signal,
					       GFP_ATOMIC);
	if (!cbss)
		return NULL;

@@ -300,7 +308,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
	rcu_assign_pointer(local->scan_sdata, NULL);

	local->scanning = 0;
	local->scan_channel = NULL;
	local->scan_chandef.chan = NULL;

	/* Set power back to normal operating levels. */
	ieee80211_hw_config(local, 0);
@@ -635,11 +643,34 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
{
	int skip;
	struct ieee80211_channel *chan;
	enum nl80211_bss_scan_width oper_scan_width;

	skip = 0;
	chan = local->scan_req->channels[local->scan_channel_idx];

	local->scan_channel = chan;
	local->scan_chandef.chan = chan;
	local->scan_chandef.center_freq1 = chan->center_freq;
	local->scan_chandef.center_freq2 = 0;
	switch (local->scan_req->scan_width) {
	case NL80211_BSS_CHAN_WIDTH_5:
		local->scan_chandef.width = NL80211_CHAN_WIDTH_5;
		break;
	case NL80211_BSS_CHAN_WIDTH_10:
		local->scan_chandef.width = NL80211_CHAN_WIDTH_10;
		break;
	case NL80211_BSS_CHAN_WIDTH_20:
		/* If scanning on oper channel, use whatever channel-type
		 * is currently in use.
		 */
		oper_scan_width = cfg80211_chandef_to_scan_width(
					&local->_oper_chandef);
		if (chan == local->_oper_chandef.chan &&
		    oper_scan_width == local->scan_req->scan_width)
			local->scan_chandef = local->_oper_chandef;
		else
			local->scan_chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
		break;
	}

	if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL))
		skip = 1;
@@ -679,7 +710,7 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local,
					 unsigned long *next_delay)
{
	/* switch back to the operating channel */
	local->scan_channel = NULL;
	local->scan_chandef.chan = NULL;
	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);

	/* disable PS */
@@ -821,7 +852,8 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,

int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
				const u8 *ssid, u8 ssid_len,
				struct ieee80211_channel *chan)
				struct ieee80211_channel *chan,
				enum nl80211_bss_scan_width scan_width)
{
	struct ieee80211_local *local = sdata->local;
	int ret = -EBUSY;
@@ -871,6 +903,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,

	local->int_scan_req->ssids = &local->scan_ssid;
	local->int_scan_req->n_ssids = 1;
	local->int_scan_req->scan_width = scan_width;
	memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
	local->int_scan_req->ssids[0].ssid_len = ssid_len;