diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/Kconfig | 2 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 1 | ||||
-rw-r--r-- | net/mac80211/debugfs.c | 6 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 11 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 2 | ||||
-rw-r--r-- | net/mac80211/main.c | 33 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 8 | ||||
-rw-r--r-- | net/mac80211/rx.c | 12 | ||||
-rw-r--r-- | net/mac80211/scan.c | 15 | ||||
-rw-r--r-- | net/mac80211/tx.c | 1 | ||||
-rw-r--r-- | net/mac80211/util.c | 6 | ||||
-rw-r--r-- | net/mac80211/work.c | 59 |
12 files changed, 113 insertions, 43 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index c766056d0488..dbf5e4006bc1 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -17,7 +17,7 @@ comment "CFG80211 needs to be enabled for MAC80211" if MAC80211 != n config MAC80211_HAS_RC - def_bool n + bool config MAC80211_RC_PID bool "PID controller based rate control algorithm" if EXPERT diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 2ba3af850dda..140503d4c97a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1863,6 +1863,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, wk->type = IEEE80211_WORK_OFFCHANNEL_TX; wk->chan = chan; + wk->chan_type = channel_type; wk->sdata = sdata; wk->done = ieee80211_offchan_tx_done; wk->offchan_tx.frame = skb; diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 1f02e599a318..51f0d780dafa 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -60,6 +60,10 @@ static const struct file_operations name## _ops = { \ debugfs_create_file(#name, mode, phyd, local, &name## _ops); +DEBUGFS_READONLY_FILE(user_power, "%d", + local->user_power_level); +DEBUGFS_READONLY_FILE(power, "%d", + local->hw.conf.power_level); DEBUGFS_READONLY_FILE(frequency, "%d", local->hw.conf.channel->center_freq); DEBUGFS_READONLY_FILE(total_ps_buffered, "%d", @@ -391,6 +395,8 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_ADD(uapsd_queues); DEBUGFS_ADD(uapsd_max_sp_len); DEBUGFS_ADD(channel_type); + DEBUGFS_ADD(user_power); + DEBUGFS_ADD(power); statsd = debugfs_create_dir("statistics", phyd); diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 775fb63471c4..a42aa61269ea 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -664,12 +664,13 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) } static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgmt *mgmt, - size_t len) + struct sk_buff *req) { + struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(req); + struct ieee80211_mgmt *mgmt = (void *)req->data; struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_local *local = sdata->local; - int tx_last_beacon; + int tx_last_beacon, len = req->len; struct sk_buff *skb; struct ieee80211_mgmt *resp; u8 *pos, *end; @@ -689,7 +690,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, mgmt->bssid, tx_last_beacon); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ - if (!tx_last_beacon) + if (!tx_last_beacon && !(rx_status->rx_flags & IEEE80211_RX_RA_MATCH)) return; if (memcmp(mgmt->bssid, ifibss->bssid, ETH_ALEN) != 0 && @@ -786,7 +787,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, switch (fc & IEEE80211_FCTL_STYPE) { case IEEE80211_STYPE_PROBE_REQ: - ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len); + ieee80211_rx_mgmt_probe_req(sdata, skb); break; case IEEE80211_STYPE_PROBE_RESP: ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f2ef15d910a5..0a570a111a84 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1066,8 +1066,6 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, void ieee80211_configure_filter(struct ieee80211_local *local); u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); -extern bool ieee80211_disable_40mhz_24ghz; - /* STA code */ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c155c0b69426..2543e48bd813 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -34,7 +34,7 @@ #include "debugfs.h" -bool ieee80211_disable_40mhz_24ghz; +static bool ieee80211_disable_40mhz_24ghz; module_param(ieee80211_disable_40mhz_24ghz, bool, 0644); MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz, "Disable 40MHz support in the 2.4GHz band"); @@ -112,7 +112,13 @@ bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local) /* This logic needs to match logic in ieee80211_hw_config */ if (local->scan_channel) { chan = local->scan_channel; - channel_type = NL80211_CHAN_NO_HT; + /* If scanning on oper channel, use whatever channel-type + * is currently in use. + */ + if (chan == local->oper_channel) + channel_type = local->_oper_channel_type; + else + channel_type = NL80211_CHAN_NO_HT; } else if (local->tmp_channel) { chan = scan_chan = local->tmp_channel; channel_type = local->tmp_channel_type; @@ -151,7 +157,13 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; if (scan_chan) { chan = scan_chan; - channel_type = NL80211_CHAN_NO_HT; + /* If scanning on oper channel, use whatever channel-type + * is currently in use. + */ + if (chan == local->oper_channel) + channel_type = local->_oper_channel_type; + else + channel_type = NL80211_CHAN_NO_HT; } else if (local->tmp_channel) { chan = scan_chan = local->tmp_channel; channel_type = local->tmp_channel_type; @@ -187,7 +199,8 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) changed |= IEEE80211_CONF_CHANGE_SMPS; } - if (scan_chan) + if ((local->scanning & SCAN_SW_SCANNING) || + (local->scanning & SCAN_HW_SCANNING)) power = chan->max_power; else power = local->power_constr_level ? @@ -710,6 +723,18 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) } channels += sband->n_channels; + /* + * Since ieee80211_disable_40mhz_24ghz is global, we can + * modify the sband's ht data even if the driver uses a + * global structure for that. + */ + if (ieee80211_disable_40mhz_24ghz && + band == IEEE80211_BAND_2GHZ && + sband->ht_cap.ht_supported) { + sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40; + } + if (max_bitrates < sband->n_bitrates) max_bitrates = sband->n_bitrates; supp_ht = supp_ht || sband->ht_cap.ht_supported; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f77adf1a520e..7b3f9df725bd 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1071,6 +1071,12 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, if (is_multicast_ether_addr(hdr->addr1)) return; + /* + * In case we receive frames after disassociation. + */ + if (!sdata->u.mgd.associated) + return; + ieee80211_sta_reset_conn_monitor(sdata); } @@ -2294,6 +2300,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, else wk->type = IEEE80211_WORK_DIRECT_PROBE; wk->chan = req->bss->channel; + wk->chan_type = NL80211_CHAN_NO_HT; wk->sdata = sdata; wk->done = ieee80211_probe_auth_done; @@ -2443,6 +2450,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN); wk->chan = req->bss->channel; + wk->chan_type = NL80211_CHAN_NO_HT; wk->sdata = sdata; wk->done = ieee80211_assoc_done; if (!bss->dtim_period && diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 045b2fe4a414..f502634d43af 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -832,18 +832,8 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) ieee80211_is_pspoll(hdr->frame_control)) && rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && rx->sdata->vif.type != NL80211_IFTYPE_WDS && - (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { - if ((!ieee80211_has_fromds(hdr->frame_control) && - !ieee80211_has_tods(hdr->frame_control) && - ieee80211_is_data(hdr->frame_control)) || - !(status->rx_flags & IEEE80211_RX_RA_MATCH)) { - /* Drop IBSS frames and frames for other hosts - * silently. */ - return RX_DROP_MONITOR; - } - + (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) return RX_DROP_MONITOR; - } return RX_CONTINUE; } diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 0ea6adae3e06..842954509925 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -307,11 +307,15 @@ static void __ieee80211_scan_completed_finish(struct ieee80211_hw *hw, mutex_lock(&local->mtx); on_oper_chan = ieee80211_cfg_on_oper_channel(local); + WARN_ON(local->scanning & (SCAN_SW_SCANNING | SCAN_HW_SCANNING)); + if (was_hw_scan || !on_oper_chan) { if (WARN_ON(local->scan_channel)) local->scan_channel = NULL; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); - } + } else + /* Set power back to normal operating levels. */ + ieee80211_hw_config(local, 0); if (!was_hw_scan) { bool on_oper_chan2; @@ -377,6 +381,9 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) ieee80211_configure_filter(local); + /* We need to set power level at maximum rate for scanning. */ + ieee80211_hw_config(local, 0); + ieee80211_queue_delayed_work(&local->hw, &local->scan_work, IEEE80211_CHANNEL_TIME); @@ -517,8 +524,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, if (ieee80211_cfg_on_oper_channel(local)) { /* We're currently on operating channel. */ - if ((next_chan == local->oper_channel) && - (local->_oper_channel_type == NL80211_CHAN_NO_HT)) + if (next_chan == local->oper_channel) /* We don't need to move off of operating channel. */ local->next_scan_state = SCAN_SET_CHANNEL; else @@ -620,8 +626,7 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, local->scan_channel = chan; /* Only call hw-config if we really need to change channels. */ - if ((chan != local->hw.conf.channel) || - (local->hw.conf.channel_type != NL80211_CHAN_NO_HT)) + if (chan != local->hw.conf.channel) if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL)) skip = 1; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 17ef4f4e8602..34edf7f22b0e 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -236,6 +236,7 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) if (local->hw.conf.flags & IEEE80211_CONF_PS) { ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_QUEUE_STOP_REASON_PS); + ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; ieee80211_queue_work(&local->hw, &local->dynamic_ps_disable_work); } diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d036597aabbe..556647a910ac 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -986,12 +986,6 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, u16 cap = sband->ht_cap.cap; __le16 tmp; - if (ieee80211_disable_40mhz_24ghz && - sband->band == IEEE80211_BAND_2GHZ) { - cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - cap &= ~IEEE80211_HT_CAP_SGI_40; - } - *pos++ = WLAN_EID_HT_CAPABILITY; *pos++ = sizeof(struct ieee80211_ht_cap); memset(pos, 0, sizeof(struct ieee80211_ht_cap)); diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 6bf787a5b38a..204f0a4db969 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -126,12 +126,6 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie, /* determine capability flags */ - if (ieee80211_disable_40mhz_24ghz && - sband->band == IEEE80211_BAND_2GHZ) { - cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - cap &= ~IEEE80211_HT_CAP_SGI_40; - } - switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: if (flags & IEEE80211_CHAN_NO_HT40PLUS) { @@ -874,6 +868,44 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, kfree_skb(skb); } +static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct, + enum nl80211_channel_type oper_ct) +{ + switch (wk_ct) { + case NL80211_CHAN_NO_HT: + return true; + case NL80211_CHAN_HT20: + if (oper_ct != NL80211_CHAN_NO_HT) + return true; + return false; + case NL80211_CHAN_HT40MINUS: + case NL80211_CHAN_HT40PLUS: + return (wk_ct == oper_ct); + } + WARN_ON(1); /* shouldn't get here */ + return false; +} + +static enum nl80211_channel_type +ieee80211_calc_ct(enum nl80211_channel_type wk_ct, + enum nl80211_channel_type oper_ct) +{ + switch (wk_ct) { + case NL80211_CHAN_NO_HT: + return oper_ct; + case NL80211_CHAN_HT20: + if (oper_ct != NL80211_CHAN_NO_HT) + return oper_ct; + return wk_ct; + case NL80211_CHAN_HT40MINUS: + case NL80211_CHAN_HT40PLUS: + return wk_ct; + } + WARN_ON(1); /* shouldn't get here */ + return wk_ct; +} + + static void ieee80211_work_timer(unsigned long data) { struct ieee80211_local *local = (void *) data; @@ -927,14 +959,22 @@ static void ieee80211_work_work(struct work_struct *work) bool on_oper_chan; bool tmp_chan_changed = false; bool on_oper_chan2; + enum nl80211_channel_type wk_ct; on_oper_chan = ieee80211_cfg_on_oper_channel(local); + + /* Work with existing channel type if possible. */ + wk_ct = wk->chan_type; + if (wk->chan == local->hw.conf.channel) + wk_ct = ieee80211_calc_ct(wk->chan_type, + local->hw.conf.channel_type); + if (local->tmp_channel) if ((local->tmp_channel != wk->chan) || - (local->tmp_channel_type != wk->chan_type)) + (local->tmp_channel_type != wk_ct)) tmp_chan_changed = true; local->tmp_channel = wk->chan; - local->tmp_channel_type = wk->chan_type; + local->tmp_channel_type = wk_ct; /* * Leave the station vifs in awake mode if they * happen to be on the same channel as @@ -1031,7 +1071,8 @@ static void ieee80211_work_work(struct work_struct *work) continue; if (wk->chan != local->tmp_channel) continue; - if (wk->chan_type != local->tmp_channel_type) + if (ieee80211_work_ct_coexists(wk->chan_type, + local->tmp_channel_type)) continue; remain_off_channel = true; } |