Commit 30d237a6 authored by David S. Miller's avatar David S. Miller

Merge tag 'mac80211-for-davem-2016-04-06' of...

Merge tag 'mac80211-for-davem-2016-04-06' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211

Johannes Berg says:

====================
For the current RC series, we have the following fixes:
 * TDLS fixes from Arik and Ilan
 * rhashtable fixes from Ben and myself
 * documentation fixes from Luis
 * U-APSD fixes from Emmanuel
 * a TXQ fix from Felix
 * and a compiler warning suppression from Jeff
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3430284f b4201cc4
...@@ -1001,6 +1001,8 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) ...@@ -1001,6 +1001,8 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* flag indicates that the PN was verified for replay protection. * flag indicates that the PN was verified for replay protection.
* Note that this flag is also currently only supported when a frame * Note that this flag is also currently only supported when a frame
* is also decrypted (ie. @RX_FLAG_DECRYPTED must be set) * is also decrypted (ie. @RX_FLAG_DECRYPTED must be set)
* @RX_FLAG_DUP_VALIDATED: The driver should set this flag if it did
* de-duplication by itself.
* @RX_FLAG_FAILED_FCS_CRC: Set this flag if the FCS check failed on * @RX_FLAG_FAILED_FCS_CRC: Set this flag if the FCS check failed on
* the frame. * the frame.
* @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on * @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on
......
...@@ -343,8 +343,10 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local, ...@@ -343,8 +343,10 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local,
struct ieee80211_chanctx *ctx, struct ieee80211_chanctx *ctx,
const struct cfg80211_chan_def *chandef) const struct cfg80211_chan_def *chandef)
{ {
if (cfg80211_chandef_identical(&ctx->conf.def, chandef)) if (cfg80211_chandef_identical(&ctx->conf.def, chandef)) {
ieee80211_recalc_chanctx_min_def(local, ctx);
return; return;
}
WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef)); WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef));
......
...@@ -1719,6 +1719,10 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, ...@@ -1719,6 +1719,10 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta); enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta);
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta); enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta);
void ieee80211_sta_set_rx_nss(struct sta_info *sta); void ieee80211_sta_set_rx_nss(struct sta_info *sta);
enum ieee80211_sta_rx_bandwidth
ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width);
enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct sta_info *sta);
void ieee80211_sta_set_rx_nss(struct sta_info *sta);
void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata, void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt); struct ieee80211_mgmt *mgmt);
u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
......
...@@ -530,7 +530,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, ...@@ -530,7 +530,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
const u8 *target_addr, *orig_addr; const u8 *target_addr, *orig_addr;
const u8 *da; const u8 *da;
u8 target_flags, ttl, flags; u8 target_flags, ttl, flags;
u32 orig_sn, target_sn, lifetime, target_metric; u32 orig_sn, target_sn, lifetime, target_metric = 0;
bool reply = false; bool reply = false;
bool forward = true; bool forward = true;
bool root_is_gate; bool root_is_gate;
......
...@@ -67,6 +67,7 @@ ...@@ -67,6 +67,7 @@
static const struct rhashtable_params sta_rht_params = { static const struct rhashtable_params sta_rht_params = {
.nelem_hint = 3, /* start small */ .nelem_hint = 3, /* start small */
.insecure_elasticity = true, /* Disable chain-length checks. */
.automatic_shrinking = true, .automatic_shrinking = true,
.head_offset = offsetof(struct sta_info, hash_node), .head_offset = offsetof(struct sta_info, hash_node),
.key_offset = offsetof(struct sta_info, addr), .key_offset = offsetof(struct sta_info, addr),
...@@ -258,11 +259,11 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta) ...@@ -258,11 +259,11 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
} }
/* Caller must hold local->sta_mtx */ /* Caller must hold local->sta_mtx */
static void sta_info_hash_add(struct ieee80211_local *local, static int sta_info_hash_add(struct ieee80211_local *local,
struct sta_info *sta) struct sta_info *sta)
{ {
rhashtable_insert_fast(&local->sta_hash, &sta->hash_node, return rhashtable_insert_fast(&local->sta_hash, &sta->hash_node,
sta_rht_params); sta_rht_params);
} }
static void sta_deliver_ps_frames(struct work_struct *wk) static void sta_deliver_ps_frames(struct work_struct *wk)
...@@ -524,7 +525,9 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) ...@@ -524,7 +525,9 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
set_sta_flag(sta, WLAN_STA_BLOCK_BA); set_sta_flag(sta, WLAN_STA_BLOCK_BA);
/* make the station visible */ /* make the station visible */
sta_info_hash_add(local, sta); err = sta_info_hash_add(local, sta);
if (err)
goto out_drop_sta;
list_add_tail_rcu(&sta->list, &local->sta_list); list_add_tail_rcu(&sta->list, &local->sta_list);
...@@ -557,6 +560,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) ...@@ -557,6 +560,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
out_remove: out_remove:
sta_info_hash_del(local, sta); sta_info_hash_del(local, sta);
list_del_rcu(&sta->list); list_del_rcu(&sta->list);
out_drop_sta:
local->num_sta--; local->num_sta--;
synchronize_net(); synchronize_net();
__cleanup_single_sta(sta); __cleanup_single_sta(sta);
......
...@@ -377,7 +377,6 @@ DECLARE_EWMA(signal, 1024, 8) ...@@ -377,7 +377,6 @@ DECLARE_EWMA(signal, 1024, 8)
* @uploaded: set to true when sta is uploaded to the driver * @uploaded: set to true when sta is uploaded to the driver
* @sta: station information we share with the driver * @sta: station information we share with the driver
* @sta_state: duplicates information about station state (for debug) * @sta_state: duplicates information about station state (for debug)
* @beacon_loss_count: number of times beacon loss has triggered
* @rcu_head: RCU head used for freeing this station struct * @rcu_head: RCU head used for freeing this station struct
* @cur_max_bandwidth: maximum bandwidth to use for TX to the station, * @cur_max_bandwidth: maximum bandwidth to use for TX to the station,
* taken from HT/VHT capabilities or VHT operating mode notification * taken from HT/VHT capabilities or VHT operating mode notification
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2014, Intel Corporation * Copyright 2014, Intel Corporation
* Copyright 2014 Intel Mobile Communications GmbH * Copyright 2014 Intel Mobile Communications GmbH
* Copyright 2015 Intel Deutschland GmbH * Copyright 2015 - 2016 Intel Deutschland GmbH
* *
* This file is GPLv2 as found in COPYING. * This file is GPLv2 as found in COPYING.
*/ */
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include "ieee80211_i.h" #include "ieee80211_i.h"
#include "driver-ops.h" #include "driver-ops.h"
#include "rate.h"
/* give usermode some time for retries in setting up the TDLS session */ /* give usermode some time for retries in setting up the TDLS session */
#define TDLS_PEER_SETUP_TIMEOUT (15 * HZ) #define TDLS_PEER_SETUP_TIMEOUT (15 * HZ)
...@@ -302,7 +303,7 @@ ieee80211_tdls_chandef_vht_upgrade(struct ieee80211_sub_if_data *sdata, ...@@ -302,7 +303,7 @@ ieee80211_tdls_chandef_vht_upgrade(struct ieee80211_sub_if_data *sdata,
/* IEEE802.11ac-2013 Table E-4 */ /* IEEE802.11ac-2013 Table E-4 */
u16 centers_80mhz[] = { 5210, 5290, 5530, 5610, 5690, 5775 }; u16 centers_80mhz[] = { 5210, 5290, 5530, 5610, 5690, 5775 };
struct cfg80211_chan_def uc = sta->tdls_chandef; struct cfg80211_chan_def uc = sta->tdls_chandef;
enum nl80211_chan_width max_width = ieee80211_get_sta_bw(&sta->sta); enum nl80211_chan_width max_width = ieee80211_sta_cap_chan_bw(sta);
int i; int i;
/* only support upgrading non-narrow channels up to 80Mhz */ /* only support upgrading non-narrow channels up to 80Mhz */
...@@ -313,7 +314,7 @@ ieee80211_tdls_chandef_vht_upgrade(struct ieee80211_sub_if_data *sdata, ...@@ -313,7 +314,7 @@ ieee80211_tdls_chandef_vht_upgrade(struct ieee80211_sub_if_data *sdata,
if (max_width > NL80211_CHAN_WIDTH_80) if (max_width > NL80211_CHAN_WIDTH_80)
max_width = NL80211_CHAN_WIDTH_80; max_width = NL80211_CHAN_WIDTH_80;
if (uc.width == max_width) if (uc.width >= max_width)
return; return;
/* /*
* Channel usage constrains in the IEEE802.11ac-2013 specification only * Channel usage constrains in the IEEE802.11ac-2013 specification only
...@@ -324,6 +325,7 @@ ieee80211_tdls_chandef_vht_upgrade(struct ieee80211_sub_if_data *sdata, ...@@ -324,6 +325,7 @@ ieee80211_tdls_chandef_vht_upgrade(struct ieee80211_sub_if_data *sdata,
for (i = 0; i < ARRAY_SIZE(centers_80mhz); i++) for (i = 0; i < ARRAY_SIZE(centers_80mhz); i++)
if (abs(uc.chan->center_freq - centers_80mhz[i]) <= 30) { if (abs(uc.chan->center_freq - centers_80mhz[i]) <= 30) {
uc.center_freq1 = centers_80mhz[i]; uc.center_freq1 = centers_80mhz[i];
uc.center_freq2 = 0;
uc.width = NL80211_CHAN_WIDTH_80; uc.width = NL80211_CHAN_WIDTH_80;
break; break;
} }
...@@ -332,7 +334,7 @@ ieee80211_tdls_chandef_vht_upgrade(struct ieee80211_sub_if_data *sdata, ...@@ -332,7 +334,7 @@ ieee80211_tdls_chandef_vht_upgrade(struct ieee80211_sub_if_data *sdata,
return; return;
/* proceed to downgrade the chandef until usable or the same */ /* proceed to downgrade the chandef until usable or the same */
while (uc.width > max_width && while (uc.width > max_width ||
!cfg80211_reg_can_beacon_relax(sdata->local->hw.wiphy, &uc, !cfg80211_reg_can_beacon_relax(sdata->local->hw.wiphy, &uc,
sdata->wdev.iftype)) sdata->wdev.iftype))
ieee80211_chandef_downgrade(&uc); ieee80211_chandef_downgrade(&uc);
...@@ -1242,18 +1244,44 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, ...@@ -1242,18 +1244,44 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
return ret; return ret;
} }
static void iee80211_tdls_recalc_chanctx(struct ieee80211_sub_if_data *sdata) static void iee80211_tdls_recalc_chanctx(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta)
{ {
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct ieee80211_chanctx_conf *conf; struct ieee80211_chanctx_conf *conf;
struct ieee80211_chanctx *ctx; struct ieee80211_chanctx *ctx;
enum nl80211_chan_width width;
struct ieee80211_supported_band *sband;
mutex_lock(&local->chanctx_mtx); mutex_lock(&local->chanctx_mtx);
conf = rcu_dereference_protected(sdata->vif.chanctx_conf, conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
lockdep_is_held(&local->chanctx_mtx)); lockdep_is_held(&local->chanctx_mtx));
if (conf) { if (conf) {
width = conf->def.width;
sband = local->hw.wiphy->bands[conf->def.chan->band];
ctx = container_of(conf, struct ieee80211_chanctx, conf); ctx = container_of(conf, struct ieee80211_chanctx, conf);
ieee80211_recalc_chanctx_chantype(local, ctx); ieee80211_recalc_chanctx_chantype(local, ctx);
/* if width changed and a peer is given, update its BW */
if (width != conf->def.width && sta &&
test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW)) {
enum ieee80211_sta_rx_bandwidth bw;
bw = ieee80211_chan_width_to_rx_bw(conf->def.width);
bw = min(bw, ieee80211_sta_cap_rx_bw(sta));
if (bw != sta->sta.bandwidth) {
sta->sta.bandwidth = bw;
rate_control_rate_update(local, sband, sta,
IEEE80211_RC_BW_CHANGED);
/*
* if a TDLS peer BW was updated, we need to
* recalc the chandef width again, to get the
* correct chanctx min_def
*/
ieee80211_recalc_chanctx_chantype(local, ctx);
}
}
} }
mutex_unlock(&local->chanctx_mtx); mutex_unlock(&local->chanctx_mtx);
} }
...@@ -1350,8 +1378,6 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, ...@@ -1350,8 +1378,6 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
break; break;
} }
iee80211_tdls_recalc_chanctx(sdata);
mutex_lock(&local->sta_mtx); mutex_lock(&local->sta_mtx);
sta = sta_info_get(sdata, peer); sta = sta_info_get(sdata, peer);
if (!sta) { if (!sta) {
...@@ -1360,6 +1386,7 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, ...@@ -1360,6 +1386,7 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
break; break;
} }
iee80211_tdls_recalc_chanctx(sdata, sta);
iee80211_tdls_recalc_ht_protection(sdata, sta); iee80211_tdls_recalc_ht_protection(sdata, sta);
set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH); set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
...@@ -1390,7 +1417,7 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, ...@@ -1390,7 +1417,7 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
iee80211_tdls_recalc_ht_protection(sdata, NULL); iee80211_tdls_recalc_ht_protection(sdata, NULL);
mutex_unlock(&local->sta_mtx); mutex_unlock(&local->sta_mtx);
iee80211_tdls_recalc_chanctx(sdata); iee80211_tdls_recalc_chanctx(sdata, NULL);
break; break;
default: default:
ret = -ENOTSUPP; ret = -ENOTSUPP;
......
...@@ -1116,11 +1116,15 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, ...@@ -1116,11 +1116,15 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
reset_agg_timer = true; reset_agg_timer = true;
} else { } else {
queued = true; queued = true;
if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER) {
clear_sta_flag(tx->sta, WLAN_STA_SP);
ps_dbg(tx->sta->sdata,
"STA %pM aid %d: SP frame queued, close the SP w/o telling the peer\n",
tx->sta->sta.addr, tx->sta->sta.aid);
}
info->control.vif = &tx->sdata->vif; info->control.vif = &tx->sdata->vif;
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS | info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
IEEE80211_TX_CTL_NO_PS_BUFFER |
IEEE80211_TX_STATUS_EOSP;
__skb_queue_tail(&tid_tx->pending, skb); __skb_queue_tail(&tid_tx->pending, skb);
if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER) if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER)
purge_skb = __skb_dequeue(&tid_tx->pending); purge_skb = __skb_dequeue(&tid_tx->pending);
...@@ -1247,7 +1251,8 @@ static void ieee80211_drv_tx(struct ieee80211_local *local, ...@@ -1247,7 +1251,8 @@ static void ieee80211_drv_tx(struct ieee80211_local *local,
struct txq_info *txqi; struct txq_info *txqi;
u8 ac; u8 ac;
if (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE) if ((info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) ||
(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
goto tx_normal; goto tx_normal;
if (!ieee80211_is_data(hdr->frame_control)) if (!ieee80211_is_data(hdr->frame_control))
......
...@@ -319,7 +319,30 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta) ...@@ -319,7 +319,30 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta)
return IEEE80211_STA_RX_BW_80; return IEEE80211_STA_RX_BW_80;
} }
static enum ieee80211_sta_rx_bandwidth enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct sta_info *sta)
{
struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap;
u32 cap_width;
if (!vht_cap->vht_supported) {
if (!sta->sta.ht_cap.ht_supported)
return NL80211_CHAN_WIDTH_20_NOHT;
return sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
NL80211_CHAN_WIDTH_40 : NL80211_CHAN_WIDTH_20;
}
cap_width = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)
return NL80211_CHAN_WIDTH_160;
else if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
return NL80211_CHAN_WIDTH_80P80;
return NL80211_CHAN_WIDTH_80;
}
enum ieee80211_sta_rx_bandwidth
ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width) ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width)
{ {
switch (width) { switch (width) {
...@@ -347,10 +370,7 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta) ...@@ -347,10 +370,7 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta)
bw = ieee80211_sta_cap_rx_bw(sta); bw = ieee80211_sta_cap_rx_bw(sta);
bw = min(bw, sta->cur_max_bandwidth); bw = min(bw, sta->cur_max_bandwidth);
bw = min(bw, ieee80211_chan_width_to_rx_bw(bss_width));
/* do not cap the BW of TDLS WIDER_BW peers by the bss */
if (!test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW))
bw = min(bw, ieee80211_chan_width_to_rx_bw(bss_width));
return bw; return bw;
} }
......
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