You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
This commit is contained in:
@@ -1001,6 +1001,26 @@ struct ieee80211_vendor_ie {
|
||||
u8 oui_type;
|
||||
} __packed;
|
||||
|
||||
struct ieee80211_wmm_ac_param {
|
||||
u8 aci_aifsn; /* AIFSN, ACM, ACI */
|
||||
u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */
|
||||
__le16 txop_limit;
|
||||
} __packed;
|
||||
|
||||
struct ieee80211_wmm_param_ie {
|
||||
u8 element_id; /* Element ID: 221 (0xdd); */
|
||||
u8 len; /* Length: 24 */
|
||||
/* required fields for WMM version 1 */
|
||||
u8 oui[3]; /* 00:50:f2 */
|
||||
u8 oui_type; /* 2 */
|
||||
u8 oui_subtype; /* 1 */
|
||||
u8 version; /* 1 for WMM version 1.0 */
|
||||
u8 qos_info; /* AP/STA specific QoS info */
|
||||
u8 reserved; /* 0 */
|
||||
/* AC_BE, AC_BK, AC_VI, AC_VO */
|
||||
struct ieee80211_wmm_ac_param ac[4];
|
||||
} __packed;
|
||||
|
||||
/* Control frames */
|
||||
struct ieee80211_rts {
|
||||
__le16 frame_control;
|
||||
|
||||
@@ -4552,6 +4552,40 @@ void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
|
||||
*/
|
||||
void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
|
||||
|
||||
/**
|
||||
* ieee80211_start_rx_ba_session_offl - start a Rx BA session
|
||||
*
|
||||
* Some device drivers may offload part of the Rx aggregation flow including
|
||||
* AddBa/DelBa negotiation but may otherwise be incapable of full Rx
|
||||
* reordering.
|
||||
*
|
||||
* Create structures responsible for reordering so device drivers may call here
|
||||
* when they complete AddBa negotiation.
|
||||
*
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback
|
||||
* @addr: station mac address
|
||||
* @tid: the rx tid
|
||||
*/
|
||||
void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
|
||||
const u8 *addr, u16 tid);
|
||||
|
||||
/**
|
||||
* ieee80211_stop_rx_ba_session_offl - stop a Rx BA session
|
||||
*
|
||||
* Some device drivers may offload part of the Rx aggregation flow including
|
||||
* AddBa/DelBa negotiation but may otherwise be incapable of full Rx
|
||||
* reordering.
|
||||
*
|
||||
* Destroy structures responsible for reordering so device drivers may call here
|
||||
* when they complete DelBa negotiation.
|
||||
*
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback
|
||||
* @addr: station mac address
|
||||
* @tid: the rx tid
|
||||
*/
|
||||
void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
|
||||
const u8 *addr, u16 tid);
|
||||
|
||||
/* Rate control API */
|
||||
|
||||
/**
|
||||
|
||||
+84
-26
@@ -52,7 +52,7 @@ static void ieee80211_free_tid_rx(struct rcu_head *h)
|
||||
del_timer_sync(&tid_rx->reorder_timer);
|
||||
|
||||
for (i = 0; i < tid_rx->buf_size; i++)
|
||||
dev_kfree_skb(tid_rx->reorder_buf[i]);
|
||||
__skb_queue_purge(&tid_rx->reorder_buf[i]);
|
||||
kfree(tid_rx->reorder_buf);
|
||||
kfree(tid_rx->reorder_time);
|
||||
kfree(tid_rx);
|
||||
@@ -224,28 +224,15 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
|
||||
ieee80211_tx_skb(sdata, skb);
|
||||
}
|
||||
|
||||
void ieee80211_process_addba_request(struct ieee80211_local *local,
|
||||
struct sta_info *sta,
|
||||
struct ieee80211_mgmt *mgmt,
|
||||
size_t len)
|
||||
void __ieee80211_start_rx_ba_session(struct sta_info *sta,
|
||||
u8 dialog_token, u16 timeout,
|
||||
u16 start_seq_num, u16 ba_policy, u16 tid,
|
||||
u16 buf_size, bool tx)
|
||||
{
|
||||
struct ieee80211_local *local = sta->sdata->local;
|
||||
struct tid_ampdu_rx *tid_agg_rx;
|
||||
u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status;
|
||||
u8 dialog_token;
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
/* extract session parameters from addba request frame */
|
||||
dialog_token = mgmt->u.action.u.addba_req.dialog_token;
|
||||
timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
|
||||
start_seq_num =
|
||||
le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
|
||||
|
||||
capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
|
||||
ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
|
||||
tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
|
||||
buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
|
||||
|
||||
status = WLAN_STATUS_REQUEST_DECLINED;
|
||||
int i, ret = -EOPNOTSUPP;
|
||||
u16 status = WLAN_STATUS_REQUEST_DECLINED;
|
||||
|
||||
if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
|
||||
ht_dbg(sta->sdata,
|
||||
@@ -264,7 +251,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
|
||||
status = WLAN_STATUS_INVALID_QOS_PARAM;
|
||||
ht_dbg_ratelimited(sta->sdata,
|
||||
"AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n",
|
||||
mgmt->sa, tid, ba_policy, buf_size);
|
||||
sta->sta.addr, tid, ba_policy, buf_size);
|
||||
goto end_no_lock;
|
||||
}
|
||||
/* determine default buffer size */
|
||||
@@ -281,7 +268,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
|
||||
if (sta->ampdu_mlme.tid_rx[tid]) {
|
||||
ht_dbg_ratelimited(sta->sdata,
|
||||
"unexpected AddBA Req from %pM on tid %u\n",
|
||||
mgmt->sa, tid);
|
||||
sta->sta.addr, tid);
|
||||
|
||||
/* delete existing Rx BA session on the same tid */
|
||||
___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
|
||||
@@ -308,7 +295,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
|
||||
|
||||
/* prepare reordering buffer */
|
||||
tid_agg_rx->reorder_buf =
|
||||
kcalloc(buf_size, sizeof(struct sk_buff *), GFP_KERNEL);
|
||||
kcalloc(buf_size, sizeof(struct sk_buff_head), GFP_KERNEL);
|
||||
tid_agg_rx->reorder_time =
|
||||
kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL);
|
||||
if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) {
|
||||
@@ -318,6 +305,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (i = 0; i < buf_size; i++)
|
||||
__skb_queue_head_init(&tid_agg_rx->reorder_buf[i]);
|
||||
|
||||
ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START,
|
||||
&sta->sta, tid, &start_seq_num, 0);
|
||||
ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n",
|
||||
@@ -350,6 +340,74 @@ end:
|
||||
mutex_unlock(&sta->ampdu_mlme.mtx);
|
||||
|
||||
end_no_lock:
|
||||
ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid,
|
||||
dialog_token, status, 1, buf_size, timeout);
|
||||
if (tx)
|
||||
ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid,
|
||||
dialog_token, status, 1, buf_size,
|
||||
timeout);
|
||||
}
|
||||
|
||||
void ieee80211_process_addba_request(struct ieee80211_local *local,
|
||||
struct sta_info *sta,
|
||||
struct ieee80211_mgmt *mgmt,
|
||||
size_t len)
|
||||
{
|
||||
u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num;
|
||||
u8 dialog_token;
|
||||
|
||||
/* extract session parameters from addba request frame */
|
||||
dialog_token = mgmt->u.action.u.addba_req.dialog_token;
|
||||
timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
|
||||
start_seq_num =
|
||||
le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
|
||||
|
||||
capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
|
||||
ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
|
||||
tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
|
||||
buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
|
||||
|
||||
__ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
|
||||
start_seq_num, ba_policy, tid,
|
||||
buf_size, true);
|
||||
}
|
||||
|
||||
void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
|
||||
const u8 *addr, u16 tid)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_rx_agg *rx_agg;
|
||||
struct sk_buff *skb = dev_alloc_skb(0);
|
||||
|
||||
if (unlikely(!skb))
|
||||
return;
|
||||
|
||||
rx_agg = (struct ieee80211_rx_agg *) &skb->cb;
|
||||
memcpy(&rx_agg->addr, addr, ETH_ALEN);
|
||||
rx_agg->tid = tid;
|
||||
|
||||
skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_START;
|
||||
skb_queue_tail(&sdata->skb_queue, skb);
|
||||
ieee80211_queue_work(&local->hw, &sdata->work);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_start_rx_ba_session_offl);
|
||||
|
||||
void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
|
||||
const u8 *addr, u16 tid)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_rx_agg *rx_agg;
|
||||
struct sk_buff *skb = dev_alloc_skb(0);
|
||||
|
||||
if (unlikely(!skb))
|
||||
return;
|
||||
|
||||
rx_agg = (struct ieee80211_rx_agg *) &skb->cb;
|
||||
memcpy(&rx_agg->addr, addr, ETH_ALEN);
|
||||
rx_agg->tid = tid;
|
||||
|
||||
skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_STOP;
|
||||
skb_queue_tail(&sdata->skb_queue, skb);
|
||||
ieee80211_queue_work(&local->hw, &sdata->work);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_stop_rx_ba_session_offl);
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local)
|
||||
static struct ieee80211_chanctx *
|
||||
ieee80211_vif_get_chanctx(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_local *local __maybe_unused = sdata->local;
|
||||
struct ieee80211_chanctx_conf *conf;
|
||||
|
||||
conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
|
||||
|
||||
+6
-4
@@ -150,13 +150,12 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
/*
|
||||
* If user has specified capability over-rides, take care
|
||||
* of that if the station we're setting up is the AP that
|
||||
* of that if the station we're setting up is the AP or TDLS peer that
|
||||
* we advertised a restricted capability set to. Override
|
||||
* our own capabilities and then use those below.
|
||||
*/
|
||||
if ((sdata->vif.type == NL80211_IFTYPE_STATION ||
|
||||
sdata->vif.type == NL80211_IFTYPE_ADHOC) &&
|
||||
!test_sta_flag(sta, WLAN_STA_TDLS_PEER))
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION ||
|
||||
sdata->vif.type == NL80211_IFTYPE_ADHOC)
|
||||
ieee80211_apply_htcap_overrides(sdata, &own_cap);
|
||||
|
||||
/*
|
||||
@@ -228,6 +227,9 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
|
||||
if (own_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1)
|
||||
ht_cap.mcs.rx_mask[32/8] |= 1;
|
||||
|
||||
/* set Rx highest rate */
|
||||
ht_cap.mcs.rx_highest = ht_cap_ie->mcs.rx_highest;
|
||||
|
||||
apply:
|
||||
changed = memcmp(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap));
|
||||
|
||||
|
||||
+2
-11
@@ -189,17 +189,8 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata,
|
||||
chandef, 0);
|
||||
}
|
||||
|
||||
if (local->hw.queues >= IEEE80211_NUM_ACS) {
|
||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*pos++ = 7; /* len */
|
||||
*pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
|
||||
*pos++ = 0x50;
|
||||
*pos++ = 0xf2;
|
||||
*pos++ = 2; /* WME */
|
||||
*pos++ = 0; /* WME info */
|
||||
*pos++ = 1; /* WME ver */
|
||||
*pos++ = 0; /* U-APSD no in use */
|
||||
}
|
||||
if (local->hw.queues >= IEEE80211_NUM_ACS)
|
||||
pos = ieee80211_add_wmm_info_ie(pos, 0); /* U-APSD not in use */
|
||||
|
||||
presp->head_len = pos - presp->head;
|
||||
if (WARN_ON(presp->head_len > frame_len))
|
||||
|
||||
@@ -345,7 +345,6 @@ enum ieee80211_sta_flags {
|
||||
IEEE80211_STA_CONNECTION_POLL = BIT(1),
|
||||
IEEE80211_STA_CONTROL_PORT = BIT(2),
|
||||
IEEE80211_STA_DISABLE_HT = BIT(4),
|
||||
IEEE80211_STA_CSA_RECEIVED = BIT(5),
|
||||
IEEE80211_STA_MFP_ENABLED = BIT(6),
|
||||
IEEE80211_STA_UAPSD_ENABLED = BIT(7),
|
||||
IEEE80211_STA_NULLFUNC_ACKED = BIT(8),
|
||||
@@ -503,6 +502,9 @@ struct ieee80211_if_managed {
|
||||
struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */
|
||||
struct ieee80211_vht_cap vht_capa; /* configured VHT overrides */
|
||||
struct ieee80211_vht_cap vht_capa_mask; /* Valid parts of vht_capa */
|
||||
|
||||
u8 tdls_peer[ETH_ALEN] __aligned(2);
|
||||
struct delayed_work tdls_peer_del_work;
|
||||
};
|
||||
|
||||
struct ieee80211_if_ibss {
|
||||
@@ -815,9 +817,6 @@ struct ieee80211_sub_if_data {
|
||||
bool radar_required;
|
||||
struct delayed_work dfs_cac_timer_work;
|
||||
|
||||
u8 tdls_peer[ETH_ALEN] __aligned(2);
|
||||
struct delayed_work tdls_peer_del_work;
|
||||
|
||||
/*
|
||||
* AP this belongs to: self in AP mode and
|
||||
* corresponding AP in VLAN mode, NULL for
|
||||
@@ -926,10 +925,17 @@ ieee80211_vif_get_shift(struct ieee80211_vif *vif)
|
||||
return shift;
|
||||
}
|
||||
|
||||
struct ieee80211_rx_agg {
|
||||
u8 addr[ETH_ALEN];
|
||||
u16 tid;
|
||||
};
|
||||
|
||||
enum sdata_queue_type {
|
||||
IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0,
|
||||
IEEE80211_SDATA_QUEUE_AGG_START = 1,
|
||||
IEEE80211_SDATA_QUEUE_AGG_STOP = 2,
|
||||
IEEE80211_SDATA_QUEUE_RX_AGG_START = 3,
|
||||
IEEE80211_SDATA_QUEUE_RX_AGG_STOP = 4,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -1578,6 +1584,10 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
|
||||
u16 initiator, u16 reason, bool stop);
|
||||
void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
|
||||
u16 initiator, u16 reason, bool stop);
|
||||
void __ieee80211_start_rx_ba_session(struct sta_info *sta,
|
||||
u8 dialog_token, u16 timeout,
|
||||
u16 start_seq_num, u16 ba_policy, u16 tid,
|
||||
u16 buf_size, bool tx);
|
||||
void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
|
||||
enum ieee80211_agg_stop_reason reason);
|
||||
void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
|
||||
@@ -1730,6 +1740,21 @@ static inline void ieee802_11_parse_elems(const u8 *start, size_t len,
|
||||
ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
|
||||
}
|
||||
|
||||
static inline bool ieee80211_rx_reorder_ready(struct sk_buff_head *frames)
|
||||
{
|
||||
struct sk_buff *tail = skb_peek_tail(frames);
|
||||
struct ieee80211_rx_status *status;
|
||||
|
||||
if (!tail)
|
||||
return false;
|
||||
|
||||
status = IEEE80211_SKB_RXCB(tail);
|
||||
if (status->flag & RX_FLAG_AMSDU_MORE)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ieee80211_dynamic_ps_enable_work(struct work_struct *work);
|
||||
void ieee80211_dynamic_ps_disable_work(struct work_struct *work);
|
||||
void ieee80211_dynamic_ps_timer(unsigned long data);
|
||||
@@ -1824,6 +1849,7 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
|
||||
int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
|
||||
struct sk_buff *skb, bool need_basic,
|
||||
enum ieee80211_band band);
|
||||
u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo);
|
||||
|
||||
/* channel management */
|
||||
void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
|
||||
|
||||
+29
-2
@@ -1140,6 +1140,7 @@ static void ieee80211_iface_work(struct work_struct *work)
|
||||
struct sk_buff *skb;
|
||||
struct sta_info *sta;
|
||||
struct ieee80211_ra_tid *ra_tid;
|
||||
struct ieee80211_rx_agg *rx_agg;
|
||||
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
return;
|
||||
@@ -1167,6 +1168,34 @@ static void ieee80211_iface_work(struct work_struct *work)
|
||||
ra_tid = (void *)&skb->cb;
|
||||
ieee80211_stop_tx_ba_cb(&sdata->vif, ra_tid->ra,
|
||||
ra_tid->tid);
|
||||
} else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) {
|
||||
rx_agg = (void *)&skb->cb;
|
||||
mutex_lock(&local->sta_mtx);
|
||||
sta = sta_info_get_bss(sdata, rx_agg->addr);
|
||||
if (sta) {
|
||||
u16 last_seq;
|
||||
|
||||
last_seq = le16_to_cpu(
|
||||
sta->last_seq_ctrl[rx_agg->tid]);
|
||||
|
||||
__ieee80211_start_rx_ba_session(sta,
|
||||
0, 0,
|
||||
ieee80211_sn_inc(last_seq),
|
||||
1, rx_agg->tid,
|
||||
IEEE80211_MAX_AMPDU_BUF,
|
||||
false);
|
||||
}
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
} else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_STOP) {
|
||||
rx_agg = (void *)&skb->cb;
|
||||
mutex_lock(&local->sta_mtx);
|
||||
sta = sta_info_get_bss(sdata, rx_agg->addr);
|
||||
if (sta)
|
||||
__ieee80211_stop_rx_ba_session(sta,
|
||||
rx_agg->tid,
|
||||
WLAN_BACK_RECIPIENT, 0,
|
||||
false);
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
} else if (ieee80211_is_action(mgmt->frame_control) &&
|
||||
mgmt->u.action.category == WLAN_CATEGORY_BACK) {
|
||||
int len = skb->len;
|
||||
@@ -1672,8 +1701,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
|
||||
ieee80211_dfs_cac_timer_work);
|
||||
INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk,
|
||||
ieee80211_delayed_tailroom_dec);
|
||||
INIT_DELAYED_WORK(&sdata->tdls_peer_del_work,
|
||||
ieee80211_tdls_peer_del_work);
|
||||
|
||||
for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
||||
@@ -482,9 +482,6 @@ int ieee80211_key_link(struct ieee80211_key *key,
|
||||
int idx, ret;
|
||||
bool pairwise;
|
||||
|
||||
if (WARN_ON(!sdata || !key))
|
||||
return -EINVAL;
|
||||
|
||||
pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
|
||||
idx = key->conf.keyidx;
|
||||
key->local = sdata->local;
|
||||
|
||||
+5
-17
@@ -830,16 +830,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
|
||||
qos_info = 0;
|
||||
}
|
||||
|
||||
pos = skb_put(skb, 9);
|
||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*pos++ = 7; /* len */
|
||||
*pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
|
||||
*pos++ = 0x50;
|
||||
*pos++ = 0xf2;
|
||||
*pos++ = 2; /* WME */
|
||||
*pos++ = 0; /* WME info */
|
||||
*pos++ = 1; /* WME ver */
|
||||
*pos++ = qos_info;
|
||||
pos = ieee80211_add_wmm_info_ie(skb_put(skb, 9), qos_info);
|
||||
}
|
||||
|
||||
/* add any remaining custom (i.e. vendor specific here) IEs */
|
||||
@@ -1005,8 +996,6 @@ static void ieee80211_chswitch_work(struct work_struct *work)
|
||||
sdata->csa_block_tx = false;
|
||||
}
|
||||
|
||||
ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
|
||||
|
||||
ieee80211_sta_reset_beacon_monitor(sdata);
|
||||
ieee80211_sta_reset_conn_monitor(sdata);
|
||||
|
||||
@@ -1064,7 +1053,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||
return;
|
||||
|
||||
/* disregard subsequent announcements if we are already processing */
|
||||
if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED)
|
||||
if (sdata->vif.csa_active)
|
||||
return;
|
||||
|
||||
current_band = cbss->channel->band;
|
||||
@@ -1091,8 +1080,6 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||
return;
|
||||
}
|
||||
|
||||
ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
|
||||
|
||||
mutex_lock(&local->mtx);
|
||||
mutex_lock(&local->chanctx_mtx);
|
||||
conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
|
||||
@@ -2108,8 +2095,6 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
|
||||
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
|
||||
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
|
||||
true, frame_buf);
|
||||
ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
|
||||
|
||||
mutex_lock(&local->mtx);
|
||||
sdata->vif.csa_active = false;
|
||||
if (sdata->csa_block_tx) {
|
||||
@@ -3722,6 +3707,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
|
||||
INIT_WORK(&ifmgd->csa_connection_drop_work,
|
||||
ieee80211_csa_connection_drop_work);
|
||||
INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_mgd_work);
|
||||
INIT_DELAYED_WORK(&ifmgd->tdls_peer_del_work,
|
||||
ieee80211_tdls_peer_del_work);
|
||||
setup_timer(&ifmgd->timer, ieee80211_sta_timer,
|
||||
(unsigned long) sdata);
|
||||
setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer,
|
||||
@@ -4585,6 +4572,7 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
|
||||
cancel_work_sync(&ifmgd->request_smps_work);
|
||||
cancel_work_sync(&ifmgd->csa_connection_drop_work);
|
||||
cancel_work_sync(&ifmgd->chswitch_work);
|
||||
cancel_delayed_work_sync(&ifmgd->tdls_peer_del_work);
|
||||
|
||||
sdata_lock(sdata);
|
||||
if (ifmgd->assoc_data) {
|
||||
|
||||
+46
-19
@@ -688,20 +688,27 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,
|
||||
int index,
|
||||
struct sk_buff_head *frames)
|
||||
{
|
||||
struct sk_buff *skb = tid_agg_rx->reorder_buf[index];
|
||||
struct sk_buff_head *skb_list = &tid_agg_rx->reorder_buf[index];
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_rx_status *status;
|
||||
|
||||
lockdep_assert_held(&tid_agg_rx->reorder_lock);
|
||||
|
||||
if (!skb)
|
||||
if (skb_queue_empty(skb_list))
|
||||
goto no_frame;
|
||||
|
||||
/* release the frame from the reorder ring buffer */
|
||||
if (!ieee80211_rx_reorder_ready(skb_list)) {
|
||||
__skb_queue_purge(skb_list);
|
||||
goto no_frame;
|
||||
}
|
||||
|
||||
/* release frames from the reorder ring buffer */
|
||||
tid_agg_rx->stored_mpdu_num--;
|
||||
tid_agg_rx->reorder_buf[index] = NULL;
|
||||
status = IEEE80211_SKB_RXCB(skb);
|
||||
status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE;
|
||||
__skb_queue_tail(frames, skb);
|
||||
while ((skb = __skb_dequeue(skb_list))) {
|
||||
status = IEEE80211_SKB_RXCB(skb);
|
||||
status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE;
|
||||
__skb_queue_tail(frames, skb);
|
||||
}
|
||||
|
||||
no_frame:
|
||||
tid_agg_rx->head_seq_num = ieee80211_sn_inc(tid_agg_rx->head_seq_num);
|
||||
@@ -738,13 +745,13 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
|
||||
struct tid_ampdu_rx *tid_agg_rx,
|
||||
struct sk_buff_head *frames)
|
||||
{
|
||||
int index, j;
|
||||
int index, i, j;
|
||||
|
||||
lockdep_assert_held(&tid_agg_rx->reorder_lock);
|
||||
|
||||
/* release the buffer until next missing frame */
|
||||
index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
|
||||
if (!tid_agg_rx->reorder_buf[index] &&
|
||||
if (!ieee80211_rx_reorder_ready(&tid_agg_rx->reorder_buf[index]) &&
|
||||
tid_agg_rx->stored_mpdu_num) {
|
||||
/*
|
||||
* No buffers ready to be released, but check whether any
|
||||
@@ -753,7 +760,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
|
||||
int skipped = 1;
|
||||
for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
|
||||
j = (j + 1) % tid_agg_rx->buf_size) {
|
||||
if (!tid_agg_rx->reorder_buf[j]) {
|
||||
if (!ieee80211_rx_reorder_ready(
|
||||
&tid_agg_rx->reorder_buf[j])) {
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
@@ -762,6 +770,11 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
|
||||
HT_RX_REORDER_BUF_TIMEOUT))
|
||||
goto set_release_timer;
|
||||
|
||||
/* don't leave incomplete A-MSDUs around */
|
||||
for (i = (index + 1) % tid_agg_rx->buf_size; i != j;
|
||||
i = (i + 1) % tid_agg_rx->buf_size)
|
||||
__skb_queue_purge(&tid_agg_rx->reorder_buf[i]);
|
||||
|
||||
ht_dbg_ratelimited(sdata,
|
||||
"release an RX reorder frame due to timeout on earlier frames\n");
|
||||
ieee80211_release_reorder_frame(sdata, tid_agg_rx, j,
|
||||
@@ -775,7 +788,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
|
||||
skipped) & IEEE80211_SN_MASK;
|
||||
skipped = 0;
|
||||
}
|
||||
} else while (tid_agg_rx->reorder_buf[index]) {
|
||||
} else while (ieee80211_rx_reorder_ready(
|
||||
&tid_agg_rx->reorder_buf[index])) {
|
||||
ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,
|
||||
frames);
|
||||
index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
|
||||
@@ -786,7 +800,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
for (; j != (index - 1) % tid_agg_rx->buf_size;
|
||||
j = (j + 1) % tid_agg_rx->buf_size) {
|
||||
if (tid_agg_rx->reorder_buf[j])
|
||||
if (ieee80211_rx_reorder_ready(
|
||||
&tid_agg_rx->reorder_buf[j]))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -811,6 +826,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
|
||||
struct sk_buff_head *frames)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
u16 sc = le16_to_cpu(hdr->seq_ctrl);
|
||||
u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
|
||||
u16 head_seq_num, buf_size;
|
||||
@@ -845,7 +861,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
|
||||
index = mpdu_seq_num % tid_agg_rx->buf_size;
|
||||
|
||||
/* check if we already stored this frame */
|
||||
if (tid_agg_rx->reorder_buf[index]) {
|
||||
if (ieee80211_rx_reorder_ready(&tid_agg_rx->reorder_buf[index])) {
|
||||
dev_kfree_skb(skb);
|
||||
goto out;
|
||||
}
|
||||
@@ -858,17 +874,20 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
|
||||
*/
|
||||
if (mpdu_seq_num == tid_agg_rx->head_seq_num &&
|
||||
tid_agg_rx->stored_mpdu_num == 0) {
|
||||
tid_agg_rx->head_seq_num =
|
||||
ieee80211_sn_inc(tid_agg_rx->head_seq_num);
|
||||
if (!(status->flag & RX_FLAG_AMSDU_MORE))
|
||||
tid_agg_rx->head_seq_num =
|
||||
ieee80211_sn_inc(tid_agg_rx->head_seq_num);
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* put the frame in the reordering buffer */
|
||||
tid_agg_rx->reorder_buf[index] = skb;
|
||||
tid_agg_rx->reorder_time[index] = jiffies;
|
||||
tid_agg_rx->stored_mpdu_num++;
|
||||
ieee80211_sta_reorder_release(sdata, tid_agg_rx, frames);
|
||||
__skb_queue_tail(&tid_agg_rx->reorder_buf[index], skb);
|
||||
if (!(status->flag & RX_FLAG_AMSDU_MORE)) {
|
||||
tid_agg_rx->reorder_time[index] = jiffies;
|
||||
tid_agg_rx->stored_mpdu_num++;
|
||||
ieee80211_sta_reorder_release(sdata, tid_agg_rx, frames);
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock(&tid_agg_rx->reorder_lock);
|
||||
@@ -3129,6 +3148,14 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx,
|
||||
if (!ieee80211_is_beacon(hdr->frame_control))
|
||||
return false;
|
||||
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
} else if (!ieee80211_has_tods(hdr->frame_control)) {
|
||||
/* ignore data frames to TDLS-peers */
|
||||
if (ieee80211_is_data(hdr->frame_control))
|
||||
return false;
|
||||
/* ignore action frames to TDLS-peers */
|
||||
if (ieee80211_is_action(hdr->frame_control) &&
|
||||
!ether_addr_equal(bssid, hdr->addr1))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case NL80211_IFTYPE_WDS:
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
* @WLAN_STA_TDLS_PEER: Station is a TDLS peer.
|
||||
* @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct
|
||||
* packets. This means the link is enabled.
|
||||
* @WLAN_STA_TDLS_INITIATOR: We are the initiator of the TDLS link with this
|
||||
* station.
|
||||
* @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was
|
||||
* keeping station in power-save mode, reply when the driver
|
||||
* unblocks the station.
|
||||
@@ -76,6 +78,7 @@ enum ieee80211_sta_info_flags {
|
||||
WLAN_STA_PSPOLL,
|
||||
WLAN_STA_TDLS_PEER,
|
||||
WLAN_STA_TDLS_PEER_AUTH,
|
||||
WLAN_STA_TDLS_INITIATOR,
|
||||
WLAN_STA_UAPSD,
|
||||
WLAN_STA_SP,
|
||||
WLAN_STA_4ADDR_EVENT,
|
||||
@@ -152,7 +155,8 @@ struct tid_ampdu_tx {
|
||||
/**
|
||||
* struct tid_ampdu_rx - TID aggregation information (Rx).
|
||||
*
|
||||
* @reorder_buf: buffer to reorder incoming aggregated MPDUs
|
||||
* @reorder_buf: buffer to reorder incoming aggregated MPDUs. An MPDU may be an
|
||||
* A-MSDU with individually reported subframes.
|
||||
* @reorder_time: jiffies when skb was added
|
||||
* @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
|
||||
* @reorder_timer: releases expired frames from the reorder buffer.
|
||||
@@ -177,7 +181,7 @@ struct tid_ampdu_tx {
|
||||
struct tid_ampdu_rx {
|
||||
struct rcu_head rcu_head;
|
||||
spinlock_t reorder_lock;
|
||||
struct sk_buff **reorder_buf;
|
||||
struct sk_buff_head *reorder_buf;
|
||||
unsigned long *reorder_time;
|
||||
struct timer_list session_timer;
|
||||
struct timer_list reorder_timer;
|
||||
|
||||
+396
-67
File diff suppressed because it is too large
Load Diff
@@ -3083,3 +3083,18 @@ int ieee80211_max_num_channels(struct ieee80211_local *local)
|
||||
|
||||
return max_num_different_channels;
|
||||
}
|
||||
|
||||
u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo)
|
||||
{
|
||||
*buf++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*buf++ = 7; /* len */
|
||||
*buf++ = 0x00; /* Microsoft OUI 00:50:F2 */
|
||||
*buf++ = 0x50;
|
||||
*buf++ = 0xf2;
|
||||
*buf++ = 2; /* WME */
|
||||
*buf++ = 0; /* WME info */
|
||||
*buf++ = 1; /* WME ver */
|
||||
*buf++ = qosinfo; /* U-APSD no in use */
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -129,6 +129,10 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
||||
if (!vht_cap_ie || !sband->vht_cap.vht_supported)
|
||||
return;
|
||||
|
||||
/* don't support VHT for TDLS peers for now */
|
||||
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
|
||||
return;
|
||||
|
||||
/*
|
||||
* A VHT STA must support 40 MHz, but if we verify that here
|
||||
* then we break a few things - some APs (e.g. Netgear R6300v2
|
||||
|
||||
+1
-1
@@ -811,7 +811,7 @@ ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx)
|
||||
ieee80211_rx_result
|
||||
ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx)
|
||||
{
|
||||
if (rx->sta->cipher_scheme)
|
||||
if (rx->sta && rx->sta->cipher_scheme)
|
||||
return ieee80211_crypto_cs_decrypt(rx);
|
||||
|
||||
return RX_DROP_UNUSABLE;
|
||||
|
||||
@@ -162,6 +162,12 @@ config CFG80211_INTERNAL_REGDB
|
||||
and includes code to query that database. This is an alternative
|
||||
to using CRDA for defining regulatory rules for the kernel.
|
||||
|
||||
Using this option requires some parsing of the db.txt at build time,
|
||||
the parser will be upkept with the latest wireless-regdb updates but
|
||||
older wireless-regdb formats will be ignored. The parser may later
|
||||
be replaced to avoid issues with conflicts on versions of
|
||||
wireless-regdb.
|
||||
|
||||
For details see:
|
||||
|
||||
http://wireless.kernel.org/en/developers/Regulatory
|
||||
|
||||
+22
-13
@@ -51,32 +51,41 @@ function parse_country_head() {
|
||||
|
||||
function parse_reg_rule()
|
||||
{
|
||||
flag_starts_at = 7
|
||||
|
||||
start = $1
|
||||
sub(/\(/, "", start)
|
||||
end = $3
|
||||
bw = $5
|
||||
sub(/\),/, "", bw)
|
||||
gain = $6
|
||||
sub(/\(/, "", gain)
|
||||
sub(/,/, "", gain)
|
||||
power = $7
|
||||
sub(/\)/, "", power)
|
||||
sub(/,/, "", power)
|
||||
gain = 0
|
||||
power = $6
|
||||
# power might be in mW...
|
||||
units = $8
|
||||
units = $7
|
||||
dfs_cac = 0
|
||||
|
||||
sub(/\(/, "", power)
|
||||
sub(/\),/, "", power)
|
||||
sub(/\),/, "", units)
|
||||
sub(/\)/, "", units)
|
||||
sub(/,/, "", units)
|
||||
dfs_cac = $9
|
||||
|
||||
if (units == "mW") {
|
||||
flag_starts_at = 8
|
||||
power = 10 * log(power)/log(10)
|
||||
if ($8 ~ /[[:digit:]]/) {
|
||||
flag_starts_at = 9
|
||||
dfs_cac = $8
|
||||
}
|
||||
} else {
|
||||
dfs_cac = $8
|
||||
if ($7 ~ /[[:digit:]]/) {
|
||||
flag_starts_at = 8
|
||||
dfs_cac = $7
|
||||
}
|
||||
}
|
||||
sub(/,/, "", dfs_cac)
|
||||
sub(/\(/, "", dfs_cac)
|
||||
sub(/\)/, "", dfs_cac)
|
||||
sub(/\),/, "", dfs_cac)
|
||||
flagstr = ""
|
||||
for (i=8; i<=NF; i++)
|
||||
for (i=flag_starts_at; i<=NF; i++)
|
||||
flagstr = flagstr $i
|
||||
split(flagstr, flagarray, ",")
|
||||
flags = ""
|
||||
|
||||
@@ -3814,7 +3814,8 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
|
||||
{
|
||||
if (params->listen_interval != -1)
|
||||
return -EINVAL;
|
||||
if (params->aid)
|
||||
if (params->aid &&
|
||||
!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
|
||||
return -EINVAL;
|
||||
|
||||
/* When you run into this, adjust the code below for the new flag */
|
||||
|
||||
Reference in New Issue
Block a user