Commit 16c54ac9 authored by David S. Miller's avatar David S. Miller

Merge tag 'mac80211-for-davem-2017-02-28' of...

Merge tag 'mac80211-for-davem-2017-02-28' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211

Johannes Berg says:

====================
First round of fixes - details in the commits:
 * use a valid hrtimer clock ID in mac80211_hwsim
 * don't reorder frames prior to BA session
 * flush a delayed work at suspend so the state is all valid before
   suspend/resume
 * fix packet statistics in fast-RX, the RX packets
   counter increment was simply missing
 * don't try to re-transmit filtered frames in an aggregation session
 * shorten (for tracing) a debug message
 * typo fix in another debug message
 * fix nul-termination with HWSIM_ATTR_RADIO_NAME in hwsim
 * fix mgmt RX processing when station is looked up by driver/device
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 449809a6 19d19e96
...@@ -3056,6 +3056,7 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2, ...@@ -3056,6 +3056,7 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2,
static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
{ {
struct hwsim_new_radio_params param = { 0 }; struct hwsim_new_radio_params param = { 0 };
const char *hwname = NULL;
param.reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; param.reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG];
param.p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE]; param.p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE];
...@@ -3069,8 +3070,14 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) ...@@ -3069,8 +3070,14 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
if (info->attrs[HWSIM_ATTR_NO_VIF]) if (info->attrs[HWSIM_ATTR_NO_VIF])
param.no_vif = true; param.no_vif = true;
if (info->attrs[HWSIM_ATTR_RADIO_NAME]) if (info->attrs[HWSIM_ATTR_RADIO_NAME]) {
param.hwname = nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]); hwname = kasprintf(GFP_KERNEL, "%.*s",
nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]),
(char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]));
if (!hwname)
return -ENOMEM;
param.hwname = hwname;
}
if (info->attrs[HWSIM_ATTR_USE_CHANCTX]) if (info->attrs[HWSIM_ATTR_USE_CHANCTX])
param.use_chanctx = true; param.use_chanctx = true;
...@@ -3098,11 +3105,15 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) ...@@ -3098,11 +3105,15 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info)
s64 idx = -1; s64 idx = -1;
const char *hwname = NULL; const char *hwname = NULL;
if (info->attrs[HWSIM_ATTR_RADIO_ID]) if (info->attrs[HWSIM_ATTR_RADIO_ID]) {
idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]); idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]);
else if (info->attrs[HWSIM_ATTR_RADIO_NAME]) } else if (info->attrs[HWSIM_ATTR_RADIO_NAME]) {
hwname = (void *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]); hwname = kasprintf(GFP_KERNEL, "%.*s",
else nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]),
(char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]));
if (!hwname)
return -ENOMEM;
} else
return -EINVAL; return -EINVAL;
spin_lock_bh(&hwsim_radio_lock); spin_lock_bh(&hwsim_radio_lock);
...@@ -3111,7 +3122,8 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) ...@@ -3111,7 +3122,8 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info)
if (data->idx != idx) if (data->idx != idx)
continue; continue;
} else { } else {
if (strcmp(hwname, wiphy_name(data->hw->wiphy))) if (!hwname ||
strcmp(hwname, wiphy_name(data->hw->wiphy)))
continue; continue;
} }
...@@ -3122,10 +3134,12 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) ...@@ -3122,10 +3134,12 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info)
spin_unlock_bh(&hwsim_radio_lock); spin_unlock_bh(&hwsim_radio_lock);
mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy),
info); info);
kfree(hwname);
return 0; return 0;
} }
spin_unlock_bh(&hwsim_radio_lock); spin_unlock_bh(&hwsim_radio_lock);
kfree(hwname);
return -ENODEV; return -ENODEV;
} }
......
...@@ -85,7 +85,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, ...@@ -85,7 +85,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
ht_dbg(sta->sdata, ht_dbg(sta->sdata,
"Rx BA session stop requested for %pM tid %u %s reason: %d\n", "Rx BA session stop requested for %pM tid %u %s reason: %d\n",
sta->sta.addr, tid, sta->sta.addr, tid,
initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator", initiator == WLAN_BACK_RECIPIENT ? "recipient" : "initiator",
(int)reason); (int)reason);
if (drv_ampdu_action(local, sta->sdata, &params)) if (drv_ampdu_action(local, sta->sdata, &params))
...@@ -398,6 +398,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, ...@@ -398,6 +398,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
tid_agg_rx->timeout = timeout; tid_agg_rx->timeout = timeout;
tid_agg_rx->stored_mpdu_num = 0; tid_agg_rx->stored_mpdu_num = 0;
tid_agg_rx->auto_seq = auto_seq; tid_agg_rx->auto_seq = auto_seq;
tid_agg_rx->started = false;
tid_agg_rx->reorder_buf_filtered = 0; tid_agg_rx->reorder_buf_filtered = 0;
status = WLAN_STATUS_SUCCESS; status = WLAN_STATUS_SUCCESS;
......
...@@ -168,6 +168,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) ...@@ -168,6 +168,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
break; break;
} }
flush_delayed_work(&sdata->dec_tailroom_needed_wk);
drv_remove_interface(local, sdata); drv_remove_interface(local, sdata);
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net> * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
...@@ -1034,6 +1034,18 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata ...@@ -1034,6 +1034,18 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
buf_size = tid_agg_rx->buf_size; buf_size = tid_agg_rx->buf_size;
head_seq_num = tid_agg_rx->head_seq_num; head_seq_num = tid_agg_rx->head_seq_num;
/*
* If the current MPDU's SN is smaller than the SSN, it shouldn't
* be reordered.
*/
if (unlikely(!tid_agg_rx->started)) {
if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
ret = false;
goto out;
}
tid_agg_rx->started = true;
}
/* frame with out of date sequence number */ /* frame with out of date sequence number */
if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) { if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
dev_kfree_skb(skb); dev_kfree_skb(skb);
...@@ -3880,6 +3892,7 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, ...@@ -3880,6 +3892,7 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
stats->last_rate = sta_stats_encode_rate(status); stats->last_rate = sta_stats_encode_rate(status);
stats->fragments++; stats->fragments++;
stats->packets++;
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
stats->last_signal = status->signal; stats->last_signal = status->signal;
...@@ -4073,15 +4086,17 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, ...@@ -4073,15 +4086,17 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
ieee80211_is_beacon(hdr->frame_control))) ieee80211_is_beacon(hdr->frame_control)))
ieee80211_scan_rx(local, skb); ieee80211_scan_rx(local, skb);
if (pubsta) { if (ieee80211_is_data(fc)) {
rx.sta = container_of(pubsta, struct sta_info, sta);
rx.sdata = rx.sta->sdata;
if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
return;
goto out;
} else if (ieee80211_is_data(fc)) {
struct sta_info *sta, *prev_sta; struct sta_info *sta, *prev_sta;
if (pubsta) {
rx.sta = container_of(pubsta, struct sta_info, sta);
rx.sdata = rx.sta->sdata;
if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
return;
goto out;
}
prev_sta = NULL; prev_sta = NULL;
for_each_sta_info(local, hdr->addr2, sta, tmp) { for_each_sta_info(local, hdr->addr2, sta, tmp) {
......
...@@ -688,7 +688,7 @@ static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending) ...@@ -688,7 +688,7 @@ static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending)
} }
/* No need to do anything if the driver does all */ /* No need to do anything if the driver does all */
if (ieee80211_hw_check(&local->hw, AP_LINK_PS)) if (ieee80211_hw_check(&local->hw, AP_LINK_PS) && !local->ops->set_tim)
return; return;
if (sta->dead) if (sta->dead)
...@@ -1264,7 +1264,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) ...@@ -1264,7 +1264,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
sta_info_recalc_tim(sta); sta_info_recalc_tim(sta);
ps_dbg(sdata, ps_dbg(sdata,
"STA %pM aid %d sending %d filtered/%d PS frames since STA not sleeping anymore\n", "STA %pM aid %d sending %d filtered/%d PS frames since STA woke up\n",
sta->sta.addr, sta->sta.aid, filtered, buffered); sta->sta.addr, sta->sta.aid, filtered, buffered);
ieee80211_check_fast_xmit(sta); ieee80211_check_fast_xmit(sta);
......
...@@ -189,6 +189,7 @@ struct tid_ampdu_tx { ...@@ -189,6 +189,7 @@ struct tid_ampdu_tx {
* @auto_seq: used for offloaded BA sessions to automatically pick head_seq_and * @auto_seq: used for offloaded BA sessions to automatically pick head_seq_and
* and ssn. * and ssn.
* @removed: this session is removed (but might have been found due to RCU) * @removed: this session is removed (but might have been found due to RCU)
* @started: this session has started (head ssn or higher was received)
* *
* This structure's lifetime is managed by RCU, assignments to * This structure's lifetime is managed by RCU, assignments to
* the array holding it must hold the aggregation mutex. * the array holding it must hold the aggregation mutex.
...@@ -212,8 +213,9 @@ struct tid_ampdu_rx { ...@@ -212,8 +213,9 @@ struct tid_ampdu_rx {
u16 ssn; u16 ssn;
u16 buf_size; u16 buf_size;
u16 timeout; u16 timeout;
bool auto_seq; u8 auto_seq:1,
bool removed; removed:1,
started:1;
}; };
/** /**
......
...@@ -51,7 +51,8 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, ...@@ -51,7 +51,8 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
struct ieee80211_hdr *hdr = (void *)skb->data; struct ieee80211_hdr *hdr = (void *)skb->data;
int ac; int ac;
if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER) { if (info->flags & (IEEE80211_TX_CTL_NO_PS_BUFFER |
IEEE80211_TX_CTL_AMPDU)) {
ieee80211_free_txskb(&local->hw, skb); ieee80211_free_txskb(&local->hw, skb);
return; return;
} }
......
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