qcacld-3.0: Add iwpriv support to set HE bss color

Add iwpriv support to set HE bss color in SAP 11AX mode operation

Change-Id: Ib58b93e8a66d9154024e61581885c4a10d737631
CRs-Fixed: 2130322
diff --git a/Kbuild b/Kbuild
index eb18307..4a1a8eb 100644
--- a/Kbuild
+++ b/Kbuild
@@ -2199,6 +2199,7 @@
 
 ifeq ($(CONFIG_WLAN_FEATURE_11AX),y)
 CDEFINES += -DWLAN_FEATURE_11AX
+CDEFINES += -DWLAN_FEATURE_11AX_BSS_COLOR
 endif
 
 # Dummy flag for WIN/MCL converged data path compilation
diff --git a/core/hdd/inc/qc_sap_ioctl.h b/core/hdd/inc/qc_sap_ioctl.h
index a58fe76..eaea2b8 100644
--- a/core/hdd/inc/qc_sap_ioctl.h
+++ b/core/hdd/inc/qc_sap_ioctl.h
@@ -261,6 +261,7 @@
 	QCASAP_PARAM_RANGE_EXT,
 	QCSAP_SET_DEFAULT_AMPDU,
 	QCSAP_ENABLE_RTS_BURSTING,
+	QCASAP_SET_HE_BSS_COLOR,
 };
 
 int iw_get_channel_list(struct net_device *dev,
diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c
index d3c2b62..3b0b64b 100644
--- a/core/hdd/src/wlan_hdd_hostapd.c
+++ b/core/hdd/src/wlan_hdd_hostapd.c
@@ -3633,6 +3633,17 @@
 		break;
 	}
 
+	case QCASAP_SET_HE_BSS_COLOR:
+		if (adapter->device_mode != QDF_SAP_MODE)
+			return -EINVAL;
+
+		status = sme_set_he_bss_color(hHal, adapter->sessionId,
+				set_value);
+		if (QDF_STATUS_SUCCESS != status) {
+			hdd_err("SET_HE_BSS_COLOR failed");
+			return -EIO;
+		}
+		break;
 	case QCASAP_SET_DFS_NOL:
 		wlansap_set_dfs_nol(
 			WLAN_HDD_GET_SAP_CTX_PTR(adapter),
@@ -5663,6 +5674,9 @@
 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
 		0, "set_rxchainmask"
 	}, {
+		QCASAP_SET_HE_BSS_COLOR,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_he_bss_clr"
+	}, {
 		QCASAP_NSS_CMD,
 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_nss"
 	}, {
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index 42e2f58..c83259f 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -2719,6 +2719,20 @@
 };
 
 /**
+ * struct sir_set_he_bss_color
+ * @message_type: SME message type
+ * @length: size of struct sir_set_he_bss_color
+ * @session_id: Session ID
+ * @bss_color: bss color value
+ */
+struct sir_set_he_bss_color {
+	uint16_t message_type;
+	uint16_t length;
+	uint8_t session_id;
+	uint8_t bss_color;
+};
+
+/**
  * struct sir_create_session - Used for creating session in monitor mode
  * @type: SME host message type.
  * @msg_len: Length of the message.
diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h
index 2a88879..9eedf6d 100644
--- a/core/mac/inc/wni_api.h
+++ b/core/mac/inc/wni_api.h
@@ -248,6 +248,7 @@
 	eWNI_SME_DFS_CAC_COMPLETE,
 	eWNI_SME_UPDATE_CONFIG,
 	eWNI_SME_BT_ACTIVITY_INFO_IND,
+	eWNI_SME_SET_HE_BSS_COLOR,
 	eWNI_SME_MSG_TYPES_END
 };
 
diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c
index fa7ecd3..b90bbe6 100644
--- a/core/mac/src/pe/lim/lim_process_message_queue.c
+++ b/core/mac/src/pe/lim/lim_process_message_queue.c
@@ -1881,6 +1881,11 @@
 		qdf_mem_free((void *)msg->bodyptr);
 		msg->bodyptr = NULL;
 		break;
+	case eWNI_SME_SET_HE_BSS_COLOR:
+		lim_process_set_he_bss_color(mac_ctx, msg->bodyptr);
+		qdf_mem_free((void *)msg->bodyptr);
+		msg->bodyptr = NULL;
+		break;
 	case eWNI_SME_DEL_ALL_TDLS_PEERS:
 		lim_process_sme_del_all_tdls_peers(mac_ctx, msg->bodyptr);
 		qdf_mem_free((void *)msg->bodyptr);
diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c
index b5b5c06..10bcdd0 100644
--- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c
+++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c
@@ -6046,3 +6046,59 @@
 		pe_err("Unable to send ExtCap to FW");
 
 }
+
+#ifdef WLAN_FEATURE_11AX_BSS_COLOR
+void lim_process_set_he_bss_color(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
+{
+	struct sir_set_he_bss_color *bss_color;
+	tpPESession session_entry = NULL;
+	tUpdateBeaconParams beacon_params;
+
+	if (!msg_buf) {
+		pe_err("Buffer is Pointing to NULL");
+		return;
+	}
+
+	bss_color = (struct sir_set_he_bss_color *)msg_buf;
+	session_entry = pe_find_session_by_sme_session_id(mac_ctx,
+				bss_color->session_id);
+	if (!session_entry) {
+		pe_err("Session not found for given session_id %d",
+			bss_color->session_id);
+		return;
+	}
+
+	if (session_entry->valid && !LIM_IS_AP_ROLE(session_entry)) {
+		pe_err("Invalid SystemRole %d",
+			GET_LIM_SYSTEM_ROLE(session_entry));
+		return;
+	}
+
+	if (bss_color->bss_color == session_entry->he_op.bss_color) {
+		pe_err("No change in  BSS color, current BSS color %d",
+			bss_color->bss_color);
+		return;
+	}
+	qdf_mem_zero(&beacon_params, sizeof(beacon_params));
+	beacon_params.paramChangeBitmap |= PARAM_BSS_COLOR_CHANGED;
+	session_entry->he_op.bss_col_disabled = 1;
+	session_entry->he_bss_color_change.countdown =
+		BSS_COLOR_SWITCH_COUNTDOWN;
+	session_entry->he_bss_color_change.new_color = bss_color->bss_color;
+	session_entry->he_op.bss_color =
+		session_entry->he_bss_color_change.new_color;
+	WMI_HEOPS_COLOR_SET(beacon_params.he_ops,
+			session_entry->he_op.bss_color);
+	WMI_HEOPS_BSSCOLORDISABLE_SET(beacon_params.he_ops,
+			session_entry->he_op.bss_col_disabled);
+	session_entry->bss_color_changing = 1;
+
+	if (sch_set_fixed_beacon_fields(mac_ctx, session_entry) !=
+			eSIR_SUCCESS) {
+		pe_err("Unable to set op mode IE in beacon");
+		return;
+	}
+
+	lim_send_beacon_params(mac_ctx, &beacon_params, session_entry);
+}
+#endif
diff --git a/core/mac/src/pe/lim/lim_prop_exts_utils.c b/core/mac/src/pe/lim/lim_prop_exts_utils.c
index 81baf38..1b2902f 100644
--- a/core/mac/src/pe/lim/lim_prop_exts_utils.c
+++ b/core/mac/src/pe/lim/lim_prop_exts_utils.c
@@ -234,7 +234,22 @@
 
 	return false;
 }
-
+#ifdef WLAN_FEATURE_11AX
+static void lim_extract_he_op(tpPESession session,
+		tSirProbeRespBeacon *beacon_struct)
+{
+	if (session->he_capable && beacon_struct->he_op.present) {
+		qdf_mem_copy(&session->he_op, &beacon_struct->he_op,
+				sizeof(session->he_op));
+		pe_debug("he_op.bss_color %d", session->he_op.bss_color);
+		pe_debug("he_op.default_pe %d", session->he_op.default_pe);
+	}
+}
+#else
+static inline void lim_extract_he_op(tpPESession session,
+		tSirProbeRespBeacon *beacon_struct)
+{}
+#endif
 /**
  * lim_extract_ap_capability() - extract AP's HCF/WME/WSM capability
  * @mac_ctx: Pointer to Global MAC structure
@@ -469,6 +484,7 @@
 			pe_err("AP does not support op_mode rx");
 		}
 	}
+	lim_extract_he_op(session, beacon_struct);
 	/* Extract the UAPSD flag from WMM Parameter element */
 	if (beacon_struct->wmeEdcaPresent)
 		*uapsd = beacon_struct->edcaParams.qosInfo.uapsd;
diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h
index d29b7ec..b56fed2 100644
--- a/core/mac/src/pe/lim/lim_types.h
+++ b/core/mac/src/pe/lim/lim_types.h
@@ -497,6 +497,21 @@
 		tLimMlmReassocReq *reassoc_req, tpPESession pe_session)
 {}
 #endif
+#ifdef WLAN_FEATURE_11AX_BSS_COLOR
+/**
+ * lim_process_set_he_bss_color() - process the set he bss color request
+ *
+ * @mac_ctx: global mac context pointer
+ * @msg_buf: message buffer pointer
+ *
+ * Return: void
+ */
+void lim_process_set_he_bss_color(tpAniSirGlobal mac_ctx, uint32_t *msg_buf);
+#else
+static inline void lim_process_set_he_bss_color(tpAniSirGlobal mac_ctx,
+		uint32_t *msg_buf)
+{}
+#endif
 void lim_send_delts_req_action_frame(tpAniSirGlobal pMac, tSirMacAddr peer,
 				     uint8_t wmmTspecPresent,
 				     tSirMacTSInfo * pTsinfo,
diff --git a/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/core/mac/src/sys/legacy/src/utils/src/parser_api.c
index bac29fb..9692d52 100644
--- a/core/mac/src/sys/legacy/src/utils/src/parser_api.c
+++ b/core/mac/src/sys/legacy/src/utils/src/parser_api.c
@@ -2351,6 +2351,24 @@
 }
 #endif
 
+#ifdef WLAN_FEATURE_11AX_BSS_COLOR
+static void update_bss_color_change_ie_from_probe_rsp(
+		tDot11fProbeResponse *prb_frm,
+		tpSirProbeRespBeacon prb_rsp_struct)
+{
+	if (prb_frm->bss_color_change.present) {
+		pe_debug("11AX: HE BSS color change present");
+		qdf_mem_copy(&prb_rsp_struct->vendor_he_bss_color_change,
+			     &prb_frm->bss_color_change,
+			     sizeof(tDot11fIEbss_color_change));
+	}
+}
+#else
+static inline void update_bss_color_change_ie_from_probe_rsp(
+		tDot11fProbeResponse *prb_frm,
+		tpSirProbeRespBeacon prb_rsp_struct)
+{}
+#endif
 tSirRetStatus sir_convert_probe_frame2_struct(tpAniSirGlobal pMac,
 					      uint8_t *pFrame,
 					      uint32_t nFrame,
@@ -2624,6 +2642,8 @@
 			     sizeof(tDot11fIEhe_op));
 	}
 
+	update_bss_color_change_ie_from_probe_rsp(pr, pProbeResp);
+
 	qdf_mem_free(pr);
 	return eSIR_SUCCESS;
 
@@ -3150,6 +3170,11 @@
 		pe_debug("11AX: HE Operation IE present");
 		qdf_mem_copy(&pAssocRsp->he_op, &ar->he_op,
 			     sizeof(tDot11fIEhe_op));
+		pe_debug("bss_clr %d def_pe %d part_bss_clr %d bss_col_dis %d",
+				pAssocRsp->he_op.bss_color,
+				pAssocRsp->he_op.default_pe,
+				pAssocRsp->he_op.partial_bss_col,
+				pAssocRsp->he_op.bss_col_disabled);
 	}
 
 	if (ar->MBO_IE.present && ar->MBO_IE.rssi_assoc_rej.present) {
@@ -3624,6 +3649,23 @@
 
 #endif /* FEATURE_WLAN_ESE */
 
+#ifdef WLAN_FEATURE_11AX_BSS_COLOR
+static void update_bss_color_change_from_beacon_ies(tDot11fBeaconIEs *bcn_ies,
+		tpSirProbeRespBeacon bcn_struct)
+{
+	if (bcn_ies->bss_color_change.present) {
+		qdf_mem_copy(&bcn_struct->vendor_he_bss_color_change,
+			     &bcn_ies->bss_color_change,
+			     sizeof(tDot11fIEbss_color_change));
+	}
+}
+#else
+static inline void update_bss_color_change_from_beacon_ies(
+		tDot11fBeaconIEs *bcn_ies,
+		tpSirProbeRespBeacon bcn_struct)
+{}
+#endif
+
 tSirRetStatus
 sir_parse_beacon_ie(tpAniSirGlobal pMac,
 		    tpSirProbeRespBeacon pBeaconStruct,
@@ -3904,20 +3946,37 @@
 	}
 
 	if (pBies->he_cap.present) {
-		qdf_mem_copy(&pBeaconStruct->he_cap,
-			     &pBies->he_cap,
+		qdf_mem_copy(&pBeaconStruct->he_cap, &pBies->he_cap,
 			     sizeof(tDot11fIEhe_cap));
 	}
 	if (pBies->he_op.present) {
-		qdf_mem_copy(&pBeaconStruct->he_op,
-			     &pBies->he_op,
+		qdf_mem_copy(&pBeaconStruct->he_op, &pBies->he_op,
 			     sizeof(tDot11fIEhe_op));
 	}
 
+	update_bss_color_change_from_beacon_ies(pBies, pBeaconStruct);
+
 	qdf_mem_free(pBies);
 	return eSIR_SUCCESS;
 } /* End sir_parse_beacon_ie. */
 
+#ifdef WLAN_FEATURE_11AX_BSS_COLOR
+static void convert_bcon_bss_color_change_ie(tDot11fBeacon *bcn_frm,
+		tpSirProbeRespBeacon bcn_struct)
+{
+	if (bcn_frm->bss_color_change.present) {
+		pe_debug("11AX: HE BSS color change present");
+		qdf_mem_copy(&bcn_struct->vendor_he_bss_color_change,
+			     &bcn_frm->bss_color_change,
+			     sizeof(tDot11fIEbss_color_change));
+	}
+}
+#else
+static inline void convert_bcon_bss_color_change_ie(tDot11fBeacon *bcn_frm,
+		tpSirProbeRespBeacon bcn_struct)
+{}
+#endif
+
 tSirRetStatus
 sir_convert_beacon_frame2_struct(tpAniSirGlobal pMac,
 				 uint8_t *pFrame,
@@ -4282,6 +4341,8 @@
 			     sizeof(tDot11fIEhe_op));
 	}
 
+	convert_bcon_bss_color_change_ie(pBeacon, pBeaconStruct);
+
 	qdf_mem_free(pBeacon);
 	return eSIR_SUCCESS;
 
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index 77d9784..76de331 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -1856,4 +1856,23 @@
 {}
 
 #endif
+#ifdef WLAN_FEATURE_11AX_BSS_COLOR
+/**
+ * sme_set_he_bss_color() - Sets the HE BSS color
+ *
+ * @hal: The handle returned by mac_open
+ * @session_id: session_id of the request
+ * @bss_color: HE BSS color value to set
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS sme_set_he_bss_color(tHalHandle hal, uint8_t session_id,
+		uint8_t bss_color);
+#else
+static inline QDF_STATUS sme_set_he_bss_color(tHalHandle hal,
+		uint8_t session_id, uint8_t bss_color)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
 #endif /* #if !defined( __SME_API_H ) */
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index afc368b..be2f0cd 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -14792,6 +14792,42 @@
 		vdev_nss->tdls, vdev_nss->ocb);
 }
 
+#ifdef WLAN_FEATURE_11AX_BSS_COLOR
+#define MAX_BSS_COLOR_VAL 63
+#define MIN_BSS_COLOR_VAL 1
+
+QDF_STATUS sme_set_he_bss_color(tHalHandle hal, uint8_t session_id,
+		uint8_t bss_color)
+
+{
+	struct sir_set_he_bss_color *bss_color_msg;
+	uint8_t len;
+
+	if (!hal) {
+		sme_err("Invalid hal pointer");
+		return QDF_STATUS_E_FAULT;
+	}
+
+	sme_debug("Set HE bss_color  %d", bss_color);
+
+	if (bss_color < MIN_BSS_COLOR_VAL || bss_color > MAX_BSS_COLOR_VAL) {
+		sme_debug("Invalid HE bss_color  %d", bss_color);
+		return QDF_STATUS_E_INVAL;
+	}
+	len = sizeof(*bss_color_msg);
+	bss_color_msg = qdf_mem_malloc(len);
+	if (!bss_color_msg) {
+		sme_err("mem alloc failed");
+		return QDF_STATUS_E_NOMEM;
+	}
+	bss_color_msg->message_type = eWNI_SME_SET_HE_BSS_COLOR;
+	bss_color_msg->length = len;
+	bss_color_msg->session_id = session_id;
+	bss_color_msg->bss_color = bss_color;
+	return umac_send_mb_message_to_mac(bss_color_msg);
+}
+#endif
+
 /**
  * sme_update_hw_dbs_capable() - sets the HW DBS capability
  * @hal: Pointer to HAL