From 0e6e6b5a47c3e6cbd10ed600cda8ae904fc3d098 Mon Sep 17 00:00:00 2001 From: Manjunathappa Prakash Date: Thu, 21 Apr 2016 11:48:48 -0700 Subject: [PATCH] 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 --- core/mac/src/pe/include/lim_api.h | 11 ++ core/mac/src/pe/lim/lim_api.c | 26 ++++ .../src/pe/lim/lim_process_message_queue.c | 5 + core/mac/src/pe/lim/lim_session.c | 6 + core/wma/src/wma_dev_if.c | 15 +- core/wma/src/wma_main.c | 3 + core/wma/src/wma_scan_roam.c | 142 ++++++++++++++++-- target/inc/wlan_tgt_def_config.h | 2 + 8 files changed, 196 insertions(+), 14 deletions(-) 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