diff options
author | Sara Sharon <sara.sharon@intel.com> | 2015-07-22 04:38:40 -0400 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2016-02-27 15:00:06 -0500 |
commit | 3af512d6aac7eb6420086f124abb4426f5f4b369 (patch) | |
tree | e192787890af13951ae28552c72d5d2e472c9a80 /drivers/net | |
parent | 77fe739554e13d44466e115dbaba3e7aa3aececd (diff) |
iwlwifi: mvm: support filtered frames notification
During d0i3 frames might be filtered by the FW and this may
cause reordering buffer a delay - as the frames will not be
received and reorder will time out.
Introduce an API function to receive notification of filtered
frames and pass the information to the mac80211.
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h | 22 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 49 |
4 files changed, 77 insertions, 0 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h index ca7fec71854f..e1e11946f7e9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h | |||
@@ -119,6 +119,8 @@ enum { | |||
119 | SCAN_ABORT_UMAC = 0xe, | 119 | SCAN_ABORT_UMAC = 0xe, |
120 | SCAN_COMPLETE_UMAC = 0xf, | 120 | SCAN_COMPLETE_UMAC = 0xf, |
121 | 121 | ||
122 | BA_WINDOW_STATUS_NOTIFICATION_ID = 0x13, | ||
123 | |||
122 | /* station table */ | 124 | /* station table */ |
123 | ADD_STA_KEY = 0x17, | 125 | ADD_STA_KEY = 0x17, |
124 | ADD_STA = 0x18, | 126 | ADD_STA = 0x18, |
@@ -1286,6 +1288,26 @@ struct iwl_fw_bcast_filter { | |||
1286 | struct iwl_fw_bcast_filter_attr attrs[MAX_BCAST_FILTER_ATTRS]; | 1288 | struct iwl_fw_bcast_filter_attr attrs[MAX_BCAST_FILTER_ATTRS]; |
1287 | } __packed; /* BCAST_FILTER_S_VER_1 */ | 1289 | } __packed; /* BCAST_FILTER_S_VER_1 */ |
1288 | 1290 | ||
1291 | #define BA_WINDOW_STREAMS_MAX 16 | ||
1292 | #define BA_WINDOW_STATUS_TID_MSK 0x000F | ||
1293 | #define BA_WINDOW_STATUS_STA_ID_POS 4 | ||
1294 | #define BA_WINDOW_STATUS_STA_ID_MSK 0x01F0 | ||
1295 | #define BA_WINDOW_STATUS_VALID_MSK BIT(9) | ||
1296 | |||
1297 | /** | ||
1298 | * struct iwl_ba_window_status_notif - reordering window's status notification | ||
1299 | * @bitmap: bitmap of received frames [start_seq_num + 0]..[start_seq_num + 63] | ||
1300 | * @ra_tid: bit 3:0 - TID, bit 8:4 - STA_ID, bit 9 - valid | ||
1301 | * @start_seq_num: the start sequence number of the bitmap | ||
1302 | * @mpdu_rx_count: the number of received MPDUs since entering D0i3 | ||
1303 | */ | ||
1304 | struct iwl_ba_window_status_notif { | ||
1305 | __le64 bitmap[BA_WINDOW_STREAMS_MAX]; | ||
1306 | __le16 ra_tid[BA_WINDOW_STREAMS_MAX]; | ||
1307 | __le32 start_seq_num[BA_WINDOW_STREAMS_MAX]; | ||
1308 | __le16 mpdu_rx_count[BA_WINDOW_STREAMS_MAX]; | ||
1309 | } __packed; /* BA_WINDOW_STATUS_NTFY_API_S_VER_1 */ | ||
1310 | |||
1289 | /** | 1311 | /** |
1290 | * struct iwl_fw_bcast_mac - per-mac broadcast filtering configuration. | 1312 | * struct iwl_fw_bcast_mac - per-mac broadcast filtering configuration. |
1291 | * @default_discard: default action for this mac (discard (1) / pass (0)). | 1313 | * @default_discard: default action for this mac (discard (1) / pass (0)). |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 416aedb7c19e..fa987bd9da0d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | |||
@@ -1268,6 +1268,8 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, | |||
1268 | struct iwl_rx_cmd_buffer *rxb); | 1268 | struct iwl_rx_cmd_buffer *rxb); |
1269 | void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, | 1269 | void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, |
1270 | struct iwl_rx_cmd_buffer *rxb); | 1270 | struct iwl_rx_cmd_buffer *rxb); |
1271 | void iwl_mvm_window_status_notif(struct iwl_mvm *mvm, | ||
1272 | struct iwl_rx_cmd_buffer *rxb); | ||
1271 | void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, | 1273 | void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, |
1272 | struct ieee80211_vif *vif); | 1274 | struct ieee80211_vif *vif); |
1273 | unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm, | 1275 | unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm, |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index bfa6da1bf846..52c73d0c1be5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c | |||
@@ -236,6 +236,9 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
236 | RX_HANDLER(ANTENNA_COUPLING_NOTIFICATION, | 236 | RX_HANDLER(ANTENNA_COUPLING_NOTIFICATION, |
237 | iwl_mvm_rx_ant_coupling_notif, true), | 237 | iwl_mvm_rx_ant_coupling_notif, true), |
238 | 238 | ||
239 | RX_HANDLER(BA_WINDOW_STATUS_NOTIFICATION_ID, | ||
240 | iwl_mvm_window_status_notif, false), | ||
241 | |||
239 | RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false), | 242 | RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false), |
240 | RX_HANDLER(MCC_CHUB_UPDATE_CMD, iwl_mvm_rx_chub_update_mcc, true), | 243 | RX_HANDLER(MCC_CHUB_UPDATE_CMD, iwl_mvm_rx_chub_update_mcc, true), |
241 | 244 | ||
@@ -294,6 +297,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = { | |||
294 | HCMD_NAME(SCAN_COMPLETE_UMAC), | 297 | HCMD_NAME(SCAN_COMPLETE_UMAC), |
295 | HCMD_NAME(TOF_CMD), | 298 | HCMD_NAME(TOF_CMD), |
296 | HCMD_NAME(TOF_NOTIFICATION), | 299 | HCMD_NAME(TOF_NOTIFICATION), |
300 | HCMD_NAME(BA_WINDOW_STATUS_NOTIFICATION_ID), | ||
297 | HCMD_NAME(ADD_STA_KEY), | 301 | HCMD_NAME(ADD_STA_KEY), |
298 | HCMD_NAME(ADD_STA), | 302 | HCMD_NAME(ADD_STA), |
299 | HCMD_NAME(REMOVE_STA), | 303 | HCMD_NAME(REMOVE_STA), |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index ad625f0c79ed..485cfc1a4daa 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2016 Intel Deutschland GmbH | ||
10 | * | 11 | * |
11 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of version 2 of the GNU General Public License as | 13 | * it under the terms of version 2 of the GNU General Public License as |
@@ -626,3 +627,51 @@ void iwl_mvm_rx_statistics(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) | |||
626 | { | 627 | { |
627 | iwl_mvm_handle_rx_statistics(mvm, rxb_addr(rxb)); | 628 | iwl_mvm_handle_rx_statistics(mvm, rxb_addr(rxb)); |
628 | } | 629 | } |
630 | |||
631 | void iwl_mvm_window_status_notif(struct iwl_mvm *mvm, | ||
632 | struct iwl_rx_cmd_buffer *rxb) | ||
633 | { | ||
634 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
635 | struct iwl_ba_window_status_notif *notif = (void *)pkt->data; | ||
636 | int i; | ||
637 | u32 pkt_len = iwl_rx_packet_payload_len(pkt); | ||
638 | |||
639 | if (WARN_ONCE(pkt_len != sizeof(*notif), | ||
640 | "Received window status notification of wrong size (%u)\n", | ||
641 | pkt_len)) | ||
642 | return; | ||
643 | |||
644 | rcu_read_lock(); | ||
645 | for (i = 0; i < BA_WINDOW_STREAMS_MAX; i++) { | ||
646 | struct ieee80211_sta *sta; | ||
647 | u8 sta_id, tid; | ||
648 | u64 bitmap; | ||
649 | u32 ssn; | ||
650 | u16 ratid; | ||
651 | u16 received_mpdu; | ||
652 | |||
653 | ratid = le16_to_cpu(notif->ra_tid[i]); | ||
654 | /* check that this TID is valid */ | ||
655 | if (!(ratid & BA_WINDOW_STATUS_VALID_MSK)) | ||
656 | continue; | ||
657 | |||
658 | received_mpdu = le16_to_cpu(notif->mpdu_rx_count[i]); | ||
659 | if (received_mpdu == 0) | ||
660 | continue; | ||
661 | |||
662 | tid = ratid & BA_WINDOW_STATUS_TID_MSK; | ||
663 | /* get the station */ | ||
664 | sta_id = (ratid & BA_WINDOW_STATUS_STA_ID_MSK) | ||
665 | >> BA_WINDOW_STATUS_STA_ID_POS; | ||
666 | sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); | ||
667 | if (IS_ERR_OR_NULL(sta)) | ||
668 | continue; | ||
669 | bitmap = le64_to_cpu(notif->bitmap[i]); | ||
670 | ssn = le32_to_cpu(notif->start_seq_num[i]); | ||
671 | |||
672 | /* update mac80211 with the bitmap for the reordering buffer */ | ||
673 | ieee80211_mark_rx_ba_filtered_frames(sta, tid, ssn, bitmap, | ||
674 | received_mpdu); | ||
675 | } | ||
676 | rcu_read_unlock(); | ||
677 | } | ||