aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/intel/iwlwifi/mvm
diff options
context:
space:
mode:
authorSara Sharon <sara.sharon@intel.com>2015-12-07 05:50:58 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2016-02-27 15:00:09 -0500
commita571f5f635ef40ff3a5e85acc7f20daa58bcf06a (patch)
treec48e07ddd651293f85aeb1aefbc99f356852e724 /drivers/net/wireless/intel/iwlwifi/mvm
parent685b346c3af35bcdc1316289ce8c76e28a5a7a7e (diff)
iwlwifi: mvm: add duplicate packet detection per rx queue
Next hardware will direct TCP/UDP streams to different cores. Packets belonging to the same stream will be directed to the same core. The result is that duplicates will be always directed to the same rx queue were the first packet was received. This enabled parallelizing the duplicate packet detection across the different cores, without sharing data between the rx queues. Signed-off-by: Sara Sharon <sara.sharon@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c66
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h13
3 files changed, 92 insertions, 1 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index a9180b06fb52..d89194223af3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -285,6 +285,66 @@ static void iwl_mvm_rx_csum(struct ieee80211_sta *sta,
285 skb->ip_summed = CHECKSUM_UNNECESSARY; 285 skb->ip_summed = CHECKSUM_UNNECESSARY;
286} 286}
287 287
288/*
289 * returns true if a packet outside BA session is a duplicate and
290 * should be dropped
291 */
292static bool iwl_mvm_is_nonagg_dup(struct ieee80211_sta *sta, int queue,
293 struct ieee80211_rx_status *rx_status,
294 struct ieee80211_hdr *hdr,
295 struct iwl_rx_mpdu_desc *desc)
296{
297 struct iwl_mvm_sta *mvm_sta;
298 struct iwl_mvm_rxq_dup_data *dup_data;
299 u8 baid, tid, sub_frame_idx;
300
301 if (WARN_ON(IS_ERR_OR_NULL(sta)))
302 return false;
303
304 baid = (le32_to_cpu(desc->reorder_data) &
305 IWL_RX_MPDU_REORDER_BAID_MASK) >>
306 IWL_RX_MPDU_REORDER_BAID_SHIFT;
307
308 if (baid != IWL_RX_REORDER_DATA_INVALID_BAID)
309 return false;
310
311 mvm_sta = iwl_mvm_sta_from_mac80211(sta);
312 dup_data = &mvm_sta->dup_data[queue];
313
314 /*
315 * Drop duplicate 802.11 retransmissions
316 * (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery")
317 */
318 if (ieee80211_is_ctl(hdr->frame_control) ||
319 ieee80211_is_qos_nullfunc(hdr->frame_control) ||
320 is_multicast_ether_addr(hdr->addr1)) {
321 rx_status->flag |= RX_FLAG_DUP_VALIDATED;
322 return false;
323 }
324
325 if (ieee80211_is_data_qos(hdr->frame_control))
326 /* frame has qos control */
327 tid = *ieee80211_get_qos_ctl(hdr) &
328 IEEE80211_QOS_CTL_TID_MASK;
329 else
330 tid = IWL_MAX_TID_COUNT;
331
332 /* If this wasn't a part of an A-MSDU the sub-frame index will be 0 */
333 sub_frame_idx = desc->amsdu_info & IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;
334
335 if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
336 dup_data->last_seq[tid] == hdr->seq_ctrl &&
337 dup_data->last_sub_frame[tid] >= sub_frame_idx))
338 return true;
339
340 dup_data->last_seq[tid] = hdr->seq_ctrl;
341 dup_data->last_sub_frame[tid] = sub_frame_idx;
342
343 rx_status->flag |= RX_FLAG_DUP_VALIDATED;
344
345 return false;
346}
347
288void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, 348void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
289 struct iwl_rx_cmd_buffer *rxb, int queue) 349 struct iwl_rx_cmd_buffer *rxb, int queue)
290{ 350{
@@ -389,6 +449,12 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
389 449
390 if (ieee80211_is_data(hdr->frame_control)) 450 if (ieee80211_is_data(hdr->frame_control))
391 iwl_mvm_rx_csum(sta, skb, desc); 451 iwl_mvm_rx_csum(sta, skb, desc);
452
453 if (iwl_mvm_is_nonagg_dup(sta, queue, rx_status, hdr, desc)) {
454 kfree_skb(skb);
455 rcu_read_unlock();
456 return;
457 }
392 } 458 }
393 459
394 /* 460 /*
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index b2123ce3e3a8..4717b185f5b0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -280,6 +280,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
280{ 280{
281 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 281 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
282 struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); 282 struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
283 struct iwl_mvm_rxq_dup_data *dup_data;
283 int i, ret, sta_id; 284 int i, ret, sta_id;
284 285
285 lockdep_assert_held(&mvm->mutex); 286 lockdep_assert_held(&mvm->mutex);
@@ -327,6 +328,16 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
327 } 328 }
328 mvm_sta->agg_tids = 0; 329 mvm_sta->agg_tids = 0;
329 330
331 if (iwl_mvm_has_new_rx_api(mvm) &&
332 !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
333 dup_data = kcalloc(mvm->trans->num_rx_queues,
334 sizeof(*dup_data),
335 GFP_KERNEL);
336 if (!dup_data)
337 return -ENOMEM;
338 mvm_sta->dup_data = dup_data;
339 }
340
330 ret = iwl_mvm_sta_send_to_fw(mvm, sta, false); 341 ret = iwl_mvm_sta_send_to_fw(mvm, sta, false);
331 if (ret) 342 if (ret)
332 goto err; 343 goto err;
@@ -508,6 +519,9 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
508 519
509 lockdep_assert_held(&mvm->mutex); 520 lockdep_assert_held(&mvm->mutex);
510 521
522 if (iwl_mvm_has_new_rx_api(mvm))
523 kfree(mvm_sta->dup_data);
524
511 if (vif->type == NL80211_IFTYPE_STATION && 525 if (vif->type == NL80211_IFTYPE_STATION &&
512 mvmvif->ap_sta_id == mvm_sta->sta_id) { 526 mvmvif->ap_sta_id == mvm_sta->sta_id) {
513 ret = iwl_mvm_drain_sta(mvm, mvm_sta, true); 527 ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index f95f603ad56c..db701cad87c1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -296,6 +296,16 @@ struct iwl_mvm_key_pn {
296}; 296};
297 297
298/** 298/**
299 * struct iwl_mvm_rxq_dup_data - per station per rx queue data
300 * @last_seq: last sequence per tid for duplicate packet detection
301 * @last_sub_frame: last subframe packet
302 */
303struct iwl_mvm_rxq_dup_data {
304 __le16 last_seq[IWL_MAX_TID_COUNT + 1];
305 u8 last_sub_frame[IWL_MAX_TID_COUNT + 1];
306} ____cacheline_aligned_in_smp;
307
308/**
299 * struct iwl_mvm_sta - representation of a station in the driver 309 * struct iwl_mvm_sta - representation of a station in the driver
300 * @sta_id: the index of the station in the fw (will be replaced by id_n_color) 310 * @sta_id: the index of the station in the fw (will be replaced by id_n_color)
301 * @tfd_queue_msk: the tfd queues used by the station 311 * @tfd_queue_msk: the tfd queues used by the station
@@ -321,6 +331,7 @@ struct iwl_mvm_key_pn {
321 * we are sending frames from an AMPDU queue and there was a hole in 331 * we are sending frames from an AMPDU queue and there was a hole in
322 * the BA window. To be used for UAPSD only. 332 * the BA window. To be used for UAPSD only.
323 * @ptk_pn: per-queue PTK PN data structures 333 * @ptk_pn: per-queue PTK PN data structures
334 * @dup_data: per queue duplicate packet detection data
324 * 335 *
325 * When mac80211 creates a station it reserves some space (hw->sta_data_size) 336 * When mac80211 creates a station it reserves some space (hw->sta_data_size)
326 * in the structure for use by driver. This structure is placed in that 337 * in the structure for use by driver. This structure is placed in that
@@ -340,8 +351,8 @@ struct iwl_mvm_sta {
340 struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT]; 351 struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT];
341 struct iwl_lq_sta lq_sta; 352 struct iwl_lq_sta lq_sta;
342 struct ieee80211_vif *vif; 353 struct ieee80211_vif *vif;
343
344 struct iwl_mvm_key_pn __rcu *ptk_pn[4]; 354 struct iwl_mvm_key_pn __rcu *ptk_pn[4];
355 struct iwl_mvm_rxq_dup_data *dup_data;
345 356
346 /* Temporary, until the new TLC will control the Tx protection */ 357 /* Temporary, until the new TLC will control the Tx protection */
347 s8 tx_protection; 358 s8 tx_protection;