Explorar o código

qcacld-3.0: Create PE session for monitor mode

Handle monitor mode set capture channel, first set capture channel will
start the monitor mode vdev along with setting the monitor mode channel.
Subsequent set channel commands use the WMI_PDEV_SET_CHANNEL_CMDID to
set the capture channel.

Change-Id: Ibae71a4799e569bf1f1f4d39b23a7d2183fa40e5
CRs-Fixed: 963060
Manjunathappa Prakash %!s(int64=9) %!d(string=hai) anos
pai
achega
0e6e6b5a47

+ 11 - 0
core/mac/src/pe/include/lim_api.h

@@ -172,6 +172,17 @@ static inline QDF_STATUS pe_roam_synch_callback(tpAniSirGlobal mac_ctx,
 	return QDF_STATUS_E_NOSUPPORT;
 }
 #endif
+
+/**
+ * lim_mon_init_session() - create PE session for monitor mode operation
+ * @mac_ptr: mac pointer
+ * @msg: Pointer to struct sir_create_session type.
+ *
+ * Return: NONE
+ */
+void lim_mon_init_session(tpAniSirGlobal mac_ptr,
+			  struct sir_create_session *msg);
+
 #define limGetQosMode(psessionEntry, pVal) (*(pVal) = (psessionEntry)->limQosEnabled)
 #define limGetWmeMode(psessionEntry, pVal) (*(pVal) = (psessionEntry)->limWmeEnabled)
 #define limGetWsmMode(psessionEntry, pVal) (*(pVal) = (psessionEntry)->limWsmEnabled)

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

@@ -2169,3 +2169,29 @@ QDF_STATUS pe_release_global_lock(tAniSirLim *psPe)
 	return status;
 }
 
+/**
+ * lim_mon_init_session() - create PE session for monitor mode operation
+ * @mac_ptr: mac pointer
+ * @msg: Pointer to struct sir_create_session type.
+ *
+ * Return: NONE
+ */
+void lim_mon_init_session(tpAniSirGlobal mac_ptr,
+			  struct sir_create_session *msg)
+{
+	tpPESession psession_entry;
+	uint8_t session_id;
+
+	lim_print_mac_addr(mac_ptr, msg->bss_id.bytes, LOGE);
+	psession_entry = pe_create_session(mac_ptr, msg->bss_id.bytes,
+					   &session_id,
+					   mac_ptr->lim.maxStation,
+					   eSIR_MONITOR_MODE);
+	if (psession_entry == NULL) {
+		QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
+			  ("Monitor mode: Session Can not be created"));
+		lim_print_mac_addr(mac_ptr, msg->bss_id.bytes, LOGE);
+		return;
+	}
+	psession_entry->vhtCapability = 1;
+}

+ 5 - 0
core/mac/src/pe/lim/lim_process_message_queue.c

@@ -1472,6 +1472,11 @@ void lim_process_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ msg)
 		qdf_mem_free(msg->bodyptr);
 		msg->bodyptr = NULL;
 		break;
+	case eWNI_SME_MON_INIT_SESSION:
+		lim_mon_init_session(mac_ctx, msg->bodyptr);
+		qdf_mem_free(msg->bodyptr);
+		msg->bodyptr = NULL;
+		break;
 	case SIR_HAL_P2P_NOA_START_IND:
 		session_entry = &mac_ctx->lim.gpSession[0];
 		lim_log(mac_ctx, LOG1, "LIM received NOA start %x", msg->type);

+ 6 - 0
core/mac/src/pe/lim/lim_session.c

@@ -295,6 +295,8 @@ pe_create_session(tpAniSirGlobal pMac, uint8_t *bssid, uint8_t *sessionId,
 	session_ptr->gLimNumOfCurrentSTAs = 0;
 	/* Copy the BSSID to the session table */
 	sir_copy_mac_addr(session_ptr->bssId, bssid);
+	if (bssType == eSIR_MONITOR_MODE)
+		sir_copy_mac_addr(pMac->lim.gpSession[i].selfMacAddr, bssid);
 	session_ptr->valid = true;
 	/* Intialize the SME and MLM states to IDLE */
 	session_ptr->limMlmState = eLIM_MLM_IDLE_STATE;
@@ -355,6 +357,10 @@ pe_create_session(tpAniSirGlobal pMac, uint8_t *bssid, uint8_t *sessionId,
 	}
 	if (eSIR_INFRASTRUCTURE_MODE == bssType)
 		lim_ft_open(pMac, &pMac->lim.gpSession[i]);
+
+	if (eSIR_MONITOR_MODE == bssType)
+		lim_ft_open(pMac, &pMac->lim.gpSession[i]);
+
 	if (eSIR_INFRA_AP_MODE == bssType) {
 		session_ptr->old_protection_state = 0;
 		session_ptr->mac_ctx = (void *)pMac;

+ 11 - 4
core/wma/src/wma_dev_if.c

@@ -54,6 +54,7 @@
 #include "lim_session_utils.h"
 
 #include "cds_utils.h"
+#include "cds_concurrency.h"
 
 #if !defined(REMOVE_PKT_LOG)
 #include "pktlog_ac.h"
@@ -206,6 +207,8 @@ enum wlan_op_mode wma_get_txrx_vdev_type(uint32_t type)
 		vdev_type = wlan_op_mode_ocb;
 		break;
 	case WMI_VDEV_TYPE_MONITOR:
+		vdev_type = wlan_op_mode_monitor;
+		break;
 	default:
 		WMA_LOGE("Invalid vdev type %u", type);
 		vdev_type = wlan_op_mode_unknown;
@@ -909,8 +912,11 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info,
 		}
 		params->smpsMode = host_map_smps_mode(resp_event->smps_mode);
 		params->status = resp_event->status;
-		if (resp_event->resp_type == WMI_VDEV_RESTART_RESP_EVENT &&
-		    (iface->type == WMI_VDEV_TYPE_STA)) {
+		if (((resp_event->resp_type == WMI_VDEV_RESTART_RESP_EVENT) &&
+		    (iface->type == WMI_VDEV_TYPE_STA)) ||
+		    ((resp_event->resp_type == WMI_VDEV_START_RESP_EVENT) &&
+		     (iface->type == WMI_VDEV_TYPE_MONITOR))) {
+
 			param.vdev_id = resp_event->vdev_id;
 			param.assoc_id = iface->aid;
 			status = wmi_unified_vdev_up_send(wma->wmi_handle,
@@ -1574,7 +1580,8 @@ ol_txrx_vdev_handle wma_vdev_attach(tp_wma_handle wma_handle,
 
 	if (((self_sta_req->type == WMI_VDEV_TYPE_AP) &&
 	    (self_sta_req->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) ||
-	    (self_sta_req->type == WMI_VDEV_TYPE_OCB)) {
+	    (self_sta_req->type == WMI_VDEV_TYPE_OCB) ||
+	    (self_sta_req->type == WMI_VDEV_TYPE_MONITOR)) {
 		WMA_LOGA("Creating self peer %pM, vdev_id %hu",
 			 self_sta_req->self_mac_addr, self_sta_req->session_id);
 		status = wma_create_peer(wma_handle, txrx_pdev,
@@ -1799,7 +1806,7 @@ QDF_STATUS wma_vdev_start(tp_wma_handle wma,
 	 */
 	params.is_dfs = req->is_dfs;
 	params.is_restart = isRestart;
-	if (req->is_dfs) {
+	if ((QDF_GLOBAL_MONITOR_MODE != cds_get_conparam()) && req->is_dfs) {
 		params.flag_dfs = WMI_CHAN_FLAG_DFS;
 		temp_chan_info |=  (1 << WMI_CHAN_FLAG_DFS);
 		params.dis_hw_ack = true;

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

@@ -247,6 +247,9 @@ static void wma_set_default_tgt_config(tp_wma_handle wma_handle)
 		tgt_cfg.rx_decap_mode = CFG_TGT_RX_DECAP_MODE_NWIFI;
 	}
 #endif /* PERE_IP_HDR_ALIGNMENT_WAR */
+	if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
+		tgt_cfg.rx_decap_mode = CFG_TGT_RX_DECAP_MODE_RAW;
+
 	wma_handle->wlan_resource_config = tgt_cfg;
 }
 

+ 131 - 9
core/wma/src/wma_scan_roam.c

@@ -57,6 +57,7 @@
 #include "lim_session_utils.h"
 
 #include "cds_utils.h"
+#include "cds_concurrency.h"
 
 #if !defined(REMOVE_PKT_LOG)
 #include "pktlog_ac.h"
@@ -96,6 +97,8 @@ enum extscan_report_events_type {
 #define WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION (5 * 1000) /* in msec */
 #endif
 
+void ol_cfg_update_mon_chan(ol_txrx_pdev_handle pdev, int mon_ch,
+			    int mon_ch_freq);
 /**
  * wma_set_p2p_scan_info() - set p2p scan info in wma handle
  * @wma_handle: wma handle
@@ -2442,6 +2445,112 @@ void wma_process_roam_synch_complete(WMA_HANDLE handle, uint8_t vdev_id)
 }
 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
 
+/**
+ * wma_switch_channel() -  WMA api to switch channel dynamically
+ * @wma: Pointer of WMA context
+ * @req: Pointer vdev_start having channel switch info.
+ *
+ * Return: 0 for success, otherwise appropriate error code
+ */
+QDF_STATUS wma_switch_channel(tp_wma_handle wma, struct wma_vdev_start_req *req)
+{
+
+	wmi_buf_t buf;
+	wmi_channel *cmd;
+	int32_t len, ret;
+	WLAN_PHY_MODE chanmode;
+	struct wma_txrx_node *intr = wma->interfaces;
+	tpAniSirGlobal pmac;
+
+	pmac = cds_get_context(QDF_MODULE_ID_PE);
+
+	if (pmac == NULL) {
+		WMA_LOGE("%s: vdev start failed as pmac is NULL", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	len = sizeof(*cmd);
+	buf = wmi_buf_alloc(wma->wmi_handle, len);
+	if (!buf) {
+		WMA_LOGE("%s : wmi_buf_alloc failed", __func__);
+		return QDF_STATUS_E_NOMEM;
+	}
+	cmd = (wmi_channel *)wmi_buf_data(buf);
+	WMITLV_SET_HDR(&cmd->tlv_header,
+		       WMITLV_TAG_STRUC_wmi_channel,
+		       WMITLV_GET_STRUCT_TLVLEN(wmi_channel));
+
+	/* Fill channel info */
+	cmd->mhz = cds_chan_to_freq(req->chan);
+	chanmode = wma_chan_to_mode(req->chan, req->chan_width,
+				req->vht_capable, req->dot11_mode);
+
+	intr[req->vdev_id].chanmode = chanmode; /* save channel mode */
+	intr[req->vdev_id].ht_capable = req->ht_capable;
+	intr[req->vdev_id].vht_capable = req->vht_capable;
+	intr[req->vdev_id].config.gtx_info.gtxRTMask[0] =
+						CFG_TGT_DEFAULT_GTX_HT_MASK;
+	intr[req->vdev_id].config.gtx_info.gtxRTMask[1] =
+						CFG_TGT_DEFAULT_GTX_VHT_MASK;
+	intr[req->vdev_id].config.gtx_info.gtxUsrcfg =
+						CFG_TGT_DEFAULT_GTX_USR_CFG;
+	intr[req->vdev_id].config.gtx_info.gtxPERThreshold =
+					CFG_TGT_DEFAULT_GTX_PER_THRESHOLD;
+	intr[req->vdev_id].config.gtx_info.gtxPERMargin =
+					CFG_TGT_DEFAULT_GTX_PER_MARGIN;
+	intr[req->vdev_id].config.gtx_info.gtxTPCstep =
+					CFG_TGT_DEFAULT_GTX_TPC_STEP;
+	intr[req->vdev_id].config.gtx_info.gtxTPCMin =
+					CFG_TGT_DEFAULT_GTX_TPC_MIN;
+	intr[req->vdev_id].config.gtx_info.gtxBWMask =
+					CFG_TGT_DEFAULT_GTX_BW_MASK;
+	intr[req->vdev_id].mhz = cmd->mhz;
+
+	WMI_SET_CHANNEL_MODE(cmd, chanmode);
+	cmd->band_center_freq1 = cmd->mhz;
+
+	if (chanmode == MODE_11AC_VHT80)
+		cmd->band_center_freq1 =
+			cds_chan_to_freq(req->ch_center_freq_seg0);
+
+	if ((chanmode == MODE_11NA_HT40) || (chanmode == MODE_11NG_HT40) ||
+			(chanmode == MODE_11AC_VHT40)) {
+		if (req->chan_width == CH_WIDTH_80MHZ)
+			cmd->band_center_freq1 += 10;
+		else
+			cmd->band_center_freq1 -= 10;
+	}
+	cmd->band_center_freq2 = 0;
+
+	/* Set half or quarter rate WMI flags */
+	if (req->is_half_rate)
+		WMI_SET_CHANNEL_FLAG(cmd, WMI_CHAN_FLAG_HALF_RATE);
+	else if (req->is_quarter_rate)
+		WMI_SET_CHANNEL_FLAG(cmd, WMI_CHAN_FLAG_QUARTER_RATE);
+
+	/* Find out min, max and regulatory power levels */
+	WMI_SET_CHANNEL_REG_POWER(cmd, req->max_txpow);
+	WMI_SET_CHANNEL_MAX_TX_POWER(cmd, req->max_txpow);
+
+
+	WMA_LOGE("%s: freq %d channel %d chanmode %d center_chan %d center_freq2 %d reg_info_1: 0x%x reg_info_2: 0x%x, req->max_txpow: 0x%x",
+		 __func__, cmd->mhz, req->chan, chanmode,
+		 cmd->band_center_freq1, cmd->band_center_freq2,
+		 cmd->reg_info_1, cmd->reg_info_2, req->max_txpow);
+
+
+	ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
+				   WMI_PDEV_SET_CHANNEL_CMDID);
+
+	if (ret < 0) {
+		WMA_LOGP("%s: Failed to send vdev start command", __func__);
+		qdf_nbuf_free(buf);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
 /**
  * wma_set_channel() - set channel
  * @wma: wma handle
@@ -2518,17 +2627,30 @@ void wma_set_channel(tp_wma_handle wma, tpSwitchChannelParams params)
 		(params->restart_on_chan_switch == true))
 		wma->interfaces[req.vdev_id].is_channel_switch = true;
 
-	status = wma_vdev_start(wma, &req,
+	if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() &&
+	    wma_is_vdev_up(vdev_id)) {
+		status = wma_switch_channel(wma, &req);
+		if (status != QDF_STATUS_SUCCESS)
+			WMA_LOGE("%s: wma_switch_channel failed %d\n", __func__,
+				 status);
+
+		ol_htt_mon_note_chan(pdev, req.chan);
+	} else {
+		status = wma_vdev_start(wma, &req,
 				wma->interfaces[req.vdev_id].is_channel_switch);
-	if (status != QDF_STATUS_SUCCESS) {
-		wma_remove_vdev_req(wma, req.vdev_id,
-				    WMA_TARGET_REQ_TYPE_VDEV_START);
-		WMA_LOGP("%s: vdev start failed status = %d", __func__, status);
-		goto send_resp;
-	}
+		if (status != QDF_STATUS_SUCCESS) {
+			wma_remove_vdev_req(wma, req.vdev_id,
+					    WMA_TARGET_REQ_TYPE_VDEV_START);
+			WMA_LOGP("%s: vdev start failed status = %d", __func__, status);
+			goto send_resp;
+		}
 
-	if (wma->interfaces[req.vdev_id].is_channel_switch)
-		wma->interfaces[req.vdev_id].is_channel_switch = false;
+		if (wma->interfaces[req.vdev_id].is_channel_switch)
+			wma->interfaces[req.vdev_id].is_channel_switch = false;
+
+		if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
+			ol_htt_mon_note_chan(pdev, req.chan);
+	}
 	return;
 send_resp:
 	WMA_LOGD("%s: channel %d ch_width %d txpower %d status %d", __func__,

+ 2 - 0
target/inc/wlan_tgt_def_config.h

@@ -125,6 +125,8 @@
 #define CFG_TGT_RX_DECAP_MODE (0x2)
 /* Decap to native Wifi header */
 #define CFG_TGT_RX_DECAP_MODE_NWIFI (0x1)
+/* Decap to raw mode header */
+#define CFG_TGT_RX_DECAP_MODE_RAW   (0x0)
 
 /* maximum number of pending scan requests */
 #define CFG_TGT_DEFAULT_SCAN_MAX_REQS   0x4