Commit 0c9a67c8 authored by John W. Linville's avatar John W. Linville

Merge tag 'mac80211-for-john-2014-11-04' of...

Merge tag 'mac80211-for-john-2014-11-04' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211

Johannes Berg <johannes@sipsolutions.net> says:

"This contains another small set of fixes for 3.18, these are all
over the place and most of the bugs are old, one even dates back
to the original mac80211 we merged into the kernel."
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parents c00ed46d b8fff407
...@@ -1987,7 +1987,7 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, ...@@ -1987,7 +1987,7 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2,
if (err != 0) { if (err != 0) {
printk(KERN_DEBUG "mac80211_hwsim: device_bind_driver failed (%d)\n", printk(KERN_DEBUG "mac80211_hwsim: device_bind_driver failed (%d)\n",
err); err);
goto failed_hw; goto failed_bind;
} }
skb_queue_head_init(&data->pending); skb_queue_head_init(&data->pending);
...@@ -2183,6 +2183,8 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, ...@@ -2183,6 +2183,8 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2,
return idx; return idx;
failed_hw: failed_hw:
device_release_driver(data->dev);
failed_bind:
device_unregister(data->dev); device_unregister(data->dev);
failed_drvdata: failed_drvdata:
ieee80211_free_hw(hw); ieee80211_free_hw(hw);
......
...@@ -805,7 +805,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, ...@@ -805,7 +805,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
memset(&csa_ie, 0, sizeof(csa_ie)); memset(&csa_ie, 0, sizeof(csa_ie));
err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, err = ieee80211_parse_ch_switch_ie(sdata, elems,
ifibss->chandef.chan->band, ifibss->chandef.chan->band,
sta_flags, ifibss->bssid, &csa_ie); sta_flags, ifibss->bssid, &csa_ie);
/* can't switch to destination channel, fail */ /* can't switch to destination channel, fail */
......
...@@ -1642,7 +1642,6 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, ...@@ -1642,7 +1642,6 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
* ieee80211_parse_ch_switch_ie - parses channel switch IEs * ieee80211_parse_ch_switch_ie - parses channel switch IEs
* @sdata: the sdata of the interface which has received the frame * @sdata: the sdata of the interface which has received the frame
* @elems: parsed 802.11 elements received with the frame * @elems: parsed 802.11 elements received with the frame
* @beacon: indicates if the frame was a beacon or probe response
* @current_band: indicates the current band * @current_band: indicates the current band
* @sta_flags: contains information about own capabilities and restrictions * @sta_flags: contains information about own capabilities and restrictions
* to decide which channel switch announcements can be accepted. Only the * to decide which channel switch announcements can be accepted. Only the
...@@ -1656,7 +1655,7 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, ...@@ -1656,7 +1655,7 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
* Return: 0 on success, <0 on error and >0 if there is nothing to parse. * Return: 0 on success, <0 on error and >0 if there is nothing to parse.
*/ */
int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
struct ieee802_11_elems *elems, bool beacon, struct ieee802_11_elems *elems,
enum ieee80211_band current_band, enum ieee80211_band current_band,
u32 sta_flags, u8 *bssid, u32 sta_flags, u8 *bssid,
struct ieee80211_csa_ie *csa_ie); struct ieee80211_csa_ie *csa_ie);
......
...@@ -766,10 +766,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ...@@ -766,10 +766,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
int i, flushed; int i, flushed;
struct ps_data *ps; struct ps_data *ps;
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef;
bool cancel_scan;
clear_bit(SDATA_STATE_RUNNING, &sdata->state); clear_bit(SDATA_STATE_RUNNING, &sdata->state);
if (rcu_access_pointer(local->scan_sdata) == sdata) cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata;
if (cancel_scan)
ieee80211_scan_cancel(local); ieee80211_scan_cancel(local);
/* /*
...@@ -898,6 +900,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ...@@ -898,6 +900,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
list_del(&sdata->u.vlan.list); list_del(&sdata->u.vlan.list);
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL); RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL);
/* see comment in the default case below */
ieee80211_free_keys(sdata, true);
/* no need to tell driver */ /* no need to tell driver */
break; break;
case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MONITOR:
...@@ -923,17 +927,16 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ...@@ -923,17 +927,16 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
/* /*
* When we get here, the interface is marked down. * When we get here, the interface is marked down.
* Free the remaining keys, if there are any * Free the remaining keys, if there are any
* (shouldn't be, except maybe in WDS mode?) * (which can happen in AP mode if userspace sets
* keys before the interface is operating, and maybe
* also in WDS mode)
* *
* Force the key freeing to always synchronize_net() * Force the key freeing to always synchronize_net()
* to wait for the RX path in case it is using this * to wait for the RX path in case it is using this
* interface enqueuing frames * at this very time on * interface enqueuing frames at this very time on
* another CPU. * another CPU.
*/ */
ieee80211_free_keys(sdata, true); ieee80211_free_keys(sdata, true);
/* fall through */
case NL80211_IFTYPE_AP:
skb_queue_purge(&sdata->skb_queue); skb_queue_purge(&sdata->skb_queue);
} }
...@@ -991,6 +994,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ...@@ -991,6 +994,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
ieee80211_recalc_ps(local, -1); ieee80211_recalc_ps(local, -1);
if (cancel_scan)
flush_delayed_work(&local->scan_work);
if (local->open_count == 0) { if (local->open_count == 0) {
ieee80211_stop_device(local); ieee80211_stop_device(local);
......
...@@ -874,7 +874,7 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, ...@@ -874,7 +874,7 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
memset(&csa_ie, 0, sizeof(csa_ie)); memset(&csa_ie, 0, sizeof(csa_ie));
err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, band, err = ieee80211_parse_ch_switch_ie(sdata, elems, band,
sta_flags, sdata->vif.addr, sta_flags, sdata->vif.addr,
&csa_ie); &csa_ie);
if (err < 0) if (err < 0)
......
...@@ -1072,7 +1072,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, ...@@ -1072,7 +1072,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
current_band = cbss->channel->band; current_band = cbss->channel->band;
memset(&csa_ie, 0, sizeof(csa_ie)); memset(&csa_ie, 0, sizeof(csa_ie));
res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band, res = ieee80211_parse_ch_switch_ie(sdata, elems, current_band,
ifmgd->flags, ifmgd->flags,
ifmgd->associated->bssid, &csa_ie); ifmgd->associated->bssid, &csa_ie);
if (res < 0) if (res < 0)
...@@ -1168,7 +1168,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, ...@@ -1168,7 +1168,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work); ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work);
else else
mod_timer(&ifmgd->chswitch_timer, mod_timer(&ifmgd->chswitch_timer,
TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval)); TU_TO_EXP_TIME((csa_ie.count - 1) *
cbss->beacon_interval));
} }
static bool static bool
......
...@@ -1678,11 +1678,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) ...@@ -1678,11 +1678,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
sc = le16_to_cpu(hdr->seq_ctrl); sc = le16_to_cpu(hdr->seq_ctrl);
frag = sc & IEEE80211_SCTL_FRAG; frag = sc & IEEE80211_SCTL_FRAG;
if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || if (likely(!ieee80211_has_morefrags(fc) && frag == 0))
is_multicast_ether_addr(hdr->addr1))) { goto out;
/* not fragmented */
if (is_multicast_ether_addr(hdr->addr1)) {
rx->local->dot11MulticastReceivedFrameCount++;
goto out; goto out;
} }
I802_DEBUG_INC(rx->local->rx_handlers_fragments); I802_DEBUG_INC(rx->local->rx_handlers_fragments);
if (skb_linearize(rx->skb)) if (skb_linearize(rx->skb))
...@@ -1775,10 +1778,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) ...@@ -1775,10 +1778,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
out: out:
if (rx->sta) if (rx->sta)
rx->sta->rx_packets++; rx->sta->rx_packets++;
if (is_multicast_ether_addr(hdr->addr1)) ieee80211_led_rx(rx->local);
rx->local->dot11MulticastReceivedFrameCount++;
else
ieee80211_led_rx(rx->local);
return RX_CONTINUE; return RX_CONTINUE;
} }
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include "wme.h" #include "wme.h"
int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
struct ieee802_11_elems *elems, bool beacon, struct ieee802_11_elems *elems,
enum ieee80211_band current_band, enum ieee80211_band current_band,
u32 sta_flags, u8 *bssid, u32 sta_flags, u8 *bssid,
struct ieee80211_csa_ie *csa_ie) struct ieee80211_csa_ie *csa_ie)
...@@ -91,19 +91,13 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, ...@@ -91,19 +91,13 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
return -EINVAL; return -EINVAL;
} }
if (!beacon && sec_chan_offs) { if (sec_chan_offs) {
secondary_channel_offset = sec_chan_offs->sec_chan_offs; secondary_channel_offset = sec_chan_offs->sec_chan_offs;
} else if (beacon && ht_oper) {
secondary_channel_offset =
ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
} else if (!(sta_flags & IEEE80211_STA_DISABLE_HT)) { } else if (!(sta_flags & IEEE80211_STA_DISABLE_HT)) {
/* If it's not a beacon, HT is enabled and the IE not present, /* If the secondary channel offset IE is not present,
* it's 20 MHz, 802.11-2012 8.5.2.6: * we can't know what's the post-CSA offset, so the
* This element [the Secondary Channel Offset Element] is * best we can do is use 20MHz.
* present when switching to a 40 MHz channel. It may be */
* present when switching to a 20 MHz channel (in which
* case the secondary channel offset is set to SCN).
*/
secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
} }
......
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