diff --git a/core/mac/src/pe/include/lim_api.h b/core/mac/src/pe/include/lim_api.h index e66de6befda7..dabb6b4d76e5 100644 --- a/core/mac/src/pe/include/lim_api.h +++ b/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) diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 31df90976b53..3c440df4627b 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/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; +} 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 499cee125e68..bebe8120dafc 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/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); diff --git a/core/mac/src/pe/lim/lim_session.c b/core/mac/src/pe/lim/lim_session.c index 1aa2a6080bf3..8f1a8c139833 100644 --- a/core/mac/src/pe/lim/lim_session.c +++ b/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; diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 6cc6a04bf1d3..c0ebf22a7339 100644 --- a/core/wma/src/wma_dev_if.c +++ b/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; diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 4db22b02b596..347c745c95d8 100644 --- a/core/wma/src/wma_main.c +++ b/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; } diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index f47b43e9325d..7c3112925777 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/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, - 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 (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); - if (wma->interfaces[req.vdev_id].is_channel_switch) - wma->interfaces[req.vdev_id].is_channel_switch = false; + 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 (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__, diff --git a/target/inc/wlan_tgt_def_config.h b/target/inc/wlan_tgt_def_config.h index 0a142008cde2..b1a2582fa19d 100644 --- a/target/inc/wlan_tgt_def_config.h +++ b/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