aboutsummaryrefslogtreecommitdiff
path: root/net/mac80211/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r--net/mac80211/main.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index caf92424c76..5667f4e8067 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -210,6 +210,8 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed)
!!rcu_dereference(sdata->u.ap.beacon);
break;
case NL80211_IFTYPE_ADHOC:
+ conf.enable_beacon = !!sdata->u.sta.probe_resp;
+ break;
case NL80211_IFTYPE_MESH_POINT:
conf.enable_beacon = true;
break;
@@ -731,6 +733,10 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
return NULL;
wiphy->privid = mac80211_wiphy_privid;
+ wiphy->max_scan_ssids = 4;
+ /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */
+ wiphy->bss_priv_size = sizeof(struct ieee80211_bss) -
+ sizeof(struct cfg80211_bss);
local = wiphy_priv(wiphy);
local->hw.wiphy = wiphy;
@@ -815,25 +821,33 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
enum ieee80211_band band;
struct net_device *mdev;
struct ieee80211_master_priv *mpriv;
+ int channels, i, j;
/*
* generic code guarantees at least one band,
* set this very early because much code assumes
* that hw.conf.channel is assigned
*/
+ channels = 0;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
struct ieee80211_supported_band *sband;
sband = local->hw.wiphy->bands[band];
- if (sband) {
+ if (sband && !local->oper_channel) {
/* init channel we're on */
local->hw.conf.channel =
local->oper_channel =
local->scan_channel = &sband->channels[0];
- break;
}
+ if (sband)
+ channels += sband->n_channels;
}
+ local->int_scan_req.n_channels = channels;
+ local->int_scan_req.channels = kzalloc(sizeof(void *) * channels, GFP_KERNEL);
+ if (!local->int_scan_req.channels)
+ return -ENOMEM;
+
/* if low-level driver supports AP, we also support VLAN */
if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP))
local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
@@ -843,7 +857,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
result = wiphy_register(local->hw.wiphy);
if (result < 0)
- return result;
+ goto fail_wiphy_register;
/*
* We use the number of queues for feature tests (QoS, HT) internally
@@ -866,8 +880,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
mpriv->local = local;
local->mdev = mdev;
- ieee80211_rx_bss_list_init(local);
-
local->hw.workqueue =
create_singlethread_workqueue(wiphy_name(local->hw.wiphy));
if (!local->hw.workqueue) {
@@ -893,14 +905,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
local->hw.conf.listen_interval = local->hw.max_listen_interval;
- local->wstats_flags |= local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC |
- IEEE80211_HW_SIGNAL_DBM) ?
- IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID;
- local->wstats_flags |= local->hw.flags & IEEE80211_HW_NOISE_DBM ?
- IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID;
- if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
- local->wstats_flags |= IW_QUAL_DBM;
-
result = sta_info_start(local);
if (result < 0)
goto fail_sta_info;
@@ -946,6 +950,20 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
ieee80211_led_init(local);
+ /* alloc internal scan request */
+ i = 0;
+ local->int_scan_req.ssids = &local->scan_ssid;
+ local->int_scan_req.n_ssids = 1;
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+ if (!hw->wiphy->bands[band])
+ continue;
+ for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) {
+ local->int_scan_req.channels[i] =
+ &hw->wiphy->bands[band]->channels[j];
+ i++;
+ }
+ }
+
return 0;
fail_wep:
@@ -964,6 +982,8 @@ fail_workqueue:
free_netdev(local->mdev);
fail_mdev_alloc:
wiphy_unregister(local->hw.wiphy);
+fail_wiphy_register:
+ kfree(local->int_scan_req.channels);
return result;
}
EXPORT_SYMBOL(ieee80211_register_hw);
@@ -991,7 +1011,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
rtnl_unlock();
- ieee80211_rx_bss_list_deinit(local);
ieee80211_clear_tx_pending(local);
sta_info_stop(local);
rate_control_deinitialize(local);
@@ -1009,6 +1028,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
ieee80211_wep_free(local);
ieee80211_led_exit(local);
free_netdev(local->mdev);
+ kfree(local->int_scan_req.channels);
}
EXPORT_SYMBOL(ieee80211_unregister_hw);