Преглед изворни кода

qcacld-3.0: Add obss detection offload support

Add support for obss detection offload support.

Change-Id: I27fdef1604f6f92890dda024fbc8f9d13df602a3
CRs-Fixed: 2170187
Arif Hussain пре 7 година
родитељ
комит
ee10f9089e

+ 63 - 58
components/pmo/core/src/wlan_pmo_wow.c

@@ -49,7 +49,7 @@ QDF_STATUS pmo_core_add_wow_user_pattern(struct wlan_objmgr_vdev *vdev,
 	pmo_set_wow_default_ptrn(vdev_ctx, 0);
 
 	pmo_debug("Add user passed wow pattern id %d vdev id %d",
-		ptrn->pattern_id, ptrn->session_id);
+		  ptrn->pattern_id, ptrn->session_id);
 	/*
 	 * Convert received pattern mask value from bit representation
 	 * to byte representation.
@@ -72,15 +72,17 @@ QDF_STATUS pmo_core_add_wow_user_pattern(struct wlan_objmgr_vdev *vdev,
 			       (pos % PMO_NUM_BITS_IN_BYTE);
 		bit_to_check = 0x1 << bit_to_check;
 		if (ptrn->pattern_mask[pos / PMO_NUM_BITS_IN_BYTE] &
-							bit_to_check)
+		    bit_to_check)
 			new_mask[pos] = PMO_WOW_PTRN_MASK_VALID;
 	}
 
 	status = pmo_tgt_send_wow_patterns_to_fw(vdev,
-			ptrn->pattern_id,
-			ptrn->pattern, ptrn->pattern_size,
-			ptrn->pattern_byte_offset, new_mask,
-			ptrn->pattern_size, true);
+						 ptrn->pattern_id,
+						 ptrn->pattern,
+						 ptrn->pattern_size,
+						 ptrn->pattern_byte_offset,
+						 new_mask,
+						 ptrn->pattern_size, true);
 	if (status != QDF_STATUS_SUCCESS)
 		pmo_err("Failed to add wow pattern %d", ptrn->pattern_id);
 
@@ -110,7 +112,7 @@ QDF_STATUS pmo_core_del_wow_user_pattern(struct wlan_objmgr_vdev *vdev,
 	}
 
 	pmo_debug("Delete user passed wow pattern id %d total user pattern %d",
-		pattern_id, pmo_get_wow_user_ptrn(vdev_ctx));
+		  pattern_id, pmo_get_wow_user_ptrn(vdev_ctx));
 
 	pmo_tgt_del_wow_pattern(vdev, pattern_id, true);
 
@@ -160,7 +162,7 @@ void pmo_core_enable_wakeup_event(struct wlan_objmgr_psoc *psoc,
 		goto out;
 
 	pmo_info("enable wakeup event vdev_id %d wake up event 0x%x%x%x%x",
-		vdev_id, bitmap[0], bitmap[1], bitmap[2], bitmap[3]);
+		 vdev_id, bitmap[0], bitmap[1], bitmap[2], bitmap[3]);
 	pmo_tgt_enable_wow_wakeup_event(vdev, bitmap);
 
 	pmo_vdev_put_ref(vdev);
@@ -192,7 +194,7 @@ void pmo_core_disable_wakeup_event(struct wlan_objmgr_psoc *psoc,
 		goto out;
 
 	pmo_info("Disable wakeup event vdev_id %d wake up event 0x%x%x%x%x",
-		vdev_id, bitmap[0], bitmap[1], bitmap[2], bitmap[3]);
+		 vdev_id, bitmap[0], bitmap[1], bitmap[2], bitmap[3]);
 	pmo_tgt_disable_wow_wakeup_event(vdev, bitmap);
 
 	pmo_vdev_put_ref(vdev);
@@ -228,7 +230,7 @@ bool pmo_is_beaconing_vdev_up(struct wlan_objmgr_psoc *psoc)
 
 		vdev_opmode = pmo_get_vdev_opmode(vdev);
 		is_beaconing = pmo_is_vdev_in_beaconning_mode(vdev_opmode) &&
-			pmo_is_vdev_up(vdev);
+			       pmo_is_vdev_up(vdev);
 
 		pmo_vdev_put_ref(vdev);
 
@@ -310,7 +312,7 @@ bool pmo_core_is_wow_applicable(struct wlan_objmgr_psoc *psoc)
 			is_wow_applicable = true;
 		} else if (pmo_core_get_vdev_op_mode(vdev) == QDF_NDI_MODE) {
 			pmo_debug("vdev %d is in NAN data mode, enabling wow",
-				vdev_id);
+				  vdev_id);
 			is_wow_applicable = true;
 		}
 
@@ -321,7 +323,7 @@ bool pmo_core_is_wow_applicable(struct wlan_objmgr_psoc *psoc)
 	}
 
 	pmo_debug("All vdev are in disconnected state\n"
-		"and pno/extscan is not in progress, skipping wow");
+		  "and pno/extscan is not in progress, skipping wow");
 
 	return false;
 }
@@ -334,64 +336,64 @@ void pmo_set_wow_event_bitmap(WOW_WAKE_EVENT_TYPE event,
 
 	if (!bitmask || wow_bitmap_size < PMO_WOW_MAX_EVENT_BM_LEN) {
 		pmo_err("wow bitmask length shorter than %d",
-			 PMO_WOW_MAX_EVENT_BM_LEN);
+			PMO_WOW_MAX_EVENT_BM_LEN);
 		return;
 	}
 	pmo_get_event_bitmap_idx(event, wow_bitmap_size, &bit_idx, &idx);
 	bitmask[idx] |= 1 << bit_idx;
 
 	pmo_debug("%s: bitmask updated %x%x%x%x",
-		 __func__, bitmask[0], bitmask[1], bitmask[2], bitmask[3]);
+		  __func__, bitmask[0], bitmask[1], bitmask[2], bitmask[3]);
 }
 
 void pmo_set_sta_wow_bitmask(uint32_t *bitmask, uint32_t wow_bitmap_size)
 {
 
 	pmo_set_wow_event_bitmap(WOW_CSA_IE_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_CLIENT_KICKOUT_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_PATTERN_MATCH_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_MAGIC_PKT_RECVD_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_DEAUTH_RECVD_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_DISASSOC_RECVD_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_BMISS_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_GTK_ERR_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_BETTER_AP_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_HTT_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_RA_MATCH_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_NLO_DETECTED_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_EXTSCAN_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_OEM_RESPONSE_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_TDLS_CONN_TRACKER_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_11D_SCAN_EVENT,
 				 wow_bitmap_size,
 				 bitmask);
@@ -402,24 +404,27 @@ void pmo_set_sap_wow_bitmask(uint32_t *bitmask, uint32_t wow_bitmap_size)
 {
 
 	pmo_set_wow_event_bitmap(WOW_PROBE_REQ_WPS_IE_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_PATTERN_MATCH_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_AUTH_REQ_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_ASSOC_REQ_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_DEAUTH_RECVD_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_DISASSOC_RECVD_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
 	pmo_set_wow_event_bitmap(WOW_HTT_EVENT,
-			     wow_bitmap_size,
-			     bitmask);
+				 wow_bitmap_size,
+				 bitmask);
+	pmo_set_wow_event_bitmap(WOW_SAP_OBSS_DETECTION_EVENT,
+				 wow_bitmap_size,
+				 bitmask);
 }

+ 16 - 10
core/hdd/src/wlan_hdd_main.c

@@ -1849,6 +1849,7 @@ void hdd_update_tgt_cfg(void *context, void *param)
 	uint8_t temp_band_cap;
 	struct cds_config_info *cds_cfg = cds_get_ini_config();
 	uint8_t antenna_mode;
+	QDF_STATUS status;
 
 	ret = hdd_objmgr_create_and_store_pdev(hdd_ctx);
 	if (ret) {
@@ -1856,7 +1857,7 @@ void hdd_update_tgt_cfg(void *context, void *param)
 		QDF_BUG(0);
 	} else {
 		hdd_debug("New pdev has been created with pdev_id = %u",
-			hdd_ctx->hdd_pdev->pdev_objmgr.wlan_pdev_id);
+			  hdd_ctx->hdd_pdev->pdev_objmgr.wlan_pdev_id);
 	}
 
 	ret = hdd_update_green_ap_config(hdd_ctx);
@@ -1952,13 +1953,13 @@ void hdd_update_tgt_cfg(void *context, void *param)
 	hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
 	hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
 	hdd_debug("fine_time_meas_cap: 0x%x",
-		hdd_ctx->config->fine_time_meas_cap);
+		  hdd_ctx->config->fine_time_meas_cap);
 
 	antenna_mode = (hdd_ctx->config->enable2x2 == 0x01) ?
 			HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
 	hdd_update_smps_antenna_mode(hdd_ctx, antenna_mode);
 	hdd_debug("Init current antenna mode: %d",
-		 hdd_ctx->current_antenna_mode);
+		  hdd_ctx->current_antenna_mode);
 
 	hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
 				hdd_ctx->config->bpf_packet_filter_enable);
@@ -1966,20 +1967,21 @@ void hdd_update_tgt_cfg(void *context, void *param)
 	hdd_update_ra_rate_limit(hdd_ctx, cfg);
 
 	if ((hdd_ctx->config->txBFCsnValue >
-		WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_FW_DEF) &&
-						!cfg->tx_bfee_8ss_enabled)
+	     WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_FW_DEF) &&
+	    !cfg->tx_bfee_8ss_enabled)
 		hdd_ctx->config->txBFCsnValue =
 			WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_FW_DEF;
 
-	if (sme_cfg_set_int(hdd_ctx->hHal,
-			WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED,
-			hdd_ctx->config->txBFCsnValue) == QDF_STATUS_E_FAILURE)
+	status = sme_cfg_set_int(hdd_ctx->hHal,
+				 WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED,
+				 hdd_ctx->config->txBFCsnValue);
+	if (QDF_IS_STATUS_ERROR(status))
 		hdd_err("fw update WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED to CFG fails");
 
 
 	hdd_debug("Target BPF %d Host BPF %d 8ss fw support %d txBFCsnValue %d",
-		cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable,
-		cfg->tx_bfee_8ss_enabled, hdd_ctx->config->txBFCsnValue);
+		  cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable,
+		  cfg->tx_bfee_8ss_enabled, hdd_ctx->config->txBFCsnValue);
 
 	/*
 	 * Update txBFCsnValue and NumSoundingDim values to vhtcap in wiphy
@@ -2006,6 +2008,10 @@ void hdd_update_tgt_cfg(void *context, void *param)
 	hdd_nan_datapath_target_config(hdd_ctx, cfg);
 	hdd_ctx->dfs_cac_offload = cfg->dfs_cac_offload;
 	hdd_ctx->lte_coex_ant_share = cfg->services.lte_coex_ant_share;
+	status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_OBSS_DETECTION_OFFLOAD,
+				 cfg->obss_detection_offloaded);
+	if (QDF_IS_STATUS_ERROR(status))
+		hdd_err("Couldn't pass WNI_CFG_OBSS_DETECTION_OFFLOAD to CFG");
 }
 
 bool hdd_dfs_indicate_radar(struct hdd_context *hdd_ctx)

+ 1 - 0
core/mac/inc/ani_global.h

@@ -828,6 +828,7 @@ typedef struct sAniSirLim {
 	uint8_t scan_disabled;
 	uint8_t beacon_probe_rsp_cnt_per_scan;
 	wlan_scan_requester req_id;
+	uint8_t obss_detection_offloaded;
 } tAniSirLim, *tpAniSirLim;
 
 struct mgmt_frm_reg_info {

+ 1 - 0
core/mac/inc/wni_cfg.h

@@ -353,6 +353,7 @@ enum {
 	WNI_CFG_EDCA_ETSI_ACBE,
 	WNI_CFG_EDCA_ETSI_ACVI,
 	WNI_CFG_EDCA_ETSI_ACVO,
+	WNI_CFG_OBSS_DETECTION_OFFLOAD,
 	/* Any new items to be added should be above this strictly */
 	CFG_PARAM_MAX_NUM
 };

+ 1 - 0
core/mac/src/cfg/cfg_param_name.c

@@ -355,6 +355,7 @@ const char *cfg_get_string(uint16_t cfg_id)
 	CASE_RETURN_STRING(WNI_CFG_EDCA_ETSI_ACBE);
 	CASE_RETURN_STRING(WNI_CFG_EDCA_ETSI_ACVI);
 	CASE_RETURN_STRING(WNI_CFG_EDCA_ETSI_ACVO);
+	CASE_RETURN_STRING(WNI_CFG_OBSS_DETECTION_OFFLOAD);
 	}
 
 	return "invalid";

+ 3 - 0
core/mac/src/cfg/cfg_proc_msg.c

@@ -1581,6 +1581,9 @@ cgstatic cfg_static[CFG_PARAM_MAX_NUM] = {
 	{WNI_CFG_EDCA_ETSI_ACVO,
 	 CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART,
 	 0, 0, 0},
+	{WNI_CFG_OBSS_DETECTION_OFFLOAD,
+	 CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT,
+	 0, 1, 0},
 };
 
 

+ 3 - 1
core/mac/src/include/sir_params.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -678,6 +678,8 @@ typedef struct sSirMbMsgP2p {
 
 #define SIR_HAL_SET_DEL_PMKID_CACHE         (SIR_HAL_ITC_MSG_TYPES_BEGIN + 391)
 #define SIR_HAL_HLP_IE_INFO                 (SIR_HAL_ITC_MSG_TYPES_BEGIN + 392)
+#define SIR_HAL_OBSS_DETECTION_REQ          (SIR_HAL_ITC_MSG_TYPES_BEGIN + 393)
+#define SIR_HAL_OBSS_DETECTION_INFO         (SIR_HAL_ITC_MSG_TYPES_BEGIN + 394)
 #define SIR_HAL_MSG_TYPES_END               (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
 
 /* CFG message types */

+ 22 - 0
core/mac/src/pe/include/lim_session.h

@@ -106,6 +106,26 @@ struct bss_color_info {
 };
 #endif
 
+/**
+ * struct obss_detection_cfg - current obss detection cfg set to firmware
+ * @obss_11b_ap_detect_mode: detection mode for 11b access point.
+ * @obss_11b_sta_detect_mode: detection mode for 11b station.
+ * @obss_11g_ap_detect_mode: detection mode for 11g access point.
+ * @obss_11a_detect_mode: detection mode for 11a access point.
+ * @obss_ht_legacy_detect_mode: detection mode for ht ap with legacy mode.
+ * @obss_ht_mixed_detect_mode: detection mode for ht ap with mixed mode.
+ * @obss_ht_20mhz_detect_mode: detection mode for ht ap with 20mhz mode.
+ */
+struct obss_detection_cfg {
+	uint8_t obss_11b_ap_detect_mode;
+	uint8_t obss_11b_sta_detect_mode;
+	uint8_t obss_11g_ap_detect_mode;
+	uint8_t obss_11a_detect_mode;
+	uint8_t obss_ht_legacy_detect_mode;
+	uint8_t obss_ht_mixed_detect_mode;
+	uint8_t obss_ht_20mhz_detect_mode;
+};
+
 typedef struct sPESession       /* Added to Support BT-AMP */
 {
 	/* To check session table is in use or free */
@@ -526,6 +546,8 @@ typedef struct sPESession       /* Added to Support BT-AMP */
 #endif
 	/* previous auth frame's sequence number */
 	uint16_t prev_auth_seq_num;
+	struct obss_detection_cfg obss_offload_cfg;
+	bool enable_obss_detection_offload;
 } tPESession, *tpPESession;
 
 /*-------------------------------------------------------------------------

+ 9 - 0
core/mac/src/pe/lim/lim_api.c

@@ -466,6 +466,15 @@ static tSirRetStatus __lim_init_config(tpAniSirGlobal pMac)
 		return eSIR_FAILURE;
 	}
 #endif
+
+	if (eSIR_SUCCESS != wlan_cfg_get_int(pMac,
+					     WNI_CFG_OBSS_DETECTION_OFFLOAD,
+					     (uint32_t *)&pMac->lim.
+					     obss_detection_offloaded)) {
+		pe_err("cfg get obss_detection_offloaded failed");
+		return eSIR_FAILURE;
+	}
+
 	return eSIR_SUCCESS;
 }
 

+ 5 - 1
core/mac/src/pe/lim/lim_process_message_queue.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.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -1900,6 +1900,10 @@ static void lim_process_messages(tpAniSirGlobal mac_ctx,
 		qdf_mem_free((void *)msg->bodyptr);
 		msg->bodyptr = NULL;
 		break;
+	case WMA_OBSS_DETECTION_INFO:
+		qdf_mem_free(msg->bodyptr);
+		msg->bodyptr = NULL;
+		break;
 	default:
 		qdf_mem_free((void *)msg->bodyptr);
 		msg->bodyptr = NULL;

+ 14 - 0
core/wma/inc/wma_internal.h

@@ -1350,4 +1350,18 @@ int wma_fill_beacon_interval_reset_req(tp_wma_handle wma, uint8_t vdev_id,
  * Return: 'true' on valid vdev else 'false'
  */
 bool wma_is_vdev_valid(uint32_t vdev_id);
+
+/**
+ * wma_vdev_obss_detection_info_handler - event handler to handle obss detection
+ * @handle: the wma handle
+ * @event: buffer with event
+ * @len: buffer length
+ *
+ * This function receives obss detection info from firmware which is used to
+ * decide obss protection.
+ *
+ * Return: 0 on success
+ */
+int wma_vdev_obss_detection_info_handler(void *handle, uint8_t *event,
+					 uint32_t len);
 #endif

+ 2 - 0
core/wma/inc/wma_tgt_cfg.h

@@ -159,6 +159,7 @@ struct wma_dfs_radar_ind {
  * @dfs_cac_offload: dfs and cac timer offloaded
  * @tx_bfee_8ss_enabled: Tx Beamformee support for 8x8
  * @rcpi_enabled: for checking rcpi support
+ * @obss_detection_offloaded: obss detection offloaded to firmware
  */
 struct wma_tgt_cfg {
 	uint32_t target_fw_version;
@@ -196,5 +197,6 @@ struct wma_tgt_cfg {
 	bool dfs_cac_offload;
 	bool tx_bfee_8ss_enabled;
 	bool rcpi_enabled;
+	bool obss_detection_offloaded;
 };
 #endif /* WMA_TGT_CFG_H */

+ 2 - 0
core/wma/inc/wma_types.h

@@ -476,6 +476,8 @@
 #define WMA_SET_ARP_STATS_REQ                SIR_HAL_SET_ARP_STATS_REQ
 #define WMA_GET_ARP_STATS_REQ                SIR_HAL_GET_ARP_STATS_REQ
 #define WMA_SET_LIMIT_OFF_CHAN               SIR_HAL_SET_LIMIT_OFF_CHAN
+#define WMA_OBSS_DETECTION_REQ               SIR_HAL_OBSS_DETECTION_REQ
+#define WMA_OBSS_DETECTION_INFO              SIR_HAL_OBSS_DETECTION_INFO
 
 /* Bit 6 will be used to control BD rate for Management frames */
 #define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40

+ 39 - 0
core/wma/src/wma_features.c

@@ -5253,3 +5253,42 @@ int wma_peer_ant_info_evt_handler(void *handle, u_int8_t *event,
 
 	return 0;
 }
+
+int wma_vdev_obss_detection_info_handler(void *handle, uint8_t *event,
+					 uint32_t len)
+{
+	tp_wma_handle wma = (tp_wma_handle) handle;
+	struct wmi_obss_detect_info *obss_detection;
+	QDF_STATUS status;
+
+	if (!event) {
+		WMA_LOGE("Invalid obss_detection_info event buffer");
+		return -EINVAL;
+	}
+
+	obss_detection = qdf_mem_malloc(sizeof(*obss_detection));
+	if (!obss_detection) {
+		WMA_LOGE("%s: Failed to malloc", __func__);
+		return -ENOMEM;
+	}
+
+	status = wmi_unified_extract_obss_detection_info(wma->wmi_handle,
+							 event, obss_detection);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		WMA_LOGE("%s: Failed to extract obss info", __func__);
+		qdf_mem_free(obss_detection);
+		return -EINVAL;
+	}
+
+	if (!wma_is_vdev_valid(obss_detection->vdev_id)) {
+		WMA_LOGE("%s: Invalid vdev id %d", __func__,
+			 obss_detection->vdev_id);
+		qdf_mem_free(obss_detection);
+		return -EINVAL;
+	}
+
+	wma_send_msg(wma, WMA_OBSS_DETECTION_INFO, obss_detection, 0);
+
+	return 0;
+}

+ 63 - 0
core/wma/src/wma_main.c

@@ -2951,6 +2951,11 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc,
 			wma_unified_phyerr_rx_event_handler,
 			WMA_RX_WORK_CTX);
 
+	wmi_unified_register_event_handler(wma_handle->wmi_handle,
+			wmi_sap_obss_detection_report_event_id,
+			wma_vdev_obss_detection_info_handler,
+			WMA_RX_SERIALIZER_CTX);
+
 	return QDF_STATUS_SUCCESS;
 
 err_dbglog_init:
@@ -4822,6 +4827,26 @@ static void wma_update_hdd_band_cap(WMI_PHY_CAPABILITY supported_band,
 	}
 }
 
+/**
+ * wma_update_obss_detection_support() - update obss detection offload support
+ * @wh: wma handle
+ * @tgt_cfg: target configuration to be updated
+ *
+ * Update obss detection offload support based on service bit.
+ *
+ * Return: None
+ */
+static void wma_update_obss_detection_support(tp_wma_handle wh,
+					      struct wma_tgt_cfg *tgt_cfg)
+{
+	if (WMI_SERVICE_EXT_IS_ENABLED(wh->wmi_service_bitmap,
+				       wh->wmi_service_ext_bitmap,
+				       WMI_SERVICE_AP_OBSS_DETECTION_OFFLOAD))
+		tgt_cfg->obss_detection_offloaded = true;
+	else
+		tgt_cfg->obss_detection_offloaded = false;
+}
+
 /**
  * wma_update_hdd_cfg() - update HDD config
  * @wma_handle: wma handle
@@ -4873,6 +4898,7 @@ static void wma_update_hdd_cfg(tp_wma_handle wma_handle)
 			      - WMI_TLV_HEADROOM;
 	wma_setup_egap_support(&tgt_cfg, wma_handle);
 	tgt_cfg.tx_bfee_8ss_enabled = wma_handle->tx_bfee_8ss_enabled;
+	wma_update_obss_detection_support(wma_handle, &tgt_cfg);
 	wma_update_hdd_cfg_ndp(wma_handle, &tgt_cfg);
 	wma_handle->tgt_cfg_update_cb(hdd_ctx, &tgt_cfg);
 }
@@ -7224,6 +7250,39 @@ static QDF_STATUS wma_process_limit_off_chan(tp_wma_handle wma_handle,
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * wma_send_obss_detection_cfg() - send obss detection cfg to firmware
+ * @wma_handle: pointer to wma handle
+ * @cfg: obss detection configuration
+ *
+ * Send obss detection configuration to firmware.
+ *
+ * Return: None
+ */
+static void wma_send_obss_detection_cfg(tp_wma_handle wma_handle,
+					struct wmi_obss_detection_cfg_param
+					*cfg)
+{
+	QDF_STATUS status;
+
+	if (cfg->vdev_id >= wma_handle->max_bssid) {
+		WMA_LOGE(FL("Invalid vdev_id: %d"), cfg->vdev_id);
+		return;
+	}
+	if (!wma_is_vdev_up(cfg->vdev_id)) {
+		WMA_LOGE("vdev %d is not up skipping obss detection req",
+			 cfg->vdev_id);
+		return;
+	}
+
+	status = wmi_unified_send_obss_detection_cfg_cmd(wma_handle->wmi_handle,
+							 cfg);
+	if (QDF_IS_STATUS_ERROR(status))
+		WMA_LOGE("Failed to send obss detection cfg");
+
+	return;
+}
+
 /**
  * wma_mc_process_msg() - process wma messages and call appropriate function.
  * @msg: message
@@ -8000,6 +8059,10 @@ static QDF_STATUS wma_mc_process_msg(struct scheduler_msg *msg)
 		wma_process_limit_off_chan(wma_handle, msg->bodyptr);
 		qdf_mem_free(msg->bodyptr);
 		break;
+	case WMA_OBSS_DETECTION_REQ:
+		wma_send_obss_detection_cfg(wma_handle, msg->bodyptr);
+		qdf_mem_free(msg->bodyptr);
+		break;
 	default:
 		WMA_LOGE("Unhandled WMA message of type %d", msg->type);
 		if (msg->bodyptr)