mac80211: IBSS fix scan request

In case of wide bandwidth (wider than 20MHz) used by IBSS,
scan all channels in chandef to be able to find neighboring
IBSS netwqworks that use the same overall channels but a different
control channel.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Janusz.Dziedzic@tieto.com
2015-03-20 06:37:00 +01:00
committed by Johannes Berg
parent 97ffe75791
commit 76bed0f43b
3 changed files with 97 additions and 12 deletions

View File

@@ -1270,7 +1270,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef);
ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len,
NULL, scan_width);
NULL, 0, scan_width);
}
static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
@@ -1307,6 +1307,76 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
capability, 0, true);
}
static unsigned ibss_setup_channels(struct wiphy *wiphy,
struct ieee80211_channel **channels,
unsigned int channels_max,
u32 center_freq, u32 width)
{
struct ieee80211_channel *chan = NULL;
unsigned int n_chan = 0;
u32 start_freq, end_freq, freq;
if (width <= 20) {
start_freq = center_freq;
end_freq = center_freq;
} else {
start_freq = center_freq - width / 2 + 10;
end_freq = center_freq + width / 2 - 10;
}
for (freq = start_freq; freq <= end_freq; freq += 20) {
chan = ieee80211_get_channel(wiphy, freq);
if (!chan)
continue;
if (n_chan >= channels_max)
return n_chan;
channels[n_chan] = chan;
n_chan++;
}
return n_chan;
}
static unsigned int
ieee80211_ibss_setup_scan_channels(struct wiphy *wiphy,
const struct cfg80211_chan_def *chandef,
struct ieee80211_channel **channels,
unsigned int channels_max)
{
unsigned int n_chan = 0;
u32 width, cf1, cf2 = 0;
switch (chandef->width) {
case NL80211_CHAN_WIDTH_40:
width = 40;
break;
case NL80211_CHAN_WIDTH_80P80:
cf2 = chandef->center_freq2;
/* fall through */
case NL80211_CHAN_WIDTH_80:
width = 80;
break;
case NL80211_CHAN_WIDTH_160:
width = 160;
break;
default:
width = 20;
break;
}
cf1 = chandef->center_freq1;
n_chan = ibss_setup_channels(wiphy, channels, channels_max, cf1, width);
if (cf2)
n_chan += ibss_setup_channels(wiphy, &channels[n_chan],
channels_max - n_chan, cf2,
width);
return n_chan;
}
/*
* This function is called with state == IEEE80211_IBSS_MLME_SEARCH
*/
@@ -1372,11 +1442,18 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
/* Selected IBSS not found in current scan results - try to scan */
if (time_after(jiffies, ifibss->last_scan_completed +
IEEE80211_SCAN_INTERVAL)) {
struct ieee80211_channel *channels[8];
unsigned int num;
sdata_info(sdata, "Trigger new scan to find an IBSS to join\n");
num = ieee80211_ibss_setup_scan_channels(local->hw.wiphy,
&ifibss->chandef,
channels,
ARRAY_SIZE(channels));
scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef);
ieee80211_request_ibss_scan(sdata, ifibss->ssid,
ifibss->ssid_len, chan,
ifibss->ssid_len, channels, num,
scan_width);
} else {
int interval = IEEE80211_SCAN_INTERVAL;