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

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
...@@ -51,6 +51,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, ...@@ -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; u32 bss_change, rate_flags, rates = 0, rates_added = 0;
u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef;
enum nl80211_bss_scan_width scan_width;
struct beacon_data *presp; struct beacon_data *presp;
int frame_len; int frame_len;
int shift; int shift;
...@@ -271,8 +272,10 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, ...@@ -271,8 +272,10 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
mod_timer(&ifibss->timer, mod_timer(&ifibss->timer,
round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
bss = cfg80211_inform_bss_frame(local->hw.wiphy, chan, scan_width = cfg80211_chandef_to_scan_width(&chandef);
mgmt, presp->head_len, 0, GFP_KERNEL); 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); cfg80211_put_bss(local->hw.wiphy, bss);
netif_carrier_on(sdata->dev); netif_carrier_on(sdata->dev);
cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); 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) ...@@ -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) static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
{ {
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
enum nl80211_bss_scan_width scan_width;
sdata_assert_lock(sdata); sdata_assert_lock(sdata);
...@@ -747,8 +751,9 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) ...@@ -747,8 +751,9 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
sdata_info(sdata, sdata_info(sdata,
"No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n"); "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, 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) 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) ...@@ -798,6 +803,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
struct cfg80211_bss *cbss; struct cfg80211_bss *cbss;
struct ieee80211_channel *chan = NULL; struct ieee80211_channel *chan = NULL;
const u8 *bssid = NULL; const u8 *bssid = NULL;
enum nl80211_bss_scan_width scan_width;
int active_ibss; int active_ibss;
u16 capability; u16 capability;
...@@ -846,8 +852,10 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) ...@@ -846,8 +852,10 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
IEEE80211_SCAN_INTERVAL)) { IEEE80211_SCAN_INTERVAL)) {
sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); 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, ieee80211_request_ibss_scan(sdata, ifibss->ssid,
ifibss->ssid_len, chan); ifibss->ssid_len, chan,
scan_width);
} else { } else {
int interval = IEEE80211_SCAN_INTERVAL; int interval = IEEE80211_SCAN_INTERVAL;
......
...@@ -1057,7 +1057,7 @@ struct ieee80211_local { ...@@ -1057,7 +1057,7 @@ struct ieee80211_local {
struct cfg80211_ssid scan_ssid; struct cfg80211_ssid scan_ssid;
struct cfg80211_scan_request *int_scan_req; struct cfg80211_scan_request *int_scan_req;
struct cfg80211_scan_request *scan_req, *hw_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; enum ieee80211_band hw_scan_band;
int scan_channel_idx; int scan_channel_idx;
int scan_ies_len; int scan_ies_len;
...@@ -1337,7 +1337,8 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, ...@@ -1337,7 +1337,8 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
void ieee80211_scan_work(struct work_struct *work); void ieee80211_scan_work(struct work_struct *work);
int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
const u8 *ssid, u8 ssid_len, 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, int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
struct cfg80211_scan_request *req); struct cfg80211_scan_request *req);
void ieee80211_scan_cancel(struct ieee80211_local *local); void ieee80211_scan_cancel(struct ieee80211_local *local);
......
...@@ -102,17 +102,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) ...@@ -102,17 +102,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
if (local->scan_channel) { if (local->scan_chandef.chan) {
chandef.chan = local->scan_channel; chandef = local->scan_chandef;
/* 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;
}
} else if (local->tmp_channel) { } else if (local->tmp_channel) {
chandef.chan = local->tmp_channel; chandef.chan = local->tmp_channel;
chandef.width = NL80211_CHAN_WIDTH_20_NOHT; chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
......
...@@ -66,6 +66,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, ...@@ -66,6 +66,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
struct cfg80211_bss *cbss; struct cfg80211_bss *cbss;
struct ieee80211_bss *bss; struct ieee80211_bss *bss;
int clen, srlen; int clen, srlen;
enum nl80211_bss_scan_width scan_width;
s32 signal = 0; s32 signal = 0;
if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
...@@ -73,8 +74,15 @@ ieee80211_bss_info_update(struct ieee80211_local *local, ...@@ -73,8 +74,15 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
signal = (rx_status->signal * 100) / local->hw.max_signal; signal = (rx_status->signal * 100) / local->hw.max_signal;
cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel, scan_width = NL80211_BSS_CHAN_WIDTH_20;
mgmt, len, signal, GFP_ATOMIC); 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) if (!cbss)
return NULL; return NULL;
...@@ -300,7 +308,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, ...@@ -300,7 +308,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
rcu_assign_pointer(local->scan_sdata, NULL); rcu_assign_pointer(local->scan_sdata, NULL);
local->scanning = 0; local->scanning = 0;
local->scan_channel = NULL; local->scan_chandef.chan = NULL;
/* Set power back to normal operating levels. */ /* Set power back to normal operating levels. */
ieee80211_hw_config(local, 0); ieee80211_hw_config(local, 0);
...@@ -635,11 +643,34 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, ...@@ -635,11 +643,34 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
{ {
int skip; int skip;
struct ieee80211_channel *chan; struct ieee80211_channel *chan;
enum nl80211_bss_scan_width oper_scan_width;
skip = 0; skip = 0;
chan = local->scan_req->channels[local->scan_channel_idx]; 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)) if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL))
skip = 1; skip = 1;
...@@ -679,7 +710,7 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local, ...@@ -679,7 +710,7 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local,
unsigned long *next_delay) unsigned long *next_delay)
{ {
/* switch back to the operating channel */ /* switch back to the operating channel */
local->scan_channel = NULL; local->scan_chandef.chan = NULL;
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
/* disable PS */ /* disable PS */
...@@ -821,7 +852,8 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, ...@@ -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, int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
const u8 *ssid, u8 ssid_len, 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; struct ieee80211_local *local = sdata->local;
int ret = -EBUSY; int ret = -EBUSY;
...@@ -871,6 +903,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, ...@@ -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->ssids = &local->scan_ssid;
local->int_scan_req->n_ssids = 1; 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); memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
local->int_scan_req->ssids[0].ssid_len = ssid_len; local->int_scan_req->ssids[0].ssid_len = ssid_len;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment