Browse Source

qcacld-3.0: Send CSA/ECSA Switch count offset in Beacon Template to FW

During a channel switch, host sends the beacon template to the FW.
Currently the CSA/ECSA Channel Switch count offset fields in the
WMI_BCN_TMPL_CMDID fixed params are not filled from the host.

Add changes to calculate the CSA/ECSA Switch count offset from
start of the beacon template data and fill it in the fixed
params field for WMI_BCN_TMPL_CMDID.

Change-Id: Icb568f59346972784c4aceef9b42c8543adaa889
CRs-Fixed: 2246600
Vignesh Viswanathan 7 years ago
parent
commit
8777d3b250

+ 3 - 0
core/mac/src/pe/include/sch_global.h

@@ -57,6 +57,9 @@ struct schMisc {
 
 	uint16_t p2pIeOffset;
 
+	/* CSA and ECSA Switch Count Offsets to be sent to FW */
+	uint32_t csa_count_offset;
+	uint32_t ecsa_count_offset;
 };
 
 /* ****************** MISC defs ********************************* */

+ 10 - 1
core/mac/src/pe/sch/sch_api.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -140,6 +140,15 @@ tSirRetStatus sch_send_beacon_req(tpAniSirGlobal pMac, uint8_t *beaconPayload,
 		beaconParams->timIeOffset = 0;
 	} else {
 		beaconParams->timIeOffset = psessionEntry->schBeaconOffsetBegin;
+		if (psessionEntry->dfsIncludeChanSwIe) {
+			beaconParams->csa_count_offset =
+				pMac->sch.schObject.csa_count_offset;
+			beaconParams->ecsa_count_offset =
+				pMac->sch.schObject.ecsa_count_offset;
+			pe_debug("csa_count_offset %d ecsa_count_offset %d",
+				 beaconParams->csa_count_offset,
+				 beaconParams->ecsa_count_offset);
+		}
 	}
 
 	/* p2pIeOffset should be atleast greater than timIeOffset */

+ 72 - 0
core/mac/src/pe/sch/sch_beacon_gen.c

@@ -43,6 +43,9 @@
 #include "parser_api.h"
 #include "wlan_utility.h"
 
+/* Offset of Channel Switch count field in CSA/ECSA IE */
+#define SCH_CSA_SWITCH_COUNT_OFFSET 2
+#define SCH_ECSA_SWITCH_COUNT_OFFSET 3
 
 const uint8_t p2p_oui[] = { 0x50, 0x6F, 0x9A, 0x9 };
 
@@ -152,6 +155,53 @@ sch_append_addn_ie(tpAniSirGlobal mac_ctx, tpPESession session,
 	return status;
 }
 
+/**
+ * sch_get_csa_ecsa_count_offset() - get the offset of Switch count field
+ * @ie: pointer to the beggining of IEs in the beacon frame buffer
+ * @ie_len: length of the IEs in the buffer
+ * @csa_count_offset: pointer to the csa_count_offset variable in the caller
+ * @ecsa_count_offset: pointer to the ecsa_count_offset variable in the caller
+ *
+ * Gets the offset of the switch count field in the CSA/ECSA IEs from the start
+ * of the IEs buffer.
+ *
+ * Return: None
+ */
+static void sch_get_csa_ecsa_count_offset(uint8_t *ie, uint32_t ie_len,
+					  uint32_t *csa_count_offset,
+					  uint32_t *ecsa_count_offset)
+{
+	uint8_t *ptr = ie;
+	uint8_t elem_id;
+	uint16_t elem_len;
+	uint32_t offset = 0;
+
+	/* IE is not present */
+	if (!ie_len)
+		return;
+
+	while (ie_len >= 2) {
+		elem_id = ptr[0];
+		elem_len = ptr[1];
+		ie_len -= 2;
+		offset += 2;
+
+		if (elem_id == DOT11F_EID_CHANSWITCHANN &&
+		    elem_len == 3)
+			*csa_count_offset = offset +
+					SCH_CSA_SWITCH_COUNT_OFFSET;
+
+		if (elem_id == DOT11F_EID_EXT_CHAN_SWITCH_ANN &&
+		    elem_len == 4)
+			*ecsa_count_offset = offset +
+					SCH_ECSA_SWITCH_COUNT_OFFSET;
+
+		ie_len -= elem_len;
+		offset += elem_len;
+		ptr += (elem_len + 2);
+	}
+}
+
 /**
  * sch_set_fixed_beacon_fields() - sets the fixed params in beacon frame
  * @mac_ctx:       mac global context
@@ -179,6 +229,8 @@ sch_set_fixed_beacon_fields(tpAniSirGlobal mac_ctx, tpPESession session)
 	uint32_t extra_ie_len = 0;
 	uint16_t extra_ie_offset = 0;
 	uint16_t p2p_ie_offset = 0;
+	uint32_t csa_count_offset = 0;
+	uint32_t ecsa_count_offset = 0;
 	tSirRetStatus status = eSIR_SUCCESS;
 	bool is_vht_enabled = false;
 	uint16_t addn_ielen = 0;
@@ -538,6 +590,26 @@ sch_set_fixed_beacon_fields(tpAniSirGlobal mac_ctx, tpPESession session)
 			n_status);
 	}
 
+	/* Fill the CSA/ECSA count offsets if the IEs are present */
+	if (session->dfsIncludeChanSwIe)
+		sch_get_csa_ecsa_count_offset(session->pSchBeaconFrameEnd,
+					      n_bytes,
+					      &csa_count_offset,
+					      &ecsa_count_offset);
+
+	if (csa_count_offset)
+		mac_ctx->sch.schObject.csa_count_offset =
+				session->schBeaconOffsetBegin + TIM_IE_SIZE +
+				csa_count_offset;
+	if (ecsa_count_offset)
+		mac_ctx->sch.schObject.ecsa_count_offset =
+				session->schBeaconOffsetBegin + TIM_IE_SIZE +
+				ecsa_count_offset;
+
+	pe_debug("csa_count_offset %d ecsa_count_offset %d",
+		 mac_ctx->sch.schObject.csa_count_offset,
+		 mac_ctx->sch.schObject.ecsa_count_offset);
+
 	extra_ie = session->pSchBeaconFrameEnd + n_bytes;
 	extra_ie_offset = n_bytes;
 

+ 4 - 0
core/wma/inc/wma_if.h

@@ -713,6 +713,8 @@ typedef struct sBeaconGenParams {
  * @beaconLength: beacon length of template
  * @timIeOffset: TIM IE offset
  * @p2pIeOffset: P2P IE offset
+ * @csa_count_offset: Offset of Switch count field in CSA IE
+ * @ecsa_count_offset: Offset of Switch count field in ECSA IE
  */
 typedef struct {
 	tSirMacAddr bssId;
@@ -720,6 +722,8 @@ typedef struct {
 	uint32_t beaconLength;
 	uint32_t timIeOffset;
 	uint16_t p2pIeOffset;
+	uint32_t csa_count_offset;
+	uint32_t ecsa_count_offset;
 } tSendbeaconParams, *tpSendbeaconParams;
 
 /**

+ 8 - 0
core/wma/src/wma_mgmt.c

@@ -2600,6 +2600,14 @@ static QDF_STATUS wma_unified_bcn_tmpl_send(tp_wma_handle wma,
 	params.tmpl_len = tmpl_len;
 	params.frm = frm;
 	params.tmpl_len_aligned = tmpl_len_aligned;
+	if (bcn_info->csa_count_offset &&
+	    (bcn_info->csa_count_offset > bytes_to_strip))
+		params.csa_switch_count_offset =
+			bcn_info->csa_count_offset - bytes_to_strip;
+	if (bcn_info->ecsa_count_offset &&
+	    (bcn_info->ecsa_count_offset > bytes_to_strip))
+		params.ext_csa_switch_count_offset =
+			bcn_info->ecsa_count_offset - bytes_to_strip;
 
 	ret = wmi_unified_beacon_tmpl_send_cmd(wma->wmi_handle,
 				 &params);