Browse Source

qcacld-3.0: Add support to handle block ack action frames

Add support to handle block ack(BA) action frames. Due to change in
architecture, reception of ADDBA request and DELBA request ack action frames
are now handled in the host and transmission of ADDBA response is also done
by the host driver.

Change-Id: I9bbc26da19fbea051eda950443d2cbc459b865b9
CRs-Fixed: 1112700
Krishna Kumaar Natarajan 8 years ago
parent
commit
48a6b4cfcd

+ 8 - 0
core/mac/inc/sir_mac_prot_def.h

@@ -160,6 +160,14 @@
 #define SIR_MAC_QOS_DEF_BA_REQ      4
 #define SIR_MAC_QOS_DEF_BA_RSP      5
 
+#define SIR_MAC_ADDBA_REQ     0
+#define SIR_MAC_ADDBA_RSP     1
+#define SIR_MAC_DELBA_REQ     2
+
+#define SIR_MAC_BA_POLICY_DELAYED      0
+#define SIR_MAC_BA_POLICY_IMMEDIATE    1
+#define SIR_MAC_BA_AMSDU_SUPPORTED     1
+
 #ifdef ANI_SUPPORT_11H
 #define SIR_MAC_ACTION_MEASURE_REQUEST_ID      0
 #define SIR_MAC_ACTION_MEASURE_REPORT_ID       1

+ 61 - 1
core/mac/src/cfg/cfgUtil/dot11f.frms

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2007, 2014-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2006-2007, 2014-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -411,6 +411,38 @@ FF ext_chan_switch_ann_action(4)
    }
 }
 
+FF addba_param_set(2)
+{
+   {
+     amsdu_supp: 1;
+     policy: 1;
+     tid: 4;
+     buff_size: 10;
+   }
+}
+
+FF ba_timeout(2)
+{
+    timeout, 2;
+}
+
+FF ba_start_seq_ctrl(2)
+{
+    {
+      frag_number: 4;
+      ssn: 12;
+    }
+}
+
+FF delba_param_set(2)
+{
+    {
+      reserved: 11;
+      initiator: 1;
+      tid: 4;
+    }
+}
+
 /////////////////////////////////////////////////////////////////////////////
 //                                  TLVs                                   //
 /////////////////////////////////////////////////////////////////////////////
@@ -3758,6 +3790,34 @@ FRAME p2p_oper_chan_change_confirm
     OPTIE OperatingMode;
 }
 
+FRAME addba_req
+{
+    FF    Category;
+    FF    Action;
+    FF    DialogToken;
+    FF    addba_param_set;
+    FF    ba_timeout;
+    FF    ba_start_seq_ctrl;
+}
+
+FRAME addba_rsp
+{
+    FF    Category;
+    FF    Action;
+    FF    DialogToken;
+    FF    Status;
+    FF    addba_param_set;
+    FF    ba_timeout;
+}
+
+FRAME delba_req
+{
+    FF    Category;
+    FF    Action;
+    FF    delba_param_set;
+    FF    Reason;
+}
+
 // Local Variables:
 // mode: c++
 // fill-column: 77

+ 172 - 10
core/mac/src/include/dot11f.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -35,7 +35,7 @@
  *
  *
  * This file was automatically generated by 'framesc'
- * Thu Nov  3 15:54:51 2016 from the following file(s):
+ * Fri Jan  6 16:25:25 2017 from the following file(s):
  *
  * dot11f.frms
  *
@@ -544,6 +544,83 @@ void dot11f_pack_ff_vht_user_position_array(tpAniSirGlobal,
 					 uint8_t *);
 
 
+typedef struct sDot11fFfaddba_param_set {
+	uint16_t  amsdu_supp:1;
+	uint16_t      policy:1;
+	uint16_t         tid:4;
+	uint16_t   buff_size:10;
+} tDot11fFfaddba_param_set;
+
+#define DOT11F_FF_ADDBA_PARAM_SET_LEN (2)
+
+void dot11f_unpack_ff_addba_param_set(tpAniSirGlobal, uint8_t *,
+				      tDot11fFfaddba_param_set *);
+
+void dot11f_pack_ff_addba_param_set(tpAniSirGlobal, tDot11fFfaddba_param_set *,
+				    uint8_t *);
+
+#define ADDBA_PARAM_SET_AMSDU_SUPP_OFFSET 0
+#define ADDBA_PARAM_SET_AMSDU_SUPP_WIDTH  1
+#define ADDBA_PARAM_SET_POLICY_OFFSET     1
+#define ADDBA_PARAM_SET_POLICY_WIDTH      1
+#define ADDBA_PARAM_SET_TID_OFFSET        2
+#define ADDBA_PARAM_SET_TID_WIDTH         4
+#define ADDBA_PARAM_SET_BUFF_SIZE_OFFSET  6
+#define ADDBA_PARAM_SET_BUFF_SIZE_WIDTH   10
+
+typedef struct sDot11fFfba_start_seq_ctrl {
+	uint16_t  frag_number:4;
+	uint16_t          ssn:12;
+} tDot11fFfba_start_seq_ctrl;
+
+#define DOT11F_FF_BA_START_SEQ_CTRL_LEN (2)
+
+void dot11f_unpack_ff_ba_start_seq_ctrl(tpAniSirGlobal, uint8_t *,
+					tDot11fFfba_start_seq_ctrl *);
+
+void dot11f_pack_ff_ba_start_seq_ctrl(tpAniSirGlobal,
+				      tDot11fFfba_start_seq_ctrl *,
+				      uint8_t *);
+
+
+#define BA_START_SEQ_CTRL_FRAG_NUMBER_OFFSET 0
+#define BA_START_SEQ_CTRL_FRAG_NUMBER_WIDTH  4
+#define BA_START_SEQ_CTRL_SSN_OFFSET         4
+#define BA_START_SEQ_CTRL_SSN_WIDTH          12
+
+typedef struct sDot11fFfba_timeout {
+	uint16_t timeout;
+} tDot11fFfba_timeout;
+
+#define DOT11F_FF_BA_TIMEOUT_LEN (2)
+
+void dot11f_unpack_ff_ba_timeout(tpAniSirGlobal, uint8_t *,
+				 tDot11fFfba_timeout *);
+
+void dot11f_pack_ff_ba_timeout(tpAniSirGlobal, tDot11fFfba_timeout *,
+			       uint8_t *);
+
+typedef struct sDot11fFfdelba_param_set {
+	uint16_t   reserved:11;
+	uint16_t  initiator:1;
+	uint16_t        tid:4;
+} tDot11fFfdelba_param_set;
+
+#define DOT11F_FF_DELBA_PARAM_SET_LEN (2)
+
+void dot11f_unpack_ff_delba_param_set(tpAniSirGlobal, uint8_t *,
+				      tDot11fFfdelba_param_set *);
+
+void dot11f_pack_ff_delba_param_set(tpAniSirGlobal, tDot11fFfdelba_param_set *,
+				    uint8_t *);
+
+#define DELBA_PARAM_SET_RESERVED_OFFSET  0
+#define DELBA_PARAM_SET_RESERVED_WIDTH   11
+#define DELBA_PARAM_SET_INITIATOR_OFFSET 11
+#define DELBA_PARAM_SET_INITIATOR_WIDTH  1
+#define DELBA_PARAM_SET_TID_OFFSET       12
+#define DELBA_PARAM_SET_TID_WIDTH        4
+
 typedef struct sDot11fFfext_chan_switch_ann_action {
 	uint32_t   switch_mode:8;
 	uint32_t      op_class:8;
@@ -593,7 +670,7 @@ void dot11f_unpack_ff_p2p_action_subtype(tpAniSirGlobal, uint8_t *,
 
 void dot11f_pack_ff_p2p_action_subtype(tpAniSirGlobal,
 				       tDot11fFfp2p_action_subtype *,
-				  uint8_t *);
+				       uint8_t *);
 
 
 /*********************************************************************
@@ -9307,13 +9384,98 @@ uint32_t dot11f_get_packed_wmm_del_ts_size(tpAniSirGlobal pCtx,
 } /* End extern "C". */
 #endif /* C++ */
 
+typedef struct sDot11faddba_req{
+	tDot11fFfCategory                 Category;
+	tDot11fFfAction                   Action;
+	tDot11fFfDialogToken              DialogToken;
+	tDot11fFfaddba_param_set          addba_param_set;
+	tDot11fFfba_timeout               ba_timeout;
+	tDot11fFfba_start_seq_ctrl        ba_start_seq_ctrl;
+} tDot11faddba_req;
+
+#define DOT11F_ADDBA_REQ (46)
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* C++ */
+
+uint32_t dot11f_unpack_addba_req(tpAniSirGlobal pCtx,
+	uint8_t *pBuf, uint32_t nBuf,
+	tDot11faddba_req * pFrm);
+uint32_t dot11f_pack_addba_req(tpAniSirGlobal pCtx,
+	tDot11faddba_req *pFrm, uint8_t *pBuf,
+	uint32_t nBuf, uint32_t *pnConsumed);
+uint32_t dot11f_get_packed_addba_req_size(tpAniSirGlobal pCtx,
+	tDot11faddba_req *pFrm,
+	uint32_t *pnNeeded);
+
+#ifdef __cplusplus
+} /* End extern "C". */
+#endif /* C++ */
+
+typedef struct sDot11faddba_rsp{
+	tDot11fFfCategory               Category;
+	tDot11fFfAction                 Action;
+	tDot11fFfDialogToken            DialogToken;
+	tDot11fFfStatus                 Status;
+	tDot11fFfaddba_param_set        addba_param_set;
+	tDot11fFfba_timeout             ba_timeout;
+} tDot11faddba_rsp;
+
+#define DOT11F_ADDBA_RSP (47)
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* C++ */
+
+uint32_t dot11f_unpack_addba_rsp(tpAniSirGlobal pCtx,
+	uint8_t *pBuf, uint32_t nBuf,
+	tDot11faddba_rsp * pFrm);
+uint32_t dot11f_pack_addba_rsp(tpAniSirGlobal pCtx,
+	tDot11faddba_rsp *pFrm, uint8_t *pBuf,
+	uint32_t nBuf, uint32_t *pnConsumed);
+uint32_t dot11f_get_packed_addba_rsp_size(tpAniSirGlobal pCtx,
+	tDot11faddba_rsp *pFrm,
+	uint32_t *pnNeeded);
+
+#ifdef __cplusplus
+} /* End extern "C". */
+#endif /* C++ */
+
+typedef struct sDot11fdelba_req{
+	tDot11fFfCategory               Category;
+	tDot11fFfAction                 Action;
+	tDot11fFfdelba_param_set        delba_param_set;
+	tDot11fFfReason                 Reason;
+} tDot11fdelba_req;
+
+#define DOT11F_DELBA_REQ (48)
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* C++ */
+
+uint32_t dot11f_unpack_delba_req(tpAniSirGlobal pCtx,
+	uint8_t *pBuf, uint32_t nBuf,
+	tDot11fdelba_req * pFrm);
+uint32_t dot11f_pack_delba_req(tpAniSirGlobal pCtx,
+	tDot11fdelba_req *pFrm, uint8_t *pBuf,
+	uint32_t nBuf, uint32_t *pnConsumed);
+uint32_t dot11f_get_packed_delba_req_size(tpAniSirGlobal pCtx,
+	tDot11fdelba_req *pFrm,
+	uint32_t *pnNeeded);
+
+#ifdef __cplusplus
+} /* End extern "C". */
+#endif /* C++ */
+
 typedef struct sDot11fext_channel_switch_action_frame{
 	tDot11fFfCategory                          Category;
 	tDot11fFfAction                            Action;
 	tDot11fFfext_chan_switch_ann_action        ext_chan_switch_ann_action;
 } tDot11fext_channel_switch_action_frame;
 
-#define DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME (46)
+#define DOT11F_EXT_CHANNEL_SWITCH_ACTION_FRAME (49)
 
 #ifdef __cplusplus
 extern "C" {
@@ -9340,7 +9502,7 @@ typedef struct sDot11fht2040_bss_coexistence_mgmt_action_frame{
 	tDot11fIEht2040_bss_intolerant_report        ht2040_bss_intolerant_report;
 } tDot11fht2040_bss_coexistence_mgmt_action_frame;
 
-#define DOT11F_HT2040_BSS_COEXISTENCE_MGMT_ACTION_FRAME (47)
+#define DOT11F_HT2040_BSS_COEXISTENCE_MGMT_ACTION_FRAME (50)
 
 #ifdef __cplusplus
 extern "C" {
@@ -9361,16 +9523,16 @@ uint32_t dot11f_get_packed_ht2040_bss_coexistence_mgmt_action_frameSize(tpAniSir
 #endif /* C++ */
 
 typedef struct sDot11fp2p_oper_chan_change_confirm{
-	tDot11fFfCategory             Category;
+	tDot11fFfCategory                  Category;
 	tDot11fFfp2p_action_oui            p2p_action_oui;
 	tDot11fFfp2p_action_subtype        p2p_action_subtype;
 	tDot11fFfDialogToken               DialogToken;
-	tDot11fIEHTCaps               HTCaps;
-	tDot11fIEVHTCaps              VHTCaps;
-	tDot11fIEOperatingMode        OperatingMode;
+	tDot11fIEHTCaps                    HTCaps;
+	tDot11fIEVHTCaps                   VHTCaps;
+	tDot11fIEOperatingMode             OperatingMode;
 } tDot11fp2p_oper_chan_change_confirm;
 
-#define DOT11F_P2P_OPER_CHAN_CHANGE_CONFIRM (48)
+#define DOT11F_P2P_OPER_CHAN_CHANGE_CONFIRM (51)
 
 #ifdef __cplusplus
 extern "C" {

+ 171 - 1
core/mac/src/pe/lim/lim_process_action_frame.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -57,6 +57,7 @@
 #include "cds_concurrency.h"
 #include "wma_types.h"
 #include "wma.h"
+#include <cdp_txrx_cmn.h>
 
 #define BA_DEFAULT_TX_BUFFER_SIZE 64
 
@@ -1716,6 +1717,160 @@ lim_drop_unprotected_action_frame(tpAniSirGlobal pMac, tpPESession psessionEntry
 }
 #endif
 
+/**
+ * lim_process_addba_req() - process ADDBA Request
+ * @mac_ctx: Pointer to Global MAC structure
+ * @rx_pkt_info: A pointer to packet info structure
+ * @session: PE session pointer
+ *
+ * This routine will be called to process ADDBA request action frame
+ *
+ * Return: None
+ */
+static void lim_process_addba_req(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info,
+				  tpPESession session)
+{
+	tpSirMacMgmtHdr mac_hdr;
+	uint8_t *body_ptr;
+	tDot11faddba_req *addba_req;
+	uint32_t frame_len, status;
+	QDF_STATUS qdf_status;
+	uint8_t peer_id;
+	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
+	void *peer, *pdev;
+
+	pdev = cds_get_context(QDF_MODULE_ID_TXRX);
+	if (!pdev) {
+		lim_log(mac_ctx, LOGE, FL("pdev is NULL"));
+		return;
+	}
+
+	mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+	body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
+	frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
+
+	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_INFO,
+			   body_ptr, frame_len);
+
+	addba_req = qdf_mem_malloc(sizeof(*addba_req));
+	if (NULL == addba_req) {
+		lim_log(mac_ctx, LOGE, FL("memory allocation failed"));
+		return;
+	}
+
+	/* Unpack ADDBA request frame */
+	status = dot11f_unpack_addba_req(mac_ctx, body_ptr, frame_len,
+					 addba_req);
+
+	if (DOT11F_FAILED(status)) {
+		lim_log(mac_ctx, LOGE,
+			FL("Failed to unpack and parse (0x%08x, %d bytes)"),
+			status, frame_len);
+		goto error;
+	} else if (DOT11F_WARNED(status)) {
+		lim_log(mac_ctx, LOGW,
+			FL("warning: unpack addba Req(0x%08x, %d bytes)"),
+			status, frame_len);
+	}
+
+	peer = cdp_peer_find_by_addr(soc, pdev, mac_hdr->sa, &peer_id);
+	if (!peer) {
+		lim_log(mac_ctx, LOGE, FL("PEER [%pM] not found"), mac_hdr->sa);
+		goto error;
+	}
+
+	qdf_status = cdp_addba_requestprocess(soc, peer,
+			addba_req->DialogToken.token,
+			addba_req->addba_param_set.tid,
+			addba_req->ba_timeout.timeout,
+			addba_req->addba_param_set.buff_size,
+			addba_req->ba_start_seq_ctrl.ssn);
+
+	if (QDF_STATUS_SUCCESS == qdf_status) {
+		lim_send_addba_response_frame(mac_ctx, mac_hdr->sa,
+			addba_req->addba_param_set.tid, session);
+	} else {
+		lim_log(mac_ctx, LOGE, FL("Failed to process addba request"));
+	}
+
+error:
+	qdf_mem_free(addba_req);
+	return;
+}
+
+/**
+ * lim_process_delba_req() - process DELBA Request
+ * @mac_ctx: Pointer to Global MAC structure
+ * @rx_pkt_info: A pointer to packet info structure
+ * @session: PE session pointer
+ *
+ * This routine will be called to process ADDBA request action frame
+ *
+ * Return: None
+ */
+static void lim_process_delba_req(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info,
+				  tpPESession session)
+{
+	tpSirMacMgmtHdr mac_hdr;
+	uint8_t *body_ptr;
+	tDot11fdelba_req *delba_req;
+	uint32_t frame_len, status;
+	QDF_STATUS qdf_status;
+	uint8_t peer_id;
+	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
+	void *peer, *pdev;
+
+	pdev = cds_get_context(QDF_MODULE_ID_TXRX);
+	if (!pdev) {
+		lim_log(mac_ctx, LOGE, FL("pdev is NULL"));
+		return;
+	}
+
+	mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+	body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
+	frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
+
+	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_INFO,
+			   body_ptr, frame_len);
+
+	delba_req = qdf_mem_malloc(sizeof(*delba_req));
+	if (NULL == delba_req) {
+		lim_log(mac_ctx, LOGE, FL("memory allocation failed"));
+		return;
+	}
+
+	/* Unpack DELBA request frame */
+	status = dot11f_unpack_delba_req(mac_ctx, body_ptr, frame_len,
+					 delba_req);
+
+	if (DOT11F_FAILED(status)) {
+		lim_log(mac_ctx, LOGE,
+			FL("Failed to unpack and parse (0x%08x, %d bytes)"),
+			status, frame_len);
+		goto error;
+	} else if (DOT11F_WARNED(status)) {
+		lim_log(mac_ctx, LOGW,
+			FL("warning: unpack addba Req(0x%08x, %d bytes)"),
+			status, frame_len);
+	}
+
+	peer = cdp_peer_find_by_addr(soc, pdev, mac_hdr->sa, &peer_id);
+	if (!peer) {
+		lim_log(mac_ctx, LOGE, FL("PEER [%pM] not found"), mac_hdr->sa);
+		goto error;
+	}
+
+	qdf_status = cdp_delba_process(soc, peer,
+			delba_req->delba_param_set.tid, delba_req->Reason.code);
+
+	if (QDF_STATUS_SUCCESS != qdf_status)
+		lim_log(mac_ctx, LOGE, FL("Failed to process delba request"));
+
+error:
+	qdf_mem_free(delba_req);
+	return;
+}
+
 /**
  * lim_process_action_frame() - to process action frames
  * @mac_ctx: Pointer to Global MAC structure
@@ -2170,6 +2325,21 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx,
 			break;
 		}
 		break;
+	case SIR_MAC_ACTION_BLKACK:
+		lim_log(mac_ctx, LOG1, FL("Rcvd Block Ack for %pM; action: %d"),
+			session->selfMacAddr, action_hdr->actionID);
+		switch (action_hdr->actionID) {
+		case SIR_MAC_ADDBA_REQ:
+			lim_process_addba_req(mac_ctx, rx_pkt_info, session);
+			break;
+		case SIR_MAC_DELBA_REQ:
+			lim_process_delba_req(mac_ctx, rx_pkt_info, session);
+			break;
+		default:
+			lim_log(mac_ctx, LOGE, FL("Unhandle BA action frame"));
+			break;
+		}
+		break;
 	default:
 		lim_log(mac_ctx, LOG1,
 			FL("Action category %d not handled"),

+ 149 - 0
core/mac/src/pe/lim/lim_send_management_frames.c

@@ -61,6 +61,7 @@
 #include "rrm_api.h"
 
 #include "wma_types.h"
+#include <cdp_txrx_cmn.h>
 
 /**
  *
@@ -4620,3 +4621,151 @@ returnAfterError:
 	return nSirStatus;
 } /* End lim_send_sa_query_response_frame */
 #endif
+
+/**
+ * lim_send_addba_response_frame(): Send ADDBA response action frame to peer
+ * @mac_ctx: mac context
+ * @peer_mac: Peer MAC address
+ * @tid: TID for which addba response is being sent
+ * @session: PE session entry
+ *
+ * This function is called when ADDBA request is successful. ADDBA response is
+ * setup by calling addba_response_setup API and frame is then sent out OTA.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS lim_send_addba_response_frame(tpAniSirGlobal mac_ctx,
+			tSirMacAddr peer_mac, uint16_t tid, tpPESession session)
+{
+
+	tDot11faddba_rsp frm;
+	uint8_t *frame_ptr;
+	tpSirMacMgmtHdr mgmt_hdr;
+	uint32_t num_bytes, payload_size, status;
+	void *pkt_ptr;
+	QDF_STATUS qdf_status;
+	uint8_t tx_flag = 0;
+	uint8_t sme_sessionid = 0;
+	uint16_t buff_size, status_code, batimeout;
+	uint8_t peer_id, dialog_token;
+	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
+	void *peer, *pdev;
+
+	sme_sessionid = session->smeSessionId;
+
+	pdev = cds_get_context(QDF_MODULE_ID_TXRX);
+	if (!pdev) {
+		lim_log(mac_ctx, LOGE, FL("pdev is NULL"));
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	peer = cdp_peer_find_by_addr(soc, pdev, peer_mac, &peer_id);
+	if (!peer) {
+		lim_log(mac_ctx, LOGE, FL("PEER [%pM] not found"), peer_mac);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	cdp_addba_responsesetup(soc, peer, tid, &dialog_token,
+		&status_code, &buff_size, &batimeout);
+
+	qdf_mem_set((uint8_t *) &frm, sizeof(frm), 0);
+	frm.Category.category = SIR_MAC_ACTION_BLKACK;
+	frm.Action.action = SIR_MAC_ADDBA_RSP;
+
+	frm.DialogToken.token = dialog_token;
+	frm.Status.status = status_code;
+	frm.addba_param_set.tid = tid;
+	frm.addba_param_set.buff_size = buff_size;
+	frm.addba_param_set.amsdu_supp = SIR_MAC_BA_POLICY_IMMEDIATE;
+	frm.addba_param_set.policy = SIR_MAC_BA_AMSDU_SUPPORTED;
+	frm.ba_timeout.timeout = batimeout;
+
+	lim_log(mac_ctx, LOG1, FL("Sending a ADDBA Response from %pM to %pM"),
+		session->selfMacAddr, peer_mac);
+	lim_log(mac_ctx, LOG1, FL("tid: %d, dialog_token: %d, status: %d, buff_size: %d"),
+		tid, frm.DialogToken.token, frm.Status.status,
+		frm.addba_param_set.buff_size);
+
+	status = dot11f_get_packed_addba_rsp_size(mac_ctx, &frm, &payload_size);
+	if (DOT11F_FAILED(status)) {
+		lim_log(mac_ctx, LOGP, FL("Failed to calculate the packed size for a ADDBA Response (0x%08x)."),
+			status);
+		/* We'll fall back on the worst case scenario: */
+		payload_size = sizeof(tDot11faddba_rsp);
+	} else if (DOT11F_WARNED(status)) {
+		lim_log(mac_ctx, LOGW, FL("There were warnings while calculating the packed size for a ADDBA Response (0x%08x)."), status);
+	}
+
+	num_bytes = payload_size + sizeof(*mgmt_hdr);
+	qdf_status = cds_packet_alloc(num_bytes, (void **)&frame_ptr,
+				      (void **)&pkt_ptr);
+	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
+		lim_log(mac_ctx, LOGP,
+			FL("Failed to allocate %d bytes for a ADDBA response action frame"), num_bytes);
+		return QDF_STATUS_E_FAILURE;
+	}
+	qdf_mem_set(frame_ptr, num_bytes, 0);
+
+	lim_populate_mac_header(mac_ctx, frame_ptr, SIR_MAC_MGMT_FRAME,
+		SIR_MAC_MGMT_ACTION, peer_mac, session->selfMacAddr);
+
+	/* Update A3 with the BSSID */
+	mgmt_hdr = (tpSirMacMgmtHdr) frame_ptr;
+	sir_copy_mac_addr(mgmt_hdr->bssId, session->bssId);
+
+	/* ADDBA Response is a robust mgmt action frame,
+	 * set the "protect" (aka WEP) bit in the FC
+	 */
+	lim_set_protected_bit(mac_ctx, session, peer_mac, mgmt_hdr);
+
+	status = dot11f_pack_addba_rsp(mac_ctx, &frm,
+			frame_ptr + sizeof(tSirMacMgmtHdr), payload_size,
+			&payload_size);
+
+	if (DOT11F_FAILED(status)) {
+		lim_log(mac_ctx, LOGE,
+			FL("Failed to pack a ADDBA Response (0x%08x)."),
+			status);
+		qdf_status = QDF_STATUS_E_FAILURE;
+		goto error_addba_rsp;
+	} else if (DOT11F_WARNED(status)) {
+		lim_log(mac_ctx, LOGW, FL("There were warnings while packing ADDBA Response (0x%08x)."),
+			status);
+	}
+
+
+	if ((SIR_BAND_5_GHZ == lim_get_rf_band(session->currentOperChannel))
+#ifdef WLAN_FEATURE_P2P
+	    || (session->pePersona == QDF_P2P_CLIENT_MODE) ||
+	    (session->pePersona == QDF_P2P_GO_MODE)
+#endif
+	    ) {
+		tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+	}
+
+	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+			 session->peSessionId, mgmt_hdr->fc.subType));
+	qdf_status = wma_tx_frame(mac_ctx, pkt_ptr, (uint16_t) num_bytes,
+			TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
+			lim_tx_complete, frame_ptr, tx_flag, sme_sessionid, 0);
+	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+			 session->peSessionId, qdf_status));
+	if (QDF_STATUS_SUCCESS != qdf_status) {
+		lim_log(mac_ctx, LOGE, FL("wma_tx_frame FAILED! Status [%d]"),
+			qdf_status);
+		qdf_status = QDF_STATUS_E_FAILURE;
+		/*
+		 * wma_tx_frame free memory in certain cases, free pkt_ptr
+		 * only if not freed already.
+		 */
+		if (pkt_ptr)
+			cds_packet_free((void *)pkt_ptr);
+		return qdf_status;
+	} else {
+		return eSIR_SUCCESS;
+	}
+
+error_addba_rsp:
+	cds_packet_free((void *)pkt_ptr);
+	return qdf_status;
+}

+ 2 - 0
core/mac/src/pe/lim/lim_types.h

@@ -908,4 +908,6 @@ enum {
 	eDBG
 };
 
+QDF_STATUS lim_send_addba_response_frame(tpAniSirGlobal mac_ctx,
+		tSirMacAddr peer_mac, uint16_t tid, tpPESession session);
 #endif /* __LIM_TYPES_H */

File diff suppressed because it is too large
+ 351 - 299
core/mac/src/sys/legacy/src/utils/src/dot11f.c


Some files were not shown because too many files changed in this diff