| /* |
| * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /* |
| * DOC: sme_api.c |
| * |
| * Definitions for SME APIs |
| */ |
| |
| /* Include Files */ |
| #include <sir_common.h> |
| #include <ani_global.h> |
| #include "sme_api.h" |
| #include "csr_inside_api.h" |
| #include "sme_inside.h" |
| #include "csr_internal.h" |
| #include "wma_types.h" |
| #include "wma_if.h" |
| #include "wma_fips_api.h" |
| #include "qdf_trace.h" |
| #include "sme_trace.h" |
| #include "qdf_types.h" |
| #include "qdf_trace.h" |
| #include "cds_utils.h" |
| #include "sap_api.h" |
| #include "mac_trace.h" |
| #ifdef WLAN_FEATURE_NAN |
| #include "nan_api.h" |
| #endif |
| #include "cds_regdomain.h" |
| #include "cfg_api.h" |
| #include "sme_power_save_api.h" |
| #include "wma.h" |
| #include "sch_api.h" |
| #include "sme_nan_datapath.h" |
| #include "csr_api.h" |
| #include "wlan_reg_services_api.h" |
| #include <wlan_scan_ucfg_api.h> |
| #include "wlan_reg_ucfg_api.h" |
| #include "ol_txrx.h" |
| #include "wifi_pos_api.h" |
| #include "net/cfg80211.h" |
| #include <qca_vendor.h> |
| #include <wlan_spectral_utils_api.h> |
| #include "wlan_mlme_public_struct.h" |
| |
| static tSelfRecoveryStats g_self_recovery_stats; |
| |
| static QDF_STATUS init_sme_cmd_list(tpAniSirGlobal pMac); |
| |
| static void sme_disconnect_connected_sessions(tpAniSirGlobal pMac); |
| |
| static QDF_STATUS sme_handle_generic_change_country_code(tpAniSirGlobal pMac, |
| void *pMsgBuf); |
| |
| static QDF_STATUS sme_process_nss_update_resp(tpAniSirGlobal mac, uint8_t *msg); |
| |
| /* Channel Change Response Indication Handler */ |
| static QDF_STATUS sme_process_channel_change_resp(tpAniSirGlobal pMac, |
| uint16_t msg_type, void *pMsgBuf); |
| |
| static QDF_STATUS sme_stats_ext_event(tpAniSirGlobal mac, |
| struct stats_ext_event *msg); |
| |
| /* Internal SME APIs */ |
| QDF_STATUS sme_acquire_global_lock(tSmeStruct *psSme) |
| { |
| QDF_STATUS status = QDF_STATUS_E_INVAL; |
| |
| if (psSme) { |
| if (QDF_IS_STATUS_SUCCESS |
| (qdf_mutex_acquire(&psSme->lkSmeGlobalLock))) |
| status = QDF_STATUS_SUCCESS; |
| } |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_release_global_lock(tSmeStruct *psSme) |
| { |
| QDF_STATUS status = QDF_STATUS_E_INVAL; |
| |
| if (psSme) { |
| if (QDF_IS_STATUS_SUCCESS |
| (qdf_mutex_release(&psSme->lkSmeGlobalLock))) |
| status = QDF_STATUS_SUCCESS; |
| } |
| |
| return status; |
| } |
| |
| tpAniSirGlobal sme_get_mac_context(void) |
| { |
| tpAniSirGlobal mac_ctx; |
| mac_handle_t mac_handle; |
| |
| mac_handle = cds_get_context(QDF_MODULE_ID_SME); |
| if (NULL == mac_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL, |
| FL("invalid mac_handle")); |
| return NULL; |
| } |
| |
| mac_ctx = PMAC_STRUCT(mac_handle); |
| |
| return mac_ctx; |
| } |
| |
| /** |
| * sme_process_set_hw_mode_resp() - Process set HW mode response |
| * @mac: Global MAC pointer |
| * @msg: HW mode response |
| * |
| * Processes the HW mode response and invokes the HDD callback |
| * to process further |
| */ |
| static QDF_STATUS sme_process_set_hw_mode_resp(tpAniSirGlobal mac, uint8_t *msg) |
| { |
| tListElem *entry; |
| tSmeCmd *command = NULL; |
| bool found; |
| policy_mgr_pdev_set_hw_mode_cback callback = NULL; |
| struct sir_set_hw_mode_resp *param; |
| enum policy_mgr_conn_update_reason reason; |
| struct csr_roam_session *session; |
| uint32_t session_id; |
| |
| param = (struct sir_set_hw_mode_resp *)msg; |
| if (!param) { |
| sme_err("HW mode resp param is NULL"); |
| /* Not returning. Need to check if active command list |
| * needs to be freed |
| */ |
| } |
| |
| entry = csr_nonscan_active_ll_peek_head(mac, LL_ACCESS_LOCK); |
| if (!entry) { |
| sme_err("No cmd found in active list"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| command = GET_BASE_ADDR(entry, tSmeCmd, Link); |
| if (!command) { |
| sme_err("Base address is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| if (e_sme_command_set_hw_mode != command->command) { |
| sme_err("Command mismatch!"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| callback = command->u.set_hw_mode_cmd.set_hw_mode_cb; |
| reason = command->u.set_hw_mode_cmd.reason; |
| session_id = command->u.set_hw_mode_cmd.session_id; |
| |
| sme_debug("reason: %d session: %d", |
| command->u.set_hw_mode_cmd.reason, |
| command->u.set_hw_mode_cmd.session_id); |
| |
| if (!callback) { |
| sme_err("Callback does not exist"); |
| goto end; |
| } |
| |
| if (!param) { |
| sme_err("Callback failed since HW mode params is NULL"); |
| goto end; |
| } |
| |
| /* Irrespective of the reason for which the hw mode change request |
| * was issued, the policy manager connection table needs to be updated |
| * with the new vdev-mac id mapping, tx/rx spatial streams etc., if the |
| * set hw mode was successful. |
| */ |
| callback(param->status, |
| param->cfgd_hw_mode_index, |
| param->num_vdev_mac_entries, |
| param->vdev_mac_map, |
| command->u.set_hw_mode_cmd.next_action, |
| command->u.set_hw_mode_cmd.reason, |
| command->u.set_hw_mode_cmd.session_id, |
| command->u.set_hw_mode_cmd.context); |
| if (!CSR_IS_SESSION_VALID(mac, session_id)) { |
| sme_err("session %d is invalid", session_id); |
| goto end; |
| } |
| session = CSR_GET_SESSION(mac, session_id); |
| if (reason == POLICY_MGR_UPDATE_REASON_HIDDEN_STA) { |
| /* In the case of hidden SSID, connection update |
| * (set hw mode) is done after the scan with reason |
| * code eCsrScanForSsid completes. The connect/failure |
| * needs to be handled after the response of set hw |
| * mode |
| */ |
| if (param->status == SET_HW_MODE_STATUS_OK) { |
| sme_debug("search for ssid success"); |
| csr_scan_handle_search_for_ssid(mac, |
| session_id); |
| } else { |
| sme_debug("search for ssid failure"); |
| csr_scan_handle_search_for_ssid_failure(mac, |
| session_id); |
| } |
| csr_saved_scan_cmd_free_fields(mac, session); |
| } |
| |
| end: |
| found = csr_nonscan_active_ll_remove_entry(mac, entry, |
| LL_ACCESS_LOCK); |
| if (found) |
| /* Now put this command back on the avilable command list */ |
| csr_release_command(mac, command); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_process_hw_mode_trans_ind() - Process HW mode transition indication |
| * @mac: Global MAC pointer |
| * @msg: HW mode transition response |
| * |
| * Processes the HW mode transition indication and invoke the HDD callback |
| * to process further |
| */ |
| static QDF_STATUS sme_process_hw_mode_trans_ind(tpAniSirGlobal mac, |
| uint8_t *msg) |
| { |
| struct sir_hw_mode_trans_ind *param; |
| |
| param = (struct sir_hw_mode_trans_ind *)msg; |
| if (!param) { |
| sme_err("HW mode trans ind param is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| policy_mgr_hw_mode_transition_cb(param->old_hw_mode_index, |
| param->new_hw_mode_index, |
| param->num_vdev_mac_entries, |
| param->vdev_mac_map, mac->psoc); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * free_sme_cmds() - This function frees memory allocated for SME commands |
| * @mac_ctx: Pointer to Global MAC structure |
| * |
| * This function frees memory allocated for SME commands |
| * |
| * @Return: void |
| */ |
| static void free_sme_cmds(tpAniSirGlobal mac_ctx) |
| { |
| uint32_t idx; |
| |
| if (NULL == mac_ctx->sme.pSmeCmdBufAddr) |
| return; |
| |
| for (idx = 0; idx < mac_ctx->sme.totalSmeCmd; idx++) |
| qdf_mem_free(mac_ctx->sme.pSmeCmdBufAddr[idx]); |
| |
| qdf_mem_free(mac_ctx->sme.pSmeCmdBufAddr); |
| mac_ctx->sme.pSmeCmdBufAddr = NULL; |
| } |
| |
| static QDF_STATUS init_sme_cmd_list(tpAniSirGlobal pMac) |
| { |
| QDF_STATUS status; |
| tSmeCmd *pCmd; |
| uint32_t cmd_idx; |
| uint32_t sme_cmd_ptr_ary_sz; |
| |
| pMac->sme.totalSmeCmd = SME_TOTAL_COMMAND; |
| |
| |
| status = csr_ll_open(&pMac->sme.smeCmdFreeList); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| goto end; |
| |
| /* following pointer contains array of pointers for tSmeCmd* */ |
| sme_cmd_ptr_ary_sz = sizeof(void *) * pMac->sme.totalSmeCmd; |
| pMac->sme.pSmeCmdBufAddr = qdf_mem_malloc(sme_cmd_ptr_ary_sz); |
| if (!pMac->sme.pSmeCmdBufAddr) { |
| status = QDF_STATUS_E_NOMEM; |
| goto end; |
| } |
| |
| status = QDF_STATUS_SUCCESS; |
| for (cmd_idx = 0; cmd_idx < pMac->sme.totalSmeCmd; cmd_idx++) { |
| /* |
| * Since total size of all commands together can be huge chunk |
| * of memory, allocate SME cmd individually. These SME CMDs are |
| * moved between pending and active queues. And these freeing of |
| * these queues just manipulates the list but does not actually |
| * frees SME CMD pointers. Hence store each SME CMD address in |
| * the array, sme.pSmeCmdBufAddr. This will later facilitate |
| * freeing up of all SME CMDs with just a for loop. |
| */ |
| pMac->sme.pSmeCmdBufAddr[cmd_idx] = |
| qdf_mem_malloc(sizeof(tSmeCmd)); |
| if (NULL == pMac->sme.pSmeCmdBufAddr[cmd_idx]) { |
| status = QDF_STATUS_E_NOMEM; |
| free_sme_cmds(pMac); |
| goto end; |
| } |
| pCmd = (tSmeCmd *)pMac->sme.pSmeCmdBufAddr[cmd_idx]; |
| csr_ll_insert_tail(&pMac->sme.smeCmdFreeList, |
| &pCmd->Link, LL_ACCESS_LOCK); |
| } |
| |
| end: |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| sme_err("Failed to initialize sme command list: %d", status); |
| |
| return status; |
| } |
| |
| void sme_release_command(tpAniSirGlobal mac_ctx, tSmeCmd *sme_cmd) |
| { |
| sme_cmd->command = eSmeNoCommand; |
| csr_ll_insert_tail(&mac_ctx->sme.smeCmdFreeList, &sme_cmd->Link, |
| LL_ACCESS_LOCK); |
| } |
| |
| static QDF_STATUS free_sme_cmd_list(tpAniSirGlobal pMac) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| csr_ll_close(&pMac->sme.smeCmdFreeList); |
| |
| status = qdf_mutex_acquire(&pMac->sme.lkSmeGlobalLock); |
| if (status != QDF_STATUS_SUCCESS) { |
| sme_err("Failed to acquire the lock status: %d", status); |
| goto done; |
| } |
| |
| free_sme_cmds(pMac); |
| |
| status = qdf_mutex_release(&pMac->sme.lkSmeGlobalLock); |
| if (status != QDF_STATUS_SUCCESS) |
| sme_err("Failed to release the lock status: %d", status); |
| done: |
| return status; |
| } |
| |
| static void dump_csr_command_info(tpAniSirGlobal pMac, tSmeCmd *pCmd) |
| { |
| switch (pCmd->command) { |
| case eSmeCommandRoam: |
| sme_debug("roam command reason is %d", |
| pCmd->u.roamCmd.roamReason); |
| break; |
| |
| case eSmeCommandWmStatusChange: |
| sme_debug("WMStatusChange command type is %d", |
| pCmd->u.wmStatusChangeCmd.Type); |
| break; |
| |
| case e_sme_command_del_sta_session: |
| sme_debug("Issue del STA command for session:%d", |
| pCmd->sessionId); |
| break; |
| |
| default: |
| sme_debug("default: Unhandled command %d", |
| pCmd->command); |
| break; |
| } |
| } |
| |
| tSmeCmd *sme_get_command_buffer(tpAniSirGlobal pMac) |
| { |
| tSmeCmd *pRetCmd = NULL, *pTempCmd = NULL; |
| tListElem *pEntry; |
| static int sme_command_queue_full; |
| |
| pEntry = csr_ll_remove_head(&pMac->sme.smeCmdFreeList, LL_ACCESS_LOCK); |
| |
| /* If we can get another MS Msg buffer, then we are ok. Just link */ |
| /* the entry onto the linked list. (We are using the linked list */ |
| /* to keep track of tfhe message buffers). */ |
| if (pEntry) { |
| pRetCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link); |
| /* reset when free list is available */ |
| sme_command_queue_full = 0; |
| } else { |
| int idx = 1; |
| |
| /* Cannot change pRetCmd here since it needs to return later. */ |
| pEntry = csr_nonscan_active_ll_peek_head(pMac, LL_ACCESS_LOCK); |
| if (pEntry) |
| pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link); |
| |
| sme_err("Out of command buffer.... command (0x%X) stuck", |
| (pTempCmd) ? pTempCmd->command : eSmeNoCommand); |
| if (pTempCmd) { |
| if (eSmeCsrCommandMask & pTempCmd->command) |
| /* CSR command is stuck. See what the reason |
| * code is for that command |
| */ |
| dump_csr_command_info(pMac, pTempCmd); |
| } /* if(pTempCmd) */ |
| |
| /* dump what is in the pending queue */ |
| csr_nonscan_pending_ll_lock(pMac); |
| pEntry = |
| csr_nonscan_pending_ll_peek_head(pMac, |
| LL_ACCESS_NOLOCK); |
| while (pEntry && !sme_command_queue_full) { |
| pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link); |
| /* Print only 1st five commands from pending queue. */ |
| if (idx <= 5) |
| sme_err("Out of command buffer.... SME pending command #%d (0x%X)", |
| idx, pTempCmd->command); |
| idx++; |
| if (eSmeCsrCommandMask & pTempCmd->command) |
| /* CSR command is stuck. See what the reason |
| * code is for that command |
| */ |
| dump_csr_command_info(pMac, pTempCmd); |
| pEntry = csr_nonscan_pending_ll_next(pMac, pEntry, |
| LL_ACCESS_NOLOCK); |
| } |
| csr_nonscan_pending_ll_unlock(pMac); |
| |
| if (pMac->mlme_cfg->gen.fatal_event_trigger) |
| cds_flush_logs(WLAN_LOG_TYPE_FATAL, |
| WLAN_LOG_INDICATOR_HOST_DRIVER, |
| WLAN_LOG_REASON_SME_OUT_OF_CMD_BUF, |
| false, |
| pMac->mlme_cfg->gen.self_recovery); |
| else |
| cds_trigger_recovery(QDF_GET_MSG_BUFF_FAILURE); |
| } |
| |
| /* memset to zero */ |
| if (pRetCmd) { |
| qdf_mem_set((uint8_t *)&pRetCmd->command, |
| sizeof(pRetCmd->command), 0); |
| qdf_mem_set((uint8_t *)&pRetCmd->sessionId, |
| sizeof(pRetCmd->sessionId), 0); |
| qdf_mem_set((uint8_t *)&pRetCmd->u, sizeof(pRetCmd->u), 0); |
| } |
| |
| return pRetCmd; |
| } |
| |
| /** |
| * sme_ser_handle_active_cmd() - handle command activation callback from |
| * new serialization module |
| * @cmd: pointer to new serialization command |
| * |
| * This API is to handle command activation callback from new serialization |
| * callback |
| * |
| * Return: QDF_STATUS_SUCCESS |
| */ |
| static |
| QDF_STATUS sme_ser_handle_active_cmd(struct wlan_serialization_command *cmd) |
| { |
| tSmeCmd *sme_cmd; |
| mac_handle_t hal; |
| tpAniSirGlobal mac_ctx; |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| bool do_continue; |
| |
| if (!cmd) { |
| sme_err("No serialization command found"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| hal = cds_get_context(QDF_MODULE_ID_SME); |
| if (NULL != hal) { |
| mac_ctx = PMAC_STRUCT(hal); |
| } else { |
| sme_err("No hal found"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| sme_cmd = cmd->umac_cmd; |
| if (!sme_cmd) { |
| sme_err("No SME command found"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| switch (sme_cmd->command) { |
| case eSmeCommandRoam: |
| status = csr_roam_process_command(mac_ctx, sme_cmd); |
| break; |
| case eSmeCommandWmStatusChange: |
| csr_roam_process_wm_status_change_command(mac_ctx, |
| sme_cmd); |
| break; |
| case e_sme_command_del_sta_session: |
| csr_process_del_sta_session_command(mac_ctx, sme_cmd); |
| break; |
| case eSmeCommandAddTs: |
| case eSmeCommandDelTs: |
| #ifndef WLAN_MDM_CODE_REDUCTION_OPT |
| do_continue = qos_process_command(mac_ctx, sme_cmd); |
| if (do_continue) |
| status = QDF_STATUS_E_FAILURE; |
| #endif |
| break; |
| case e_sme_command_set_hw_mode: |
| csr_process_set_hw_mode(mac_ctx, sme_cmd); |
| break; |
| case e_sme_command_nss_update: |
| csr_process_nss_update_req(mac_ctx, sme_cmd); |
| break; |
| case e_sme_command_set_dual_mac_config: |
| csr_process_set_dual_mac_config(mac_ctx, sme_cmd); |
| break; |
| case e_sme_command_set_antenna_mode: |
| csr_process_set_antenna_mode(mac_ctx, sme_cmd); |
| break; |
| default: |
| /* something is wrong */ |
| sme_err("unknown command %d", sme_cmd->command); |
| status = QDF_STATUS_E_FAILURE; |
| break; |
| } |
| return status; |
| } |
| |
| QDF_STATUS sme_ser_cmd_callback(void *buf, |
| enum wlan_serialization_cb_reason reason) |
| { |
| struct wlan_serialization_command *cmd = buf; |
| mac_handle_t hal; |
| tpAniSirGlobal mac_ctx; |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tSmeCmd *sme_cmd; |
| |
| hal = cds_get_context(QDF_MODULE_ID_SME); |
| if (hal != NULL) { |
| mac_ctx = PMAC_STRUCT(hal); |
| } else { |
| sme_err("hal is null"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| /* |
| * Do not acquire lock here as sme global lock is already acquired in |
| * caller or MC thread context |
| */ |
| if (!cmd) { |
| sme_err("serialization command is null"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| switch (reason) { |
| case WLAN_SER_CB_ACTIVATE_CMD: |
| sme_debug("WLAN_SER_CB_ACTIVATE_CMD callback"); |
| status = sme_ser_handle_active_cmd(cmd); |
| break; |
| case WLAN_SER_CB_CANCEL_CMD: |
| sme_debug("WLAN_SER_CB_CANCEL_CMD callback"); |
| break; |
| case WLAN_SER_CB_RELEASE_MEM_CMD: |
| sme_debug("WLAN_SER_CB_RELEASE_MEM_CMD callback"); |
| if (cmd->vdev) |
| wlan_objmgr_vdev_release_ref(cmd->vdev, |
| WLAN_LEGACY_SME_ID); |
| sme_cmd = cmd->umac_cmd; |
| csr_release_command_buffer(mac_ctx, sme_cmd); |
| break; |
| case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT: |
| sme_debug("WLAN_SER_CB_ACTIVE_CMD_TIMEOUT callback"); |
| break; |
| default: |
| sme_debug("STOP: unknown reason code"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| return status; |
| } |
| |
| #ifdef WLAN_FEATURE_MEMDUMP_ENABLE |
| /** |
| * sme_get_sessionid_from_activelist() - gets session id |
| * @mac: mac context |
| * |
| * This function is used to get session id from sme command |
| * active list |
| * |
| * Return: returns session id |
| */ |
| static uint32_t sme_get_sessionid_from_activelist(tpAniSirGlobal mac) |
| { |
| tListElem *entry; |
| tSmeCmd *command; |
| uint32_t session_id = CSR_SESSION_ID_INVALID; |
| |
| entry = csr_nonscan_active_ll_peek_head(mac, LL_ACCESS_LOCK); |
| if (entry) { |
| command = GET_BASE_ADDR(entry, tSmeCmd, Link); |
| session_id = command->sessionId; |
| } |
| |
| return session_id; |
| } |
| |
| /** |
| * sme_state_info_dump() - prints state information of sme layer |
| * @buf: buffer pointer |
| * @size: size of buffer to be filled |
| * |
| * This function is used to dump state information of sme layer |
| * |
| * Return: None |
| */ |
| static void sme_state_info_dump(char **buf_ptr, uint16_t *size) |
| { |
| uint32_t session_id, active_session_id; |
| mac_handle_t hal; |
| tpAniSirGlobal mac; |
| uint16_t len = 0; |
| char *buf = *buf_ptr; |
| eCsrConnectState connect_state; |
| |
| hal = cds_get_context(QDF_MODULE_ID_SME); |
| if (hal == NULL) { |
| QDF_ASSERT(0); |
| return; |
| } |
| |
| mac = PMAC_STRUCT(hal); |
| |
| active_session_id = sme_get_sessionid_from_activelist(mac); |
| if (active_session_id != CSR_SESSION_ID_INVALID) { |
| len += qdf_scnprintf(buf + len, *size - len, |
| "\n active command sessionid %d", active_session_id); |
| } |
| |
| for (session_id = 0; session_id < CSR_ROAM_SESSION_MAX; session_id++) { |
| if (CSR_IS_SESSION_VALID(mac, session_id)) { |
| connect_state = |
| mac->roam.roamSession[session_id].connectState; |
| if ((eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED == |
| connect_state) |
| || (eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED == |
| connect_state)) { |
| len += qdf_scnprintf(buf + len, *size - len, |
| "\n NeighborRoamState: %d", |
| mac->roam.neighborRoamInfo[session_id]. |
| neighborRoamState); |
| len += qdf_scnprintf(buf + len, *size - len, |
| "\n RoamState: %d", mac->roam. |
| curState[session_id]); |
| len += qdf_scnprintf(buf + len, *size - len, |
| "\n RoamSubState: %d", mac->roam. |
| curSubState[session_id]); |
| len += qdf_scnprintf(buf + len, *size - len, |
| "\n ConnectState: %d", |
| connect_state); |
| } |
| } |
| } |
| |
| *size -= len; |
| *buf_ptr += len; |
| } |
| |
| /** |
| * sme_register_debug_callback() - registration function sme layer |
| * to print sme state information |
| * |
| * Return: None |
| */ |
| static void sme_register_debug_callback(void) |
| { |
| qdf_register_debug_callback(QDF_MODULE_ID_SME, &sme_state_info_dump); |
| } |
| #else /* WLAN_FEATURE_MEMDUMP_ENABLE */ |
| static void sme_register_debug_callback(void) |
| { |
| } |
| #endif /* WLAN_FEATURE_MEMDUMP_ENABLE */ |
| |
| /* Global APIs */ |
| |
| /** |
| * sme_open() - Initialze all SME modules and put them at idle state |
| * @mac_handle: The handle returned by mac_open |
| * |
| * The function initializes each module inside SME, PMC, CSR, etc. Upon |
| * successfully return, all modules are at idle state ready to start. |
| * smeOpen must be called before any other SME APIs can be involved. |
| * smeOpen must be called after mac_open. |
| * |
| * Return: QDF_STATUS_SUCCESS - SME is successfully initialized. |
| * Other status means SME is failed to be initialized |
| */ |
| QDF_STATUS sme_open(mac_handle_t mac_handle) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| pMac->sme.state = SME_STATE_STOP; |
| pMac->sme.currDeviceMode = QDF_STA_MODE; |
| if (!QDF_IS_STATUS_SUCCESS(qdf_mutex_create( |
| &pMac->sme.lkSmeGlobalLock))) { |
| sme_err("Init lock failed"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| status = csr_open(pMac); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("csr_open failed, status: %d", status); |
| return status; |
| } |
| |
| status = sme_ps_open(mac_handle); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("sme_ps_open failed with status: %d", status); |
| return status; |
| } |
| |
| #ifndef WLAN_MDM_CODE_REDUCTION_OPT |
| status = sme_qos_open(pMac); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("Qos open, status: %d", status); |
| return status; |
| } |
| #endif |
| status = init_sme_cmd_list(pMac); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| return status; |
| |
| status = rrm_open(pMac); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("rrm_open failed, status: %d", status); |
| return status; |
| } |
| sme_trace_init(pMac); |
| sme_register_debug_callback(); |
| wlan_serialization_legacy_init_callback(); |
| |
| return status; |
| } |
| |
| /* |
| * sme_init_chan_list, triggers channel setup based on country code. |
| */ |
| QDF_STATUS sme_init_chan_list(mac_handle_t hal, uint8_t *alpha2, |
| enum country_src cc_src) |
| { |
| tpAniSirGlobal pmac = PMAC_STRUCT(hal); |
| |
| if ((cc_src == SOURCE_USERSPACE) && |
| (pmac->roam.configParam.fSupplicantCountryCodeHasPriority)) { |
| pmac->roam.configParam.Is11dSupportEnabled = false; |
| } |
| |
| return csr_init_chan_list(pmac, alpha2); |
| } |
| |
| /* |
| * sme_set11dinfo() - Set the 11d information about valid channels |
| * and there power using information from nvRAM |
| * This function is called only for AP. |
| * |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * pSmeConfigParams - a pointer to a caller allocated object of |
| * typedef struct _smeConfigParams. |
| * |
| * Return QDF_STATUS_SUCCESS - SME update the config parameters successfully. |
| * |
| * Other status means SME is failed to update the config parameters. |
| */ |
| |
| QDF_STATUS sme_set11dinfo(mac_handle_t hal, tpSmeConfigParams pSmeConfigParams) |
| { |
| tpAniSirGlobal mac_ctx = MAC_CONTEXT(hal); |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_MSG_SET_11DINFO, NO_SESSION, 0)); |
| if (NULL == pSmeConfigParams) { |
| sme_err("SME config params empty"); |
| return status; |
| } |
| |
| status = csr_set_channels(mac_ctx, &pSmeConfigParams->csrConfig); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| sme_err("csr_set_channels failed with status: %d", status); |
| |
| return status; |
| } |
| |
| /** |
| * sme_set_scan_disable() - Dynamically enable/disable scan |
| * @mac_handle: Handle to HAL |
| * |
| * This command gives the user an option to dynamically |
| * enable or disable scans. |
| * |
| * Return: None |
| */ |
| void sme_set_scan_disable(mac_handle_t mac_handle, int value) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| |
| sme_info("scan disable %d", value); |
| ucfg_scan_set_enable(mac_ctx->psoc, !value); |
| } |
| /* |
| * sme_get_soft_ap_domain() - Get the current regulatory domain of softAp. |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by HostapdAdapter. |
| * v_REGDOMAIN_t - The current Regulatory Domain requested for SoftAp. |
| * Return QDF_STATUS_SUCCESS - SME successfully completed the request. |
| * Other status means, failed to get the current regulatory domain. |
| */ |
| |
| QDF_STATUS sme_get_soft_ap_domain(mac_handle_t mac_handle, |
| v_REGDOMAIN_t *domainIdSoftAp) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_MSG_GET_SOFTAP_DOMAIN, |
| NO_SESSION, 0)); |
| if (NULL == domainIdSoftAp) { |
| sme_err("Uninitialized domain Id"); |
| return status; |
| } |
| |
| *domainIdSoftAp = pMac->scan.domainIdCurrent; |
| status = QDF_STATUS_SUCCESS; |
| |
| return status; |
| } |
| |
| /** |
| * sme_update_fine_time_measurement_capab() - Update the FTM capabitlies from |
| * incoming val |
| * @mac_handle: Handle for Hal layer |
| * @val: New FTM capability value |
| * |
| * Return: None |
| */ |
| void sme_update_fine_time_measurement_capab(mac_handle_t mac_handle, |
| uint8_t session_id, |
| uint32_t val) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status; |
| |
| ucfg_wifi_pos_set_ftm_cap(mac_ctx->psoc, val); |
| |
| if (!val) { |
| mac_ctx->rrm.rrmPEContext.rrmEnabledCaps.fine_time_meas_rpt = 0; |
| ((tpRRMCaps)mac_ctx->rrm.rrmSmeContext. |
| rrmConfig.rm_capability)->fine_time_meas_rpt = 0; |
| } else { |
| mac_ctx->rrm.rrmPEContext.rrmEnabledCaps.fine_time_meas_rpt = 1; |
| ((tpRRMCaps)mac_ctx->rrm.rrmSmeContext. |
| rrmConfig.rm_capability)->fine_time_meas_rpt = 1; |
| } |
| |
| /* Inform this RRM IE change to FW */ |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| csr_roam_offload_scan(mac_ctx, session_id, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, |
| REASON_CONNECT_IES_CHANGED); |
| sme_release_global_lock(&mac_ctx->sme); |
| } else { |
| sme_err("Failed to acquire SME lock"); |
| } |
| } |
| |
| /* |
| * sme_update_config() - Change configurations for all SME moduels |
| * The function updates some configuration for modules in SME, CSR, etc |
| * during SMEs close open sequence. |
| * Modules inside SME apply the new configuration at the next transaction. |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * pSmeConfigParams - a pointer to a caller allocated object of |
| * typedef struct _smeConfigParams. |
| * Return QDF_STATUS_SUCCESS - SME update the config parameters successfully. |
| * Other status means SME is failed to update the config parameters. |
| */ |
| QDF_STATUS sme_update_config(mac_handle_t mac_handle, tpSmeConfigParams |
| pSmeConfigParams) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_MSG_UPDATE_CONFIG, NO_SESSION, |
| 0)); |
| if (NULL == pSmeConfigParams) { |
| sme_err("SME config params empty"); |
| return status; |
| } |
| |
| status = csr_change_default_config_param(pMac, &pSmeConfigParams-> |
| csrConfig); |
| |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| sme_err("csr_change_default_config_param failed status: %d", |
| status); |
| |
| status = rrm_change_default_config_param(pMac, &pSmeConfigParams-> |
| rrmConfig); |
| |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| sme_err("rrm_change_default_config_param failed status: %d", |
| status); |
| |
| /* For SOC, CFG is set before start We don't want to apply global CFG |
| * in connect state because that may cause some side affect |
| */ |
| if (csr_is_all_session_disconnected(pMac)) |
| csr_set_global_cfgs(pMac); |
| |
| /* |
| * If scan offload is enabled then lim has allow the sending of |
| * scan request to firmware even in powersave mode. The firmware has |
| * to take care of exiting from power save mode |
| */ |
| status = sme_cfg_set_int(mac_handle, WNI_CFG_SCAN_IN_POWERSAVE, true); |
| |
| if (QDF_STATUS_SUCCESS != status) |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "Could not pass on WNI_CFG_SCAN_IN_POWERSAVE to CFG"); |
| |
| pMac->snr_monitor_enabled = pSmeConfigParams->snr_monitor_enabled; |
| |
| return status; |
| } |
| |
| /** |
| * sme_update_scan_roam_params() - Update the scan roaming params |
| * @mac_ctx: mac ctx |
| * |
| * Return: void. |
| */ |
| static void sme_update_scan_roam_params(tpAniSirGlobal mac_ctx) |
| { |
| struct roam_filter_params scan_params = {0}; |
| struct roam_ext_params *roam_params_src; |
| uint8_t i; |
| QDF_STATUS status; |
| |
| roam_params_src = &mac_ctx->roam.configParam.roam_params; |
| |
| scan_params.num_bssid_avoid_list = |
| roam_params_src->num_bssid_avoid_list; |
| |
| if (scan_params.num_bssid_avoid_list > |
| MAX_AVOID_LIST_BSSID) |
| scan_params.num_bssid_avoid_list = |
| MAX_AVOID_LIST_BSSID; |
| |
| for (i = 0; i < scan_params.num_bssid_avoid_list; i++) { |
| qdf_copy_macaddr(&scan_params.bssid_avoid_list[i], |
| &roam_params_src->bssid_avoid_list[i]); |
| } |
| |
| status = ucfg_scan_update_roam_params(mac_ctx->psoc, &scan_params); |
| if (QDF_IS_STATUS_ERROR(status)) |
| sme_err("ailed to update scan roam params with status=%d", |
| status); |
| } |
| |
| /** |
| * sme_update_roam_params() - Store/Update the roaming params |
| * @hal: Handle for Hal layer |
| * @session_id: SME Session ID |
| * @roam_params_src: The source buffer to copy |
| * @update_param: Type of parameter to be updated |
| * |
| * Return: Return the status of the updation. |
| */ |
| QDF_STATUS sme_update_roam_params(mac_handle_t hal, |
| uint8_t session_id, struct roam_ext_params *roam_params_src, |
| int update_param) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct roam_ext_params *roam_params_dst; |
| QDF_STATUS status; |
| uint8_t i; |
| |
| roam_params_dst = &mac_ctx->roam.configParam.roam_params; |
| switch (update_param) { |
| case REASON_ROAM_EXT_SCAN_PARAMS_CHANGED: |
| mac_ctx->mlme_cfg->lfr.rssi_boost_threshold_5g = |
| roam_params_src->raise_rssi_thresh_5g; |
| mac_ctx->mlme_cfg->lfr.rssi_penalize_threshold_5g = |
| roam_params_src->drop_rssi_thresh_5g; |
| mac_ctx->mlme_cfg->lfr.rssi_boost_factor_5g = |
| roam_params_src->raise_factor_5g; |
| mac_ctx->mlme_cfg->lfr.rssi_penalize_factor_5g = |
| roam_params_src->drop_factor_5g; |
| mac_ctx->mlme_cfg->lfr.max_rssi_boost_5g = |
| roam_params_src->max_raise_rssi_5g; |
| mac_ctx->mlme_cfg->lfr.max_rssi_penalize_5g = |
| roam_params_src->max_drop_rssi_5g; |
| roam_params_dst->alert_rssi_threshold = |
| roam_params_src->alert_rssi_threshold; |
| mac_ctx->mlme_cfg->lfr.enable_5g_band_pref = true; |
| break; |
| case REASON_ROAM_SET_SSID_ALLOWED: |
| qdf_mem_set(&roam_params_dst->ssid_allowed_list, 0, |
| sizeof(tSirMacSSid) * MAX_SSID_ALLOWED_LIST); |
| roam_params_dst->num_ssid_allowed_list = |
| roam_params_src->num_ssid_allowed_list; |
| for (i = 0; i < roam_params_dst->num_ssid_allowed_list; i++) { |
| roam_params_dst->ssid_allowed_list[i].length = |
| roam_params_src->ssid_allowed_list[i].length; |
| qdf_mem_copy(roam_params_dst->ssid_allowed_list[i].ssId, |
| roam_params_src->ssid_allowed_list[i].ssId, |
| roam_params_dst->ssid_allowed_list[i].length); |
| } |
| break; |
| case REASON_ROAM_SET_FAVORED_BSSID: |
| qdf_mem_set(&roam_params_dst->bssid_favored, 0, |
| sizeof(tSirMacAddr) * MAX_BSSID_FAVORED); |
| roam_params_dst->num_bssid_favored = |
| roam_params_src->num_bssid_favored; |
| for (i = 0; i < roam_params_dst->num_bssid_favored; i++) { |
| qdf_mem_copy(&roam_params_dst->bssid_favored[i], |
| &roam_params_src->bssid_favored[i], |
| sizeof(tSirMacAddr)); |
| roam_params_dst->bssid_favored_factor[i] = |
| roam_params_src->bssid_favored_factor[i]; |
| } |
| break; |
| case REASON_ROAM_SET_BLACKLIST_BSSID: |
| qdf_mem_set(&roam_params_dst->bssid_avoid_list, 0, |
| QDF_MAC_ADDR_SIZE * MAX_BSSID_AVOID_LIST); |
| roam_params_dst->num_bssid_avoid_list = |
| roam_params_src->num_bssid_avoid_list; |
| for (i = 0; i < roam_params_dst->num_bssid_avoid_list; i++) { |
| qdf_copy_macaddr(&roam_params_dst->bssid_avoid_list[i], |
| &roam_params_src->bssid_avoid_list[i]); |
| } |
| break; |
| case REASON_ROAM_GOOD_RSSI_CHANGED: |
| roam_params_dst->good_rssi_roam = |
| roam_params_src->good_rssi_roam; |
| break; |
| default: |
| break; |
| } |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| csr_roam_offload_scan(mac_ctx, session_id, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, |
| update_param); |
| sme_release_global_lock(&mac_ctx->sme); |
| } else { |
| sme_err("Failed to acquire SME lock"); |
| } |
| |
| sme_update_scan_roam_params(mac_ctx); |
| |
| return 0; |
| } |
| |
| /** |
| * sme_process_ready_to_suspend() - |
| * @mac: Global MAC context |
| * @pReadyToSuspend: Parameter received along with ready to suspend |
| * indication from WMA. |
| * |
| * On getting ready to suspend indication, this function calls |
| * callback registered (HDD callbacks) with SME to inform ready |
| * to suspend indication. |
| * |
| * Return: None |
| */ |
| static void sme_process_ready_to_suspend(tpAniSirGlobal mac, |
| tpSirReadyToSuspendInd pReadyToSuspend) |
| { |
| if (NULL == mac) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL, |
| "%s: mac is null", __func__); |
| return; |
| } |
| |
| if (NULL != mac->readyToSuspendCallback) { |
| mac->readyToSuspendCallback(mac->readyToSuspendContext, |
| pReadyToSuspend->suspended); |
| mac->readyToSuspendCallback = NULL; |
| } |
| } |
| |
| #ifdef WLAN_FEATURE_EXTWOW_SUPPORT |
| |
| /** |
| * sme_process_ready_to_ext_wow() - inform ready to ExtWoW indication. |
| * @mac: Global MAC context |
| * @indication: ready to Ext WoW indication from lower layer |
| * |
| * On getting ready to Ext WoW indication, this function calls callback |
| * registered (HDD callback) with SME to inform ready to ExtWoW indication. |
| * |
| * Return: None |
| */ |
| static void sme_process_ready_to_ext_wow(tpAniSirGlobal mac, |
| tpSirReadyToExtWoWInd indication) |
| { |
| if (!mac) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL, |
| "%s: mac is null", __func__); |
| return; |
| } |
| |
| if (NULL != mac->readyToExtWoWCallback) { |
| mac->readyToExtWoWCallback(mac->readyToExtWoWContext, |
| indication->status); |
| mac->readyToExtWoWCallback = NULL; |
| mac->readyToExtWoWContext = NULL; |
| } |
| |
| } |
| #endif |
| |
| /* |
| * sme_hdd_ready_ind() - SME sends eWNI_SME_SYS_READY_IND to PE to inform |
| * that the NIC is ready tio run. |
| * The function is called by HDD at the end of initialization stage so PE/HAL |
| * can enable the NIC to running state. |
| * This is a synchronous call |
| * |
| * @mac_handle - The handle returned by mac_open. |
| * Return QDF_STATUS_SUCCESS - eWNI_SME_SYS_READY_IND is sent to PE |
| * successfully. |
| * Other status means SME failed to send the message to PE. |
| */ |
| QDF_STATUS sme_hdd_ready_ind(mac_handle_t mac_handle) |
| { |
| tSirSmeReadyReq *msg; |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_MSG_HDDREADYIND, NO_SESSION, 0)); |
| do { |
| |
| msg = qdf_mem_malloc(sizeof(*msg)); |
| if (!msg) |
| return QDF_STATUS_E_NOMEM; |
| |
| msg->messageType = eWNI_SME_SYS_READY_IND; |
| msg->length = sizeof(*msg); |
| msg->csr_roam_synch_cb = csr_roam_synch_callback; |
| msg->sme_msg_cb = sme_process_msg_callback; |
| msg->stop_roaming_cb = sme_stop_roaming; |
| |
| status = u_mac_post_ctrl_msg(mac_handle, (tSirMbMsg *)msg); |
| if (QDF_IS_STATUS_ERROR(status)) { |
| sme_err("u_mac_post_ctrl_msg failed to send eWNI_SME_SYS_READY_IND"); |
| break; |
| } |
| |
| status = csr_ready(pMac); |
| if (QDF_IS_STATUS_ERROR(status)) { |
| sme_err("csr_ready failed with status: %d", status); |
| break; |
| } |
| |
| pMac->sme.state = SME_STATE_READY; |
| } while (0); |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_get_valid_channels(uint8_t *chan_list, uint32_t *list_len) |
| { |
| tpAniSirGlobal mac_ctx = sme_get_mac_context(); |
| |
| if (NULL == mac_ctx) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid MAC context")); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return wlan_cfg_get_str(mac_ctx, WNI_CFG_VALID_CHANNEL_LIST, |
| chan_list, list_len); |
| } |
| |
| #ifdef WLAN_CONV_SPECTRAL_ENABLE |
| static QDF_STATUS sme_register_spectral_cb(tpAniSirGlobal mac_ctx) |
| { |
| struct spectral_legacy_cbacks spectral_cb; |
| QDF_STATUS status; |
| |
| spectral_cb.vdev_get_chan_freq = sme_get_oper_chan_freq; |
| spectral_cb.vdev_get_ch_width = sme_get_oper_ch_width; |
| spectral_cb.vdev_get_sec20chan_freq_mhz = sme_get_sec20chan_freq_mhz; |
| status = spectral_register_legacy_cb(mac_ctx->psoc, &spectral_cb); |
| |
| return status; |
| } |
| #else |
| static QDF_STATUS sme_register_spectral_cb(tpAniSirGlobal mac_ctx) |
| { |
| return QDF_STATUS_SUCCESS; |
| } |
| #endif |
| /* |
| * sme_start() - Put all SME modules at ready state. |
| * The function starts each module in SME, PMC, CSR, etc. . Upon |
| * successfully return, all modules are ready to run. |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * Return QDF_STATUS_SUCCESS - SME is ready. |
| * Other status means SME is failed to start |
| */ |
| QDF_STATUS sme_start(mac_handle_t mac_handle) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct policy_mgr_sme_cbacks sme_cbacks; |
| |
| do { |
| status = csr_start(pMac); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("csr_start failed status: %d", status); |
| break; |
| } |
| sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss; |
| sme_cbacks.sme_get_valid_channels = sme_get_valid_channels; |
| sme_cbacks.sme_nss_update_request = sme_nss_update_request; |
| sme_cbacks.sme_pdev_set_hw_mode = sme_pdev_set_hw_mode; |
| sme_cbacks.sme_pdev_set_pcl = sme_pdev_set_pcl; |
| sme_cbacks.sme_soc_set_dual_mac_config = |
| sme_soc_set_dual_mac_config; |
| sme_cbacks.sme_change_mcc_beacon_interval = |
| sme_change_mcc_beacon_interval; |
| sme_cbacks.sme_get_ap_channel_from_scan = |
| sme_get_ap_channel_from_scan; |
| sme_cbacks.sme_scan_result_purge = sme_scan_result_purge; |
| status = policy_mgr_register_sme_cb(pMac->psoc, &sme_cbacks); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("Failed to register sme cb with Policy Manager: %d", |
| status); |
| break; |
| } |
| sme_register_spectral_cb(pMac); |
| pMac->sme.state = SME_STATE_START; |
| |
| /* START RRM */ |
| status = rrm_start(pMac); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("Failed to start RRM"); |
| break; |
| } |
| } while (0); |
| return status; |
| } |
| |
| static QDF_STATUS dfs_msg_processor(tpAniSirGlobal mac, |
| struct scheduler_msg *msg) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| struct csr_roam_info roam_info = { 0 }; |
| tSirSmeCSAIeTxCompleteRsp *csa_ie_tx_complete_rsp; |
| uint32_t session_id = 0; |
| eRoamCmdStatus roam_status; |
| eCsrRoamResult roam_result; |
| |
| switch (msg->type) { |
| case eWNI_SME_DFS_RADAR_FOUND: |
| { |
| session_id = msg->bodyval; |
| roam_status = eCSR_ROAM_DFS_RADAR_IND; |
| roam_result = eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND; |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "sapdfs: Radar indication event occurred"); |
| break; |
| } |
| case eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND: |
| { |
| csa_ie_tx_complete_rsp = |
| (tSirSmeCSAIeTxCompleteRsp *) msg->bodyptr; |
| if (!csa_ie_tx_complete_rsp) { |
| sme_err("eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND null msg"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| session_id = csa_ie_tx_complete_rsp->sessionId; |
| roam_status = eCSR_ROAM_DFS_CHAN_SW_NOTIFY; |
| roam_result = eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS; |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND session=%d", |
| session_id); |
| break; |
| } |
| case eWNI_SME_DFS_CAC_COMPLETE: |
| { |
| session_id = msg->bodyval; |
| roam_status = eCSR_ROAM_CAC_COMPLETE_IND; |
| roam_result = eCSR_ROAM_RESULT_CAC_END_IND; |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "sapdfs: Received eWNI_SME_DFS_CAC_COMPLETE vdevid%d", |
| session_id); |
| break; |
| } |
| case eWNI_SME_CSA_RESTART_RSP: |
| { |
| session_id = msg->bodyval; |
| roam_status = 0; |
| roam_result = eCSR_ROAM_RESULT_CSA_RESTART_RSP; |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "sapdfs: Received eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_REQ vdevid%d", |
| session_id); |
| break; |
| } |
| default: |
| { |
| sme_err("Invalid DFS message: 0x%x", msg->type); |
| status = QDF_STATUS_E_FAILURE; |
| return status; |
| } |
| } |
| |
| /* Indicate Radar Event to SAP */ |
| csr_roam_call_callback(mac, session_id, &roam_info, 0, |
| roam_status, roam_result); |
| return status; |
| } |
| |
| |
| #ifdef WLAN_FEATURE_11W |
| /* |
| * Handle the unprotected management frame indication from LIM and |
| * forward it to HDD. |
| */ |
| static QDF_STATUS |
| sme_unprotected_mgmt_frm_ind(tpAniSirGlobal mac, |
| tpSirSmeUnprotMgmtFrameInd pSmeMgmtFrm) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| struct csr_roam_info roam_info = { 0 }; |
| uint32_t SessionId = pSmeMgmtFrm->sessionId; |
| |
| roam_info.nFrameLength = pSmeMgmtFrm->frameLen; |
| roam_info.pbFrames = pSmeMgmtFrm->frameBuf; |
| roam_info.frameType = pSmeMgmtFrm->frameType; |
| |
| /* forward the mgmt frame to HDD */ |
| csr_roam_call_callback(mac, SessionId, &roam_info, 0, |
| eCSR_ROAM_UNPROT_MGMT_FRAME_IND, 0); |
| |
| return status; |
| } |
| #endif |
| |
| QDF_STATUS sme_update_new_channel_event(mac_handle_t hal, uint8_t session_id) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| struct csr_roam_info *roamInfo; |
| eRoamCmdStatus roamStatus; |
| eCsrRoamResult roamResult; |
| |
| roamInfo = qdf_mem_malloc(sizeof(*roamInfo)); |
| if (!roamInfo) |
| return QDF_STATUS_E_FAILURE; |
| |
| roamInfo->dfs_event.sessionId = session_id; |
| roamStatus = eCSR_ROAM_CHANNEL_COMPLETE_IND; |
| roamResult = eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND; |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "sapdfs: Updated new channel event"); |
| |
| /* Indicate channel Event to SAP */ |
| csr_roam_call_callback(mac, session_id, roamInfo, 0, |
| roamStatus, roamResult); |
| |
| qdf_mem_free(roamInfo); |
| return status; |
| } |
| |
| |
| /** |
| * sme_extended_change_channel_ind()- function to indicate ECSA |
| * action frame is received in lim to SAP |
| * @mac_ctx: pointer to global mac structure |
| * @msg_buf: contain new channel and session id. |
| * |
| * This function is called to post ECSA action frame |
| * receive event to SAP. |
| * |
| * Return: success if msg indicated to SAP else return failure |
| */ |
| static QDF_STATUS sme_extended_change_channel_ind(tpAniSirGlobal mac_ctx, |
| void *msg_buf) |
| { |
| struct sir_sme_ext_cng_chan_ind *ext_chan_ind; |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| uint32_t session_id = 0; |
| struct csr_roam_info roamInfo = {0}; |
| eRoamCmdStatus roam_status; |
| eCsrRoamResult roam_result; |
| |
| ext_chan_ind = msg_buf; |
| if (NULL == ext_chan_ind) { |
| sme_err("ext_chan_ind is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| session_id = ext_chan_ind->session_id; |
| roamInfo.target_channel = ext_chan_ind->new_channel; |
| roam_status = eCSR_ROAM_EXT_CHG_CHNL_IND; |
| roam_result = eCSR_ROAM_EXT_CHG_CHNL_UPDATE_IND; |
| sme_debug("sapdfs: Received eWNI_SME_EXT_CHANGE_CHANNEL_IND for session id [%d]", |
| session_id); |
| |
| /* Indicate Ext Channel Change event to SAP */ |
| csr_roam_call_callback(mac_ctx, session_id, &roamInfo, 0, |
| roam_status, roam_result); |
| return status; |
| } |
| |
| #ifdef FEATURE_WLAN_ESE |
| /** |
| * sme_update_is_ese_feature_enabled() - enable/disable ESE support at runtime |
| * @mac_handle: HAL handle |
| * @sessionId: session id |
| * @isEseIniFeatureEnabled: ese ini enabled |
| * |
| * It is used at in the REG_DYNAMIC_VARIABLE macro definition of |
| * isEseIniFeatureEnabled. This is a synchronous call |
| * |
| * Return: QDF_STATUS enumeration |
| */ |
| QDF_STATUS sme_update_is_ese_feature_enabled(mac_handle_t mac_handle, |
| uint8_t sessionId, const bool isEseIniFeatureEnabled) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status; |
| |
| if (pMac->roam.configParam.isEseIniFeatureEnabled == |
| isEseIniFeatureEnabled) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: ESE Mode is already enabled or disabled, nothing to do (returning) old(%d) new(%d)", |
| __func__, |
| pMac->roam.configParam.isEseIniFeatureEnabled, |
| isEseIniFeatureEnabled); |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: EseEnabled is changed from %d to %d", __func__, |
| pMac->roam.configParam.isEseIniFeatureEnabled, |
| isEseIniFeatureEnabled); |
| pMac->roam.configParam.isEseIniFeatureEnabled = isEseIniFeatureEnabled; |
| csr_neighbor_roam_update_fast_roaming_enabled( |
| pMac, sessionId, isEseIniFeatureEnabled); |
| |
| if (true == isEseIniFeatureEnabled) |
| sme_update_fast_transition_enabled(mac_handle, true); |
| |
| if (pMac->roam.configParam.isRoamOffloadScanEnabled) { |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| csr_roam_offload_scan(pMac, sessionId, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, |
| REASON_ESE_INI_CFG_CHANGED); |
| sme_release_global_lock(&pMac->sme); |
| } else { |
| sme_err("Failed to acquire SME lock"); |
| return status; |
| } |
| } |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_set_plm_request() - set plm request |
| * @mac_handle: HAL handle |
| * @pPlmReq: Pointer to input plm request |
| * |
| * Return: QDF_STATUS enumeration |
| */ |
| QDF_STATUS sme_set_plm_request(mac_handle_t mac_handle, tpSirPlmReq pPlmReq) |
| { |
| QDF_STATUS status; |
| bool ret = false; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| uint8_t ch_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = { 0 }; |
| uint8_t count, valid_count = 0; |
| struct scheduler_msg msg = {0}; |
| struct csr_roam_session *pSession = CSR_GET_SESSION(pMac, |
| pPlmReq->sessionId); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| return status; |
| |
| if (!pSession) { |
| sme_err("session %d not found", pPlmReq->sessionId); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| if (!pSession->sessionActive) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid Sessionid")); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| if (!pPlmReq->enable) |
| goto send_plm_start; |
| /* validating channel numbers */ |
| for (count = 0; count < pPlmReq->plmNumCh; count++) { |
| ret = csr_is_supported_channel(pMac, pPlmReq->plmChList[count]); |
| if (ret && pPlmReq->plmChList[count] > 14) { |
| if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state( |
| pMac->pdev, |
| pPlmReq->plmChList[count])) { |
| /* DFS channel is provided, no PLM bursts can be |
| * transmitted. Ignoring these channels. |
| */ |
| QDF_TRACE(QDF_MODULE_ID_SME, |
| QDF_TRACE_LEVEL_DEBUG, |
| FL("DFS channel %d ignored for PLM"), |
| pPlmReq->plmChList[count]); |
| continue; |
| } |
| } else if (!ret) { |
| /* Not supported, ignore the channel */ |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| FL("Unsupported channel %d ignored for PLM"), |
| pPlmReq->plmChList[count]); |
| continue; |
| } |
| ch_list[valid_count] = pPlmReq->plmChList[count]; |
| valid_count++; |
| } /* End of for () */ |
| |
| /* Copying back the valid channel list to plm struct */ |
| qdf_mem_set((void *)pPlmReq->plmChList, |
| pPlmReq->plmNumCh, 0); |
| if (valid_count) |
| qdf_mem_copy(pPlmReq->plmChList, ch_list, |
| valid_count); |
| /* All are invalid channels, FW need to send the PLM |
| * report with "incapable" bit set. |
| */ |
| pPlmReq->plmNumCh = valid_count; |
| |
| send_plm_start: |
| /* PLM START */ |
| msg.type = WMA_SET_PLM_REQ; |
| msg.reserved = 0; |
| msg.bodyptr = pPlmReq; |
| |
| if (!QDF_IS_STATUS_SUCCESS(scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &msg))) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Not able to post WMA_SET_PLM_REQ to WMA")); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| sme_release_global_lock(&pMac->sme); |
| return status; |
| } |
| |
| /** |
| * sme_tsm_ie_ind() - sme tsm ie indication |
| * @mac: Global mac context |
| * @pSmeTsmIeInd: Pointer to tsm ie indication |
| * |
| * Handle the tsm ie indication from LIM and forward it to HDD. |
| * |
| * Return: QDF_STATUS enumeration |
| */ |
| static QDF_STATUS sme_tsm_ie_ind(tpAniSirGlobal mac, |
| tSirSmeTsmIEInd *pSmeTsmIeInd) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| struct csr_roam_info roam_info = { 0 }; |
| uint32_t SessionId = pSmeTsmIeInd->sessionId; |
| |
| roam_info.tsmIe.tsid = pSmeTsmIeInd->tsmIe.tsid; |
| roam_info.tsmIe.state = pSmeTsmIeInd->tsmIe.state; |
| roam_info.tsmIe.msmt_interval = pSmeTsmIeInd->tsmIe.msmt_interval; |
| /* forward the tsm ie information to HDD */ |
| csr_roam_call_callback(mac, SessionId, &roam_info, 0, |
| eCSR_ROAM_TSM_IE_IND, 0); |
| return status; |
| } |
| |
| /** |
| * sme_set_cckm_ie() - set cckm ie |
| * @mac_handle: HAL handle |
| * @sessionId: session id |
| * @pCckmIe: Pointer to CCKM Ie |
| * @cckmIeLen: Length of @pCckmIe |
| * |
| * Function to store the CCKM IE passed from supplicant and use |
| * it while packing reassociation request. |
| * |
| * Return: QDF_STATUS enumeration |
| */ |
| QDF_STATUS sme_set_cckm_ie(mac_handle_t mac_handle, uint8_t sessionId, |
| uint8_t *pCckmIe, uint8_t cckmIeLen) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| csr_set_cckm_ie(pMac, sessionId, pCckmIe, cckmIeLen); |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /** |
| * sme_set_ese_beacon_request() - set ese beacon request |
| * @mac_handle: HAL handle |
| * @sessionId: session id |
| * @pEseBcnReq: Ese beacon report |
| * |
| * function to set ESE beacon request parameters |
| * |
| * Return: QDF_STATUS enumeration |
| */ |
| QDF_STATUS sme_set_ese_beacon_request(mac_handle_t mac_handle, |
| const uint8_t sessionId, |
| const tCsrEseBeaconReq *pEseBcnReq) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| tpSirBeaconReportReqInd pSmeBcnReportReq = NULL; |
| tCsrEseBeaconReqParams *pBeaconReq = NULL; |
| uint8_t counter = 0; |
| struct csr_roam_session *pSession = CSR_GET_SESSION(pMac, sessionId); |
| tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; |
| |
| if (pSmeRrmContext->eseBcnReqInProgress == true) { |
| sme_err("A Beacon Report Req is already in progress"); |
| return QDF_STATUS_E_RESOURCES; |
| } |
| |
| /* Store the info in RRM context */ |
| qdf_mem_copy(&pSmeRrmContext->eseBcnReqInfo, pEseBcnReq, |
| sizeof(tCsrEseBeaconReq)); |
| |
| /* Prepare the request to send to SME. */ |
| pSmeBcnReportReq = qdf_mem_malloc(sizeof(tSirBeaconReportReqInd)); |
| if (!pSmeBcnReportReq) |
| return QDF_STATUS_E_NOMEM; |
| |
| pSmeRrmContext->eseBcnReqInProgress = true; |
| |
| sme_debug("Sending Beacon Report Req to SME"); |
| |
| pSmeBcnReportReq->messageType = eWNI_SME_BEACON_REPORT_REQ_IND; |
| pSmeBcnReportReq->length = sizeof(tSirBeaconReportReqInd); |
| qdf_mem_copy(pSmeBcnReportReq->bssId, |
| pSession->connectedProfile.bssid.bytes, |
| sizeof(tSirMacAddr)); |
| pSmeBcnReportReq->channelInfo.channelNum = 255; |
| pSmeBcnReportReq->channelList.numChannels = pEseBcnReq->numBcnReqIe; |
| pSmeBcnReportReq->msgSource = eRRM_MSG_SOURCE_ESE_UPLOAD; |
| |
| for (counter = 0; counter < pEseBcnReq->numBcnReqIe; counter++) { |
| pBeaconReq = |
| (tCsrEseBeaconReqParams *) &pEseBcnReq->bcnReq[counter]; |
| pSmeBcnReportReq->fMeasurementtype[counter] = |
| pBeaconReq->scanMode; |
| pSmeBcnReportReq->measurementDuration[counter] = |
| SYS_TU_TO_MS(pBeaconReq->measurementDuration); |
| pSmeBcnReportReq->channelList.channelNumber[counter] = |
| pBeaconReq->channel; |
| } |
| |
| status = sme_rrm_process_beacon_report_req_ind(pMac, pSmeBcnReportReq); |
| |
| if (status != QDF_STATUS_SUCCESS) |
| pSmeRrmContext->eseBcnReqInProgress = false; |
| |
| qdf_mem_free(pSmeBcnReportReq); |
| |
| return status; |
| } |
| |
| /** |
| * sme_get_tsm_stats() - SME get tsm stats |
| * @mac_handle: HAL handle |
| * @callback: SME sends back the requested stats using the callback |
| * @staId: The station ID for which the stats is requested for |
| * @bssId: bssid |
| * @pContext: user context to be passed back along with the callback |
| * @tid: Traffic id |
| * |
| * API register a callback to get TSM Stats. |
| * |
| * Return: QDF_STATUS enumeration |
| */ |
| QDF_STATUS sme_get_tsm_stats(mac_handle_t mac_handle, |
| tCsrTsmStatsCallback callback, |
| uint8_t staId, struct qdf_mac_addr bssId, |
| void *pContext, uint8_t tid) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_get_tsm_stats(pMac, callback, |
| staId, bssId, pContext, |
| tid); |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /** |
| * sme_set_ese_roam_scan_channel_list() - To set ese roam scan channel list |
| * @mac_handle: pointer HAL handle returned by mac_open |
| * @sessionId: sme session id |
| * @pChannelList: Output channel list |
| * @numChannels: Output number of channels |
| * |
| * This routine is called to set ese roam scan channel list. |
| * This is a synchronous call |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_set_ese_roam_scan_channel_list(mac_handle_t mac_handle, |
| uint8_t sessionId, |
| uint8_t *pChannelList, |
| uint8_t numChannels) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; |
| tpCsrChannelInfo curchnl_list_info = NULL; |
| uint8_t oldChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN * 2] = { 0 }; |
| uint8_t newChannelList[128] = { 0 }; |
| uint8_t i = 0, j = 0; |
| |
| if (sessionId >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), sessionId); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; |
| curchnl_list_info = |
| &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("Failed to acquire SME lock"); |
| return status; |
| } |
| if (NULL != curchnl_list_info->ChannelList) { |
| for (i = 0; i < curchnl_list_info->numOfChannels; i++) { |
| j += snprintf(oldChannelList + j, |
| sizeof(oldChannelList) - j, "%d", |
| curchnl_list_info->ChannelList[i]); |
| } |
| } |
| status = csr_create_roam_scan_channel_list(pMac, sessionId, |
| pChannelList, numChannels, |
| csr_get_current_band(pMac)); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (NULL != curchnl_list_info->ChannelList) { |
| j = 0; |
| for (i = 0; i < curchnl_list_info->numOfChannels; i++) { |
| j += snprintf(newChannelList + j, |
| sizeof(newChannelList) - j, "%d", |
| curchnl_list_info->ChannelList[i]); |
| } |
| } |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "ESE roam scan chnl list successfully set to %s-old value is %s-roam state is %d", |
| newChannelList, oldChannelList, |
| pNeighborRoamInfo->neighborRoamState); |
| } |
| |
| if (pMac->roam.configParam.isRoamOffloadScanEnabled) |
| csr_roam_offload_scan(pMac, sessionId, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, |
| REASON_CHANNEL_LIST_CHANGED); |
| |
| sme_release_global_lock(&pMac->sme); |
| return status; |
| } |
| |
| #endif /* FEATURE_WLAN_ESE */ |
| |
| static |
| QDF_STATUS sme_ibss_peer_info_response_handler(tpAniSirGlobal pMac, |
| tpSirIbssGetPeerInfoRspParams |
| pIbssPeerInfoParams) |
| { |
| if (NULL == pMac) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL, |
| "%s: pMac is null", __func__); |
| return QDF_STATUS_E_FAILURE; |
| } |
| if (pMac->sme.peerInfoParams.peerInfoCbk == NULL) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: HDD callback is null", __func__); |
| return QDF_STATUS_E_FAILURE; |
| } |
| pMac->sme.peerInfoParams.peerInfoCbk(pMac->sme.peerInfoParams.pUserData, |
| &pIbssPeerInfoParams-> |
| ibssPeerInfoRspParams); |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_process_dual_mac_config_resp() - Process set Dual mac config response |
| * @mac: Global MAC pointer |
| * @msg: Dual mac config response |
| * |
| * Processes the dual mac configuration response and invokes the HDD callback |
| * to process further |
| */ |
| static QDF_STATUS sme_process_dual_mac_config_resp(tpAniSirGlobal mac, |
| uint8_t *msg) |
| { |
| tListElem *entry = NULL; |
| tSmeCmd *command = NULL; |
| bool found; |
| dual_mac_cb callback = NULL; |
| struct sir_dual_mac_config_resp *param; |
| |
| param = (struct sir_dual_mac_config_resp *)msg; |
| if (!param) { |
| sme_err("Dual mac config resp param is NULL"); |
| /* Not returning. Need to check if active command list |
| * needs to be freed |
| */ |
| } |
| |
| entry = csr_nonscan_active_ll_peek_head(mac, LL_ACCESS_LOCK); |
| if (!entry) { |
| sme_err("No cmd found in active list"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| command = GET_BASE_ADDR(entry, tSmeCmd, Link); |
| if (!command) { |
| sme_err("Base address is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| if (e_sme_command_set_dual_mac_config != command->command) { |
| sme_err("Command mismatch!"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| callback = command->u.set_dual_mac_cmd.set_dual_mac_cb; |
| if (callback) { |
| if (!param) { |
| sme_err("Callback failed-Dual mac config is NULL"); |
| } else { |
| sme_debug("Calling HDD callback for Dual mac config"); |
| callback(param->status, |
| command->u.set_dual_mac_cmd.scan_config, |
| command->u.set_dual_mac_cmd.fw_mode_config); |
| } |
| } else { |
| sme_err("Callback does not exist"); |
| } |
| |
| found = csr_nonscan_active_ll_remove_entry(mac, entry, LL_ACCESS_LOCK); |
| if (found) |
| /* Now put this command back on the available command list */ |
| csr_release_command(mac, command); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_process_antenna_mode_resp() - Process set antenna mode |
| * response |
| * @mac: Global MAC pointer |
| * @msg: antenna mode response |
| * |
| * Processes the antenna mode response and invokes the HDD |
| * callback to process further |
| */ |
| static QDF_STATUS sme_process_antenna_mode_resp(tpAniSirGlobal mac, |
| uint8_t *msg) |
| { |
| tListElem *entry; |
| tSmeCmd *command; |
| bool found; |
| void *context = NULL; |
| antenna_mode_cb callback; |
| struct sir_antenna_mode_resp *param; |
| |
| param = (struct sir_antenna_mode_resp *)msg; |
| if (!param) |
| sme_err("set antenna mode resp is NULL"); |
| /* Not returning. Need to check if active command list |
| * needs to be freed |
| */ |
| |
| entry = csr_nonscan_active_ll_peek_head(mac, LL_ACCESS_LOCK); |
| if (!entry) { |
| sme_err("No cmd found in active list"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| command = GET_BASE_ADDR(entry, tSmeCmd, Link); |
| if (!command) { |
| sme_err("Base address is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| if (e_sme_command_set_antenna_mode != command->command) { |
| sme_err("Command mismatch!"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| context = command->u.set_antenna_mode_cmd.set_antenna_mode_ctx; |
| callback = command->u.set_antenna_mode_cmd.set_antenna_mode_resp; |
| if (callback) { |
| if (!param) |
| sme_err("Set antenna mode call back is NULL"); |
| else |
| callback(param->status, context); |
| } else { |
| sme_err("Callback does not exist"); |
| } |
| |
| found = csr_nonscan_active_ll_remove_entry(mac, entry, LL_ACCESS_LOCK); |
| if (found) |
| /* Now put this command back on the available command list */ |
| csr_release_command(mac, command); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS sme_process_msg(tpAniSirGlobal pMac, struct scheduler_msg *pMsg) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| struct sir_peer_info *peer_stats; |
| struct sir_peer_info_resp *peer_info_rsp; |
| |
| if (pMsg == NULL) { |
| sme_err("Empty message for SME"); |
| return status; |
| } |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_warn("Locking failed, bailing out"); |
| if (pMsg->bodyptr) |
| qdf_mem_free(pMsg->bodyptr); |
| return status; |
| } |
| if (!SME_IS_START(pMac)) { |
| sme_debug("message type %d in stop state ignored", pMsg->type); |
| if (pMsg->bodyptr) |
| qdf_mem_free(pMsg->bodyptr); |
| goto release_lock; |
| } |
| switch (pMsg->type) { |
| #ifdef WLAN_FEATURE_ROAM_OFFLOAD |
| case eWNI_SME_HO_FAIL_IND: |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("LFR3: Rcvd eWNI_SME_HO_FAIL_IND")); |
| csr_process_ho_fail_ind(pMac, pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| #endif |
| case WNI_CFG_SET_CNF: |
| case WNI_CFG_DNLD_CNF: |
| case WNI_CFG_GET_RSP: |
| case WNI_CFG_ADD_GRP_ADDR_CNF: |
| case WNI_CFG_DEL_GRP_ADDR_CNF: |
| break; |
| case eWNI_SME_ADDTS_RSP: |
| case eWNI_SME_DELTS_RSP: |
| case eWNI_SME_DELTS_IND: |
| case eWNI_SME_FT_AGGR_QOS_RSP: |
| /* QoS */ |
| if (pMsg->bodyptr) { |
| #ifndef WLAN_MDM_CODE_REDUCTION_OPT |
| status = sme_qos_msg_processor(pMac, pMsg->type, |
| pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| #endif |
| } else { |
| sme_err("Empty message for: %d", pMsg->type); |
| } |
| break; |
| case eWNI_SME_NEIGHBOR_REPORT_IND: |
| case eWNI_SME_BEACON_REPORT_REQ_IND: |
| if (pMsg->bodyptr) { |
| status = sme_rrm_msg_processor(pMac, pMsg->type, |
| pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } else { |
| sme_err("Empty message for: %d", pMsg->type); |
| } |
| break; |
| case eWNI_SME_ADD_STA_SELF_RSP: |
| if (pMsg->bodyptr) { |
| status = csr_process_add_sta_session_rsp(pMac, |
| pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } else { |
| sme_err("Empty message for: %d", pMsg->type); |
| } |
| break; |
| case eWNI_SME_DEL_STA_SELF_RSP: |
| if (pMsg->bodyptr) { |
| status = csr_process_del_sta_session_rsp(pMac, |
| pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } else { |
| sme_err("Empty message for: %d", pMsg->type); |
| } |
| break; |
| case eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE: |
| if (pMsg->bodyptr) { |
| status = sme_handle_generic_change_country_code( |
| (void *)pMac, pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } else { |
| sme_err("Empty message for: %d", pMsg->type); |
| } |
| break; |
| |
| #ifdef WLAN_FEATURE_11W |
| case eWNI_SME_UNPROT_MGMT_FRM_IND: |
| if (pMsg->bodyptr) { |
| sme_unprotected_mgmt_frm_ind(pMac, pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } else { |
| sme_err("Empty message for: %d", pMsg->type); |
| } |
| break; |
| #endif |
| #ifdef FEATURE_WLAN_ESE |
| case eWNI_SME_TSM_IE_IND: |
| if (pMsg->bodyptr) { |
| sme_tsm_ie_ind(pMac, pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } else { |
| sme_err("Empty message for: %d", pMsg->type); |
| } |
| break; |
| #endif /* FEATURE_WLAN_ESE */ |
| case eWNI_SME_ROAM_SCAN_OFFLOAD_RSP: |
| status = csr_roam_offload_scan_rsp_hdlr((void *)pMac, |
| pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| case eWNI_SME_IBSS_PEER_INFO_RSP: |
| if (pMsg->bodyptr) { |
| sme_ibss_peer_info_response_handler(pMac, |
| pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } else { |
| sme_err("Empty message for: %d", pMsg->type); |
| } |
| break; |
| case eWNI_SME_READY_TO_SUSPEND_IND: |
| if (pMsg->bodyptr) { |
| sme_process_ready_to_suspend(pMac, pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } else { |
| sme_err("Empty message for: %d", pMsg->type); |
| } |
| break; |
| #ifdef WLAN_FEATURE_EXTWOW_SUPPORT |
| case eWNI_SME_READY_TO_EXTWOW_IND: |
| if (pMsg->bodyptr) { |
| sme_process_ready_to_ext_wow(pMac, pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } else { |
| sme_err("Empty message for: %d", pMsg->type); |
| } |
| break; |
| #endif |
| #ifdef FEATURE_WLAN_AUTO_SHUTDOWN |
| case eWNI_SME_AUTO_SHUTDOWN_IND: |
| if (pMac->sme.pAutoShutdownNotificationCb) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| FL("Auto shutdown notification")); |
| pMac->sme.pAutoShutdownNotificationCb(); |
| } |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| #endif |
| case eWNI_SME_DFS_RADAR_FOUND: |
| case eWNI_SME_DFS_CAC_COMPLETE: |
| case eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND: |
| case eWNI_SME_CSA_RESTART_RSP: |
| status = dfs_msg_processor(pMac, pMsg); |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| case eWNI_SME_CHANNEL_CHANGE_RSP: |
| if (pMsg->bodyptr) { |
| status = sme_process_channel_change_resp(pMac, |
| pMsg->type, |
| pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } else { |
| sme_err("Empty message for: %d", pMsg->type); |
| } |
| break; |
| case eWNI_SME_STATS_EXT_EVENT: |
| status = sme_stats_ext_event(pMac, pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| case eWNI_SME_GET_PEER_INFO_IND: |
| if (pMac->sme.pget_peer_info_ind_cb) |
| pMac->sme.pget_peer_info_ind_cb(pMsg->bodyptr, |
| pMac->sme.pget_peer_info_cb_context); |
| if (pMsg->bodyptr) { |
| peer_info_rsp = (struct sir_peer_info_resp *) |
| (pMsg->bodyptr); |
| peer_stats = (struct sir_peer_info *) |
| (peer_info_rsp->info); |
| if (peer_stats) { |
| pMac->peer_rssi = peer_stats[0].rssi; |
| pMac->peer_txrate = peer_stats[0].tx_rate; |
| pMac->peer_rxrate = peer_stats[0].rx_rate; |
| } |
| } |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| case eWNI_SME_GET_PEER_INFO_EXT_IND: |
| if (pMac->sme.pget_peer_info_ext_ind_cb) |
| pMac->sme.pget_peer_info_ext_ind_cb(pMsg->bodyptr, |
| pMac->sme.pget_peer_info_ext_cb_context); |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| case eWNI_SME_CSA_OFFLOAD_EVENT: |
| if (pMsg->bodyptr) { |
| csr_scan_flush_bss_entry(pMac, pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } |
| break; |
| case eWNI_SME_TSF_EVENT: |
| if (pMac->sme.get_tsf_cb) { |
| pMac->sme.get_tsf_cb(pMac->sme.get_tsf_cxt, |
| (struct stsf *)pMsg->bodyptr); |
| } |
| if (pMsg->bodyptr) |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| #ifdef WLAN_FEATURE_NAN |
| case eWNI_SME_NAN_EVENT: |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_RX_WMA_MSG, |
| NO_SESSION, pMsg->type)); |
| if (pMsg->bodyptr) { |
| sme_nan_event(MAC_HANDLE(pMac), pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } |
| break; |
| #endif /* WLAN_FEATURE_NAN */ |
| case eWNI_SME_LINK_STATUS_IND: |
| { |
| tAniGetLinkStatus *pLinkStatus = |
| (tAniGetLinkStatus *) pMsg->bodyptr; |
| if (pLinkStatus) { |
| if (pMac->sme.link_status_callback) |
| pMac->sme.link_status_callback( |
| pLinkStatus->linkStatus, |
| pMac->sme.link_status_context); |
| |
| pMac->sme.link_status_callback = NULL; |
| pMac->sme.link_status_context = NULL; |
| qdf_mem_free(pLinkStatus); |
| } |
| break; |
| } |
| case eWNI_SME_MSG_GET_TEMPERATURE_IND: |
| if (pMac->sme.pGetTemperatureCb) |
| pMac->sme.pGetTemperatureCb(pMsg->bodyval, |
| pMac->sme.pTemperatureCbContext); |
| break; |
| case eWNI_SME_SNR_IND: |
| { |
| tAniGetSnrReq *pSnrReq = (tAniGetSnrReq *) pMsg->bodyptr; |
| |
| if (pSnrReq) { |
| if (pSnrReq->snrCallback) { |
| ((tCsrSnrCallback) |
| (pSnrReq->snrCallback)) |
| (pSnrReq->snr, pSnrReq->staId, |
| pSnrReq->pDevContext); |
| } |
| qdf_mem_free(pSnrReq); |
| } |
| break; |
| } |
| #ifdef FEATURE_WLAN_EXTSCAN |
| case eWNI_SME_EXTSCAN_FULL_SCAN_RESULT_IND: |
| if (pMac->sme.ext_scan_ind_cb) |
| pMac->sme.ext_scan_ind_cb(pMac->hdd_handle, |
| eSIR_EXTSCAN_FULL_SCAN_RESULT_IND, |
| pMsg->bodyptr); |
| else |
| sme_err("callback not registered to process: %d", |
| pMsg->type); |
| |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| case eWNI_SME_EPNO_NETWORK_FOUND_IND: |
| if (pMac->sme.ext_scan_ind_cb) |
| pMac->sme.ext_scan_ind_cb(pMac->hdd_handle, |
| eSIR_EPNO_NETWORK_FOUND_IND, |
| pMsg->bodyptr); |
| else |
| sme_err("callback not registered to process: %d", |
| pMsg->type); |
| |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| #endif |
| case eWNI_SME_SET_HW_MODE_RESP: |
| if (pMsg->bodyptr) { |
| status = sme_process_set_hw_mode_resp(pMac, |
| pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } else { |
| sme_err("Empty message for: %d", pMsg->type); |
| } |
| break; |
| case eWNI_SME_HW_MODE_TRANS_IND: |
| if (pMsg->bodyptr) { |
| status = sme_process_hw_mode_trans_ind(pMac, |
| pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } else { |
| sme_err("Empty message for: %d", pMsg->type); |
| } |
| break; |
| case eWNI_SME_NSS_UPDATE_RSP: |
| if (pMsg->bodyptr) { |
| status = sme_process_nss_update_resp(pMac, |
| pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } else { |
| sme_err("Empty message for: %d", pMsg->type); |
| } |
| break; |
| #ifdef WLAN_FEATURE_DSRC |
| case eWNI_SME_OCB_SET_CONFIG_RSP: |
| if (pMac->sme.ocb_set_config_callback) |
| pMac->sme.ocb_set_config_callback( |
| pMac->sme.ocb_set_config_context, |
| pMsg->bodyptr); |
| else |
| sme_err("No callback for Msg type: %d", pMsg->type); |
| pMac->sme.ocb_set_config_callback = NULL; |
| pMac->sme.ocb_set_config_context = NULL; |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| case eWNI_SME_OCB_GET_TSF_TIMER_RSP: |
| if (pMac->sme.ocb_get_tsf_timer_callback) |
| pMac->sme.ocb_get_tsf_timer_callback( |
| pMac->sme.ocb_get_tsf_timer_context, |
| pMsg->bodyptr); |
| else |
| sme_err("No callback for Msg type: %d", pMsg->type); |
| pMac->sme.ocb_get_tsf_timer_callback = NULL; |
| pMac->sme.ocb_get_tsf_timer_context = NULL; |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| case eWNI_SME_DCC_GET_STATS_RSP: |
| if (pMac->sme.dcc_get_stats_callback) |
| pMac->sme.dcc_get_stats_callback( |
| pMac->sme.dcc_get_stats_context, |
| pMsg->bodyptr); |
| else |
| sme_err("No callback for Msg type: %d", pMsg->type); |
| pMac->sme.dcc_get_stats_callback = NULL; |
| pMac->sme.dcc_get_stats_context = NULL; |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| case eWNI_SME_DCC_UPDATE_NDL_RSP: |
| if (pMac->sme.dcc_update_ndl_callback) |
| pMac->sme.dcc_update_ndl_callback( |
| pMac->sme.dcc_update_ndl_context, |
| pMsg->bodyptr); |
| else |
| sme_err("No callback for Msg type: %d", pMsg->type); |
| pMac->sme.dcc_update_ndl_callback = NULL; |
| pMac->sme.dcc_update_ndl_context = NULL; |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| case eWNI_SME_DCC_STATS_EVENT: |
| if (pMac->sme.dcc_stats_event_callback) |
| pMac->sme.dcc_stats_event_callback( |
| pMac->sme.dcc_stats_event_context, |
| pMsg->bodyptr); |
| else |
| sme_err("No callback for Msg type: %d", pMsg->type); |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| #endif |
| case eWNI_SME_SET_DUAL_MAC_CFG_RESP: |
| if (pMsg->bodyptr) { |
| status = sme_process_dual_mac_config_resp(pMac, |
| pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } else { |
| sme_err("Empty message for: %d", pMsg->type); |
| } |
| break; |
| case eWNI_SME_SET_THERMAL_LEVEL_IND: |
| if (pMac->sme.set_thermal_level_cb) |
| pMac->sme.set_thermal_level_cb(pMac->hdd_handle, |
| pMsg->bodyval); |
| break; |
| case eWNI_SME_EXT_CHANGE_CHANNEL_IND: |
| status = sme_extended_change_channel_ind(pMac, pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| case eWNI_SME_SET_ANTENNA_MODE_RESP: |
| if (pMsg->bodyptr) { |
| status = sme_process_antenna_mode_resp(pMac, |
| pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } else { |
| sme_err("Empty message for: %d", pMsg->type); |
| } |
| break; |
| case eWNI_SME_LOST_LINK_INFO_IND: |
| if (pMac->sme.lost_link_info_cb) |
| pMac->sme.lost_link_info_cb(pMac->hdd_handle, |
| (struct sir_lost_link_info *)pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| case eWNI_SME_RSO_CMD_STATUS_IND: |
| if (pMac->sme.rso_cmd_status_cb) |
| pMac->sme.rso_cmd_status_cb(pMac->hdd_handle, |
| pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| case eWMI_SME_LL_STATS_IND: |
| if (pMac->sme.link_layer_stats_ext_cb) |
| pMac->sme.link_layer_stats_ext_cb(pMac->hdd_handle, |
| pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| break; |
| case eWNI_SME_BT_ACTIVITY_INFO_IND: |
| if (pMac->sme.bt_activity_info_cb) |
| pMac->sme.bt_activity_info_cb(pMac->hdd_handle, |
| pMsg->bodyval); |
| break; |
| default: |
| |
| if ((pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN) |
| && (pMsg->type <= eWNI_SME_MSG_TYPES_END)) { |
| /* CSR */ |
| if (pMsg->bodyptr) { |
| status = csr_msg_processor(pMac, pMsg->bodyptr); |
| qdf_mem_free(pMsg->bodyptr); |
| } else |
| sme_err("Empty message for: %d", pMsg->type); |
| } else { |
| sme_warn("Unknown message type: %d", pMsg->type); |
| if (pMsg->bodyptr) |
| qdf_mem_free(pMsg->bodyptr); |
| } |
| } /* switch */ |
| release_lock: |
| sme_release_global_lock(&pMac->sme); |
| return status; |
| } |
| |
| QDF_STATUS sme_mc_process_handler(struct scheduler_msg *msg) |
| { |
| tpAniSirGlobal mac_ctx = cds_get_context(QDF_MODULE_ID_SME); |
| |
| if (mac_ctx == NULL) { |
| QDF_ASSERT(0); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return sme_process_msg(mac_ctx, msg); |
| } |
| |
| /** |
| * sme_process_nss_update_resp() - Process nss update response |
| * @mac: Global MAC pointer |
| * @msg: nss update response |
| * |
| * Processes the nss update response and invokes the HDD |
| * callback to process further |
| */ |
| static QDF_STATUS sme_process_nss_update_resp(tpAniSirGlobal mac, uint8_t *msg) |
| { |
| tListElem *entry = NULL; |
| tSmeCmd *command = NULL; |
| bool found; |
| policy_mgr_nss_update_cback callback = NULL; |
| struct sir_bcn_update_rsp *param; |
| |
| param = (struct sir_bcn_update_rsp *)msg; |
| if (!param) |
| sme_err("nss update resp param is NULL"); |
| /* Not returning. Need to check if active command list |
| * needs to be freed |
| */ |
| |
| if (param && param->reason != REASON_NSS_UPDATE) { |
| sme_err("reason not NSS update"); |
| return QDF_STATUS_E_INVAL; |
| } |
| entry = csr_nonscan_active_ll_peek_head(mac, LL_ACCESS_LOCK); |
| if (!entry) { |
| sme_err("No cmd found in active list"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| command = GET_BASE_ADDR(entry, tSmeCmd, Link); |
| if (!command) { |
| sme_err("Base address is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| if (e_sme_command_nss_update != command->command) { |
| sme_err("Command mismatch!"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| callback = command->u.nss_update_cmd.nss_update_cb; |
| if (callback) { |
| if (!param) |
| sme_err("Callback failed since nss update params is NULL"); |
| else |
| callback(command->u.nss_update_cmd.context, |
| param->status, |
| param->vdev_id, |
| command->u.nss_update_cmd.next_action, |
| command->u.nss_update_cmd.reason, |
| command->u.nss_update_cmd.original_vdev_id); |
| } else { |
| sme_err("Callback does not exisit"); |
| } |
| |
| found = csr_nonscan_active_ll_remove_entry(mac, entry, LL_ACCESS_LOCK); |
| if (found) { |
| /* Now put this command back on the avilable command list */ |
| csr_release_command(mac, command); |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS sme_stop(mac_handle_t mac_handle) |
| { |
| QDF_STATUS status; |
| QDF_STATUS ret_status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| |
| status = rrm_stop(mac); |
| if (QDF_IS_STATUS_ERROR(status)) { |
| ret_status = status; |
| sme_err("rrm_stop failed with status: %d", status); |
| } |
| |
| status = csr_stop(mac); |
| if (QDF_IS_STATUS_ERROR(status)) { |
| ret_status = status; |
| sme_err("csr_stop failed with status: %d", status); |
| } |
| |
| mac->sme.state = SME_STATE_STOP; |
| |
| return ret_status; |
| } |
| |
| /* |
| * sme_close() - Release all SME modules and their resources. |
| * The function release each module in SME, PMC, CSR, etc. . Upon |
| * return, all modules are at closed state. |
| * |
| * No SME APIs can be involved after smeClose except smeOpen. |
| * smeClose must be called before mac_close. |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open |
| * Return QDF_STATUS_SUCCESS - SME is successfully close. |
| * |
| * Other status means SME is failed to be closed but caller still cannot |
| * call any other SME functions except smeOpen. |
| */ |
| QDF_STATUS sme_close(mac_handle_t mac_handle) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| QDF_STATUS fail_status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (!pMac) |
| return QDF_STATUS_E_FAILURE; |
| |
| /* Note: pSession will be invalid from here on, do not access */ |
| status = csr_close(pMac); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("csr_close failed with status: %d", status); |
| fail_status = status; |
| } |
| #ifndef WLAN_MDM_CODE_REDUCTION_OPT |
| status = sme_qos_close(pMac); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("Qos close failed with status: %d", status); |
| fail_status = status; |
| } |
| #endif |
| status = sme_ps_close(mac_handle); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("sme_ps_close failed status: %d", status); |
| fail_status = status; |
| } |
| |
| status = rrm_close(pMac); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("RRM close failed with status: %d", status); |
| fail_status = status; |
| } |
| |
| free_sme_cmd_list(pMac); |
| |
| if (!QDF_IS_STATUS_SUCCESS |
| (qdf_mutex_destroy(&pMac->sme.lkSmeGlobalLock))) |
| fail_status = QDF_STATUS_E_FAILURE; |
| |
| if (!QDF_IS_STATUS_SUCCESS(fail_status)) |
| status = fail_status; |
| |
| pMac->sme.state = SME_STATE_STOP; |
| |
| return status; |
| } |
| |
| /** |
| * sme_remove_bssid_from_scan_list() - wrapper to remove the bssid from |
| * scan list |
| * @hal: hal context. |
| * @bssid: bssid to be removed |
| * |
| * This function remove the given bssid from scan list. |
| * |
| * Return: QDF status. |
| */ |
| QDF_STATUS sme_remove_bssid_from_scan_list(mac_handle_t hal, |
| tSirMacAddr bssid) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| csr_remove_bssid_from_scan_list(mac_ctx, bssid); |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| |
| return status; |
| } |
| |
| |
| /* |
| * sme_scan_get_result |
| * A wrapper function to request scan results from CSR. |
| * This is a synchronous call |
| * |
| * pFilter - If pFilter is NULL, all cached results are returned |
| * phResult - an object for the result. |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_scan_get_result(mac_handle_t mac_handle, uint8_t sessionId, |
| tCsrScanResultFilter *pFilter, |
| tScanResultHandle *phResult) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_MSG_SCAN_GET_RESULTS, sessionId, |
| 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_scan_get_result(pMac, pFilter, phResult); |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_scan_get_result_for_bssid(mac_handle_t mac_handle, |
| struct qdf_mac_addr *bssid, |
| tCsrScanResultInfo *res) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status; |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_scan_get_result_for_bssid(mac_ctx, bssid, res); |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| |
| return status; |
| } |
| |
| /** |
| * sme_get_ap_channel_from_scan() - a wrapper function to get |
| * AP's channel id from |
| * CSR by filtering the |
| * result which matches |
| * our roam profile. |
| * @profile: SAP profile |
| * @ap_chnl_id: pointer to channel id of SAP. Fill the value after finding the |
| * best ap from scan cache. |
| * |
| * This function is written to get AP's channel id from CSR by filtering |
| * the result which matches our roam profile. This is a synchronous call. |
| * |
| * Return: QDF_STATUS. |
| */ |
| QDF_STATUS sme_get_ap_channel_from_scan(void *profile, |
| tScanResultHandle *scan_cache, |
| uint8_t *ap_chnl_id) |
| { |
| return sme_get_ap_channel_from_scan_cache((struct csr_roam_profile *) |
| profile, |
| scan_cache, |
| ap_chnl_id); |
| } |
| |
| /** |
| * sme_get_ap_channel_from_scan_cache() - a wrapper function to get AP's |
| * channel id from CSR by filtering the |
| * result which matches our roam profile. |
| * @profile: SAP adapter |
| * @ap_chnl_id: pointer to channel id of SAP. Fill the value after finding the |
| * best ap from scan cache. |
| * |
| * This function is written to get AP's channel id from CSR by filtering |
| * the result which matches our roam profile. This is a synchronous call. |
| * |
| * Return: QDF_STATUS. |
| */ |
| QDF_STATUS sme_get_ap_channel_from_scan_cache( |
| struct csr_roam_profile *profile, tScanResultHandle *scan_cache, |
| uint8_t *ap_chnl_id) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal mac_ctx = sme_get_mac_context(); |
| tCsrScanResultFilter *scan_filter = NULL; |
| tScanResultHandle filtered_scan_result = NULL; |
| tSirBssDescription first_ap_profile; |
| |
| if (NULL == mac_ctx) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("mac_ctx is NULL")); |
| return QDF_STATUS_E_FAILURE; |
| } |
| scan_filter = qdf_mem_malloc(sizeof(tCsrScanResultFilter)); |
| if (!scan_filter) |
| return QDF_STATUS_E_FAILURE; |
| |
| qdf_mem_set(&first_ap_profile, sizeof(tSirBssDescription), 0); |
| if (NULL == profile) { |
| scan_filter->EncryptionType.numEntries = 1; |
| scan_filter->EncryptionType.encryptionType[0] |
| = eCSR_ENCRYPT_TYPE_NONE; |
| } else { |
| /* Here is the profile we need to connect to */ |
| status = csr_roam_prepare_filter_from_profile(mac_ctx, |
| profile, |
| scan_filter); |
| } |
| |
| if (QDF_STATUS_SUCCESS == status) { |
| /* Save the WPS info */ |
| if (NULL != profile) { |
| scan_filter->bWPSAssociation = |
| profile->bWPSAssociation; |
| scan_filter->bOSENAssociation = |
| profile->bOSENAssociation; |
| } else { |
| scan_filter->bWPSAssociation = 0; |
| scan_filter->bOSENAssociation = 0; |
| } |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Preparing the profile filter failed")); |
| qdf_mem_free(scan_filter); |
| return QDF_STATUS_E_FAILURE; |
| } |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| status = csr_scan_get_result(mac_ctx, scan_filter, |
| &filtered_scan_result); |
| if (QDF_STATUS_SUCCESS == status) { |
| csr_get_bssdescr_from_scan_handle(filtered_scan_result, |
| &first_ap_profile); |
| *scan_cache = filtered_scan_result; |
| if (0 != first_ap_profile.channelId) { |
| *ap_chnl_id = first_ap_profile.channelId; |
| QDF_TRACE(QDF_MODULE_ID_SME, |
| QDF_TRACE_LEVEL_DEBUG, |
| FL("Found best AP & its on chnl[%d]"), |
| first_ap_profile.channelId); |
| } else { |
| /* |
| * This means scan result is empty |
| * so set the channel to zero, caller should |
| * take of zero channel id case. |
| */ |
| *ap_chnl_id = 0; |
| QDF_TRACE(QDF_MODULE_ID_SME, |
| QDF_TRACE_LEVEL_ERROR, |
| FL("Scan is empty, set chnl to 0")); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| } else { |
| sme_err("Failed to get scan get result"); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| csr_free_scan_filter(mac_ctx, scan_filter); |
| sme_release_global_lock(&mac_ctx->sme); |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Aquiring lock failed")); |
| csr_free_scan_filter(mac_ctx, scan_filter); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| qdf_mem_free(scan_filter); |
| return status; |
| } |
| |
| /** |
| * sme_store_joinreq_param() - This function will pass station's join |
| * request to store to csr. |
| * @mac_handle: pointer to hal context. |
| * @profile: pointer to station's roam profile. |
| * @scan_cache: pointer to station's scan cache. |
| * @roam_id: reference to roam_id variable being passed. |
| * @session_id: station's session id. |
| * |
| * This function will pass station's join request further down to csr |
| * to store it. this stored parameter will be used later. |
| * |
| * Return: true or false based on function's overall success. |
| **/ |
| bool sme_store_joinreq_param(mac_handle_t mac_handle, |
| struct csr_roam_profile *profile, |
| tScanResultHandle scan_cache, |
| uint32_t *roam_id, |
| uint32_t session_id) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| bool ret_status = true; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_STORE_JOIN_REQ, |
| session_id, 0)); |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| if (false == csr_store_joinreq_param(mac_ctx, profile, |
| scan_cache, roam_id, session_id)) |
| ret_status = false; |
| sme_release_global_lock(&mac_ctx->sme); |
| } else { |
| ret_status = false; |
| } |
| |
| return ret_status; |
| } |
| |
| /** |
| * sme_clear_joinreq_param() - This function will pass station's clear |
| * the join request to csr. |
| * @mac_handle: pointer to hal context. |
| * @session_id: station's session id. |
| * |
| * This function will pass station's clear join request further down to csr |
| * to cleanup. |
| * |
| * Return: true or false based on function's overall success. |
| **/ |
| bool sme_clear_joinreq_param(mac_handle_t mac_handle, |
| uint32_t session_id) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| bool ret_status = true; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_CLEAR_JOIN_REQ, |
| session_id, 0)); |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| if (false == csr_clear_joinreq_param(mac_ctx, |
| session_id)) |
| ret_status = false; |
| sme_release_global_lock(&mac_ctx->sme); |
| } else { |
| ret_status = false; |
| } |
| |
| return ret_status; |
| } |
| |
| /** |
| * sme_issue_stored_joinreq() - This function will issues station's stored |
| * the join request to csr. |
| * @mac_handle: pointer to hal context. |
| * @roam_id: reference to roam_id variable being passed. |
| * @session_id: station's session id. |
| * |
| * This function will issue station's stored join request further down to csr |
| * to proceed forward. |
| * |
| * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE. |
| **/ |
| QDF_STATUS sme_issue_stored_joinreq(mac_handle_t mac_handle, |
| uint32_t *roam_id, |
| uint32_t session_id) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| QDF_STATUS ret_status = QDF_STATUS_SUCCESS; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_ISSUE_JOIN_REQ, |
| session_id, 0)); |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| if (QDF_STATUS_SUCCESS != csr_issue_stored_joinreq(mac_ctx, |
| roam_id, |
| session_id)) { |
| ret_status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&mac_ctx->sme); |
| } else { |
| csr_clear_joinreq_param(mac_ctx, session_id); |
| ret_status = QDF_STATUS_E_FAILURE; |
| } |
| return ret_status; |
| } |
| |
| /* |
| * sme_scan_flush_result() - |
| * A wrapper function to request CSR to clear scan results. |
| * This is a synchronous call |
| * |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_scan_flush_result(mac_handle_t mac_handle) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_MSG_SCAN_FLUSH_RESULTS, |
| 0, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_scan_flush_result(pMac); |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_filter_scan_results() - |
| * A wrapper function to request CSR to clear scan results. |
| * This is a synchronous call |
| * |
| * mac_handle_t - HAL context handle |
| * sessionId - session id |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_filter_scan_results(mac_handle_t mac_handle, uint8_t sessionId) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_MSG_SCAN_FLUSH_RESULTS, |
| sessionId, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| csr_scan_filter_results(pMac); |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_scan_flush_p2p_result(mac_handle_t mac_handle, uint8_t sessionId) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_MSG_SCAN_FLUSH_P2PRESULTS, |
| sessionId, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_scan_flush_selective_result(pMac, true); |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_scan_result_get_first() - |
| * A wrapper function to request CSR to returns the first element of |
| * scan result. |
| * This is a synchronous call |
| * |
| * hScanResult - returned from csr_scan_get_result |
| * Return tCsrScanResultInfo * - NULL if no result |
| */ |
| tCsrScanResultInfo *sme_scan_result_get_first(mac_handle_t mac_handle, |
| tScanResultHandle hScanResult) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| tCsrScanResultInfo *pRet = NULL; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_MSG_SCAN_RESULT_GETFIRST, |
| NO_SESSION, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| pRet = csr_scan_result_get_first(pMac, hScanResult); |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return pRet; |
| } |
| |
| /* |
| * sme_scan_result_get_next() - |
| * A wrapper function to request CSR to returns the next element of |
| * scan result. It can be called without calling csr_scan_result_get_first first |
| * This is a synchronous call |
| * |
| * hScanResult - returned from csr_scan_get_result |
| * Return Null if no result or reach the end |
| */ |
| tCsrScanResultInfo *sme_scan_result_get_next(mac_handle_t mac_handle, |
| tScanResultHandle hScanResult) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| tCsrScanResultInfo *pRet = NULL; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| pRet = csr_scan_result_get_next(pMac, hScanResult); |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return pRet; |
| } |
| |
| /* |
| * sme_scan_result_purge() - |
| * A wrapper function to request CSR to remove all items(tCsrScanResult) |
| * in the list and free memory for each item |
| * This is a synchronous call |
| * |
| * hScanResult - returned from csr_scan_get_result. hScanResult is |
| * considered gone by |
| * calling this function and even before this function reutrns. |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_scan_result_purge(tScanResultHandle hScanResult) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal mac_ctx = sme_get_mac_context(); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_MSG_SCAN_RESULT_PURGE, |
| NO_SESSION, 0)); |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_scan_result_purge(mac_ctx, hScanResult); |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| |
| return status; |
| } |
| |
| eCsrPhyMode sme_get_phy_mode(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.phyMode; |
| } |
| |
| /* |
| * sme_get_channel_bonding_mode5_g() - get the channel bonding mode for 5G band |
| * |
| * mac_handle - HAL handle |
| * mode - channel bonding mode |
| * |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_get_channel_bonding_mode5_g(mac_handle_t mac_handle, |
| uint32_t *mode) |
| { |
| tSmeConfigParams *smeConfig; |
| |
| if (!mode) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: invalid mode", __func__); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| smeConfig = qdf_mem_malloc(sizeof(*smeConfig)); |
| if (!smeConfig) |
| return QDF_STATUS_E_NOMEM; |
| |
| if (sme_get_config_param(mac_handle, smeConfig) != QDF_STATUS_SUCCESS) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: sme_get_config_param failed", __func__); |
| qdf_mem_free(smeConfig); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| *mode = smeConfig->csrConfig.channelBondingMode5GHz; |
| qdf_mem_free(smeConfig); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /* |
| * sme_get_channel_bonding_mode24_g() - get the channel bonding mode for 2.4G |
| * band |
| * |
| * mac_handle - HAL handle |
| * mode - channel bonding mode |
| * |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_get_channel_bonding_mode24_g(mac_handle_t mac_handle, |
| uint32_t *mode) |
| { |
| tSmeConfigParams *smeConfig; |
| |
| if (!mode) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: invalid mode", __func__); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| smeConfig = qdf_mem_malloc(sizeof(*smeConfig)); |
| if (!smeConfig) |
| return QDF_STATUS_E_NOMEM; |
| |
| if (sme_get_config_param(mac_handle, smeConfig) != QDF_STATUS_SUCCESS) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: sme_get_config_param failed", __func__); |
| qdf_mem_free(smeConfig); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| *mode = smeConfig->csrConfig.channelBondingMode24GHz; |
| qdf_mem_free(smeConfig); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /* |
| * sme_roam_connect() - |
| * A wrapper function to request CSR to inititiate an association |
| * This is an asynchronous call. |
| * |
| * sessionId - the sessionId returned by sme_open_session. |
| * pProfile - description of the network to which to connect |
| * hBssListIn - a list of BSS descriptor to roam to. It is returned |
| * from csr_scan_get_result |
| * pRoamId - to get back the request ID |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_roam_connect(mac_handle_t mac_handle, uint8_t sessionId, |
| struct csr_roam_profile *pProfile, |
| uint32_t *pRoamId) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (!pMac) |
| return QDF_STATUS_E_FAILURE; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_MSG_CONNECT, sessionId, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(pMac, sessionId)) { |
| status = |
| csr_roam_connect(pMac, sessionId, pProfile, |
| pRoamId); |
| } else { |
| sme_err("Invalid sessionID: %d", sessionId); |
| status = QDF_STATUS_E_INVAL; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } else { |
| sme_err("sme_acquire_global_lock failed"); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_set_phy_mode() - |
| * Changes the PhyMode. |
| * |
| * mac_handle - The handle returned by mac_open. |
| * phyMode new phyMode which is to set |
| * Return QDF_STATUS SUCCESS. |
| */ |
| QDF_STATUS sme_set_phy_mode(mac_handle_t mac_handle, eCsrPhyMode phyMode) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| pMac->roam.configParam.phyMode = phyMode; |
| pMac->roam.configParam.uCfgDot11Mode = |
| csr_get_cfg_dot11_mode_from_csr_phy_mode(NULL, |
| pMac->roam.configParam.phyMode, |
| pMac->roam.configParam. |
| ProprietaryRatesEnabled); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /* |
| * sme_roam_reassoc() - |
| * A wrapper function to request CSR to inititiate a re-association |
| * |
| * pProfile - can be NULL to join the currently connected AP. In that |
| * case modProfileFields should carry the modified field(s) which could trigger |
| * reassoc |
| * modProfileFields - fields which are part of tCsrRoamConnectedProfile |
| * that might need modification dynamically once STA is up & running and this |
| * could trigger a reassoc |
| * pRoamId - to get back the request ID |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_roam_reassoc(mac_handle_t mac_handle, uint8_t sessionId, |
| struct csr_roam_profile *pProfile, |
| tCsrRoamModifyProfileFields modProfileFields, |
| uint32_t *pRoamId, bool fForce) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_ROAM_REASSOC, sessionId, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(pMac, sessionId)) { |
| if ((NULL == pProfile) && (fForce == 1)) |
| status = csr_reassoc(pMac, sessionId, |
| &modProfileFields, pRoamId, |
| fForce); |
| else |
| status = csr_roam_reassoc(pMac, sessionId, |
| pProfile, |
| modProfileFields, pRoamId); |
| } else { |
| status = QDF_STATUS_E_INVAL; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_roam_connect_to_last_profile() - |
| * A wrapper function to request CSR to disconnect and reconnect with |
| * the same profile |
| * This is an asynchronous call. |
| * |
| * Return QDF_STATUS. It returns fail if currently connected |
| */ |
| QDF_STATUS sme_roam_connect_to_last_profile(mac_handle_t mac_handle, |
| uint8_t sessionId) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_ROAM_GET_CONNECTPROFILE, |
| sessionId, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(pMac, sessionId)) |
| status = csr_roam_connect_to_last_profile(pMac, |
| sessionId); |
| else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_roam_disconnect(mac_handle_t hal, uint8_t session_id, |
| eCsrRoamDisconnectReason reason) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_ROAM_DISCONNECT, session_id, |
| reason)); |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(mac_ctx, session_id)) |
| status = csr_roam_disconnect(mac_ctx, session_id, |
| reason); |
| else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| |
| return status; |
| } |
| |
| /* sme_dhcp_done_ind() - send dhcp done ind |
| * @hal: hal context |
| * @session_id: session id |
| * |
| * Return: void. |
| */ |
| void sme_dhcp_done_ind(mac_handle_t hal, uint8_t session_id) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct csr_roam_session *session; |
| |
| if (!mac_ctx) |
| return; |
| |
| session = CSR_GET_SESSION(mac_ctx, session_id); |
| if (!session) { |
| sme_err("Session: %d not found", session_id); |
| return; |
| } |
| session->dhcp_done = true; |
| } |
| |
| /* |
| * sme_roam_stop_bss() - |
| * To stop BSS for Soft AP. This is an asynchronous API. |
| * |
| * mac_handle - Global structure |
| * sessionId - sessionId of SoftAP |
| * Return QDF_STATUS SUCCESS Roam callback will be called to indicate |
| * actual results |
| */ |
| QDF_STATUS sme_roam_stop_bss(mac_handle_t mac_handle, uint8_t sessionId) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(pMac, sessionId)) |
| status = csr_roam_issue_stop_bss_cmd(pMac, sessionId, |
| false); |
| else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /** |
| * sme_roam_disconnect_sta() - disassociate a station |
| * @mac_handle: Global structure |
| * @sessionId: SessionId of SoftAP |
| * @p_del_sta_params: Pointer to parameters of the station to disassoc |
| * |
| * To disassociate a station. This is an asynchronous API. |
| * |
| * Return: QDF_STATUS_SUCCESS on success.Roam callback will |
| * be called to indicate actual result. |
| */ |
| QDF_STATUS sme_roam_disconnect_sta(mac_handle_t mac_handle, uint8_t sessionId, |
| struct csr_del_sta_params *p_del_sta_params) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (NULL == pMac) { |
| QDF_ASSERT(0); |
| return status; |
| } |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(pMac, sessionId)) |
| status = csr_roam_issue_disassociate_sta_cmd(pMac, |
| sessionId, p_del_sta_params); |
| else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /** |
| * sme_roam_deauth_sta() - deauthenticate a station |
| * @mac_handle: Global structure |
| * @sessionId: SessionId of SoftAP |
| * @pDelStaParams: Pointer to parameters of the station to deauthenticate |
| * |
| * To disassociate a station. This is an asynchronous API. |
| * |
| * Return: QDF_STATUS_SUCCESS on success or another QDF_STATUS error |
| * code on error. Roam callback will be called to indicate actual |
| * result |
| */ |
| QDF_STATUS sme_roam_deauth_sta(mac_handle_t mac_handle, uint8_t sessionId, |
| struct csr_del_sta_params *pDelStaParams) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (NULL == pMac) { |
| QDF_ASSERT(0); |
| return status; |
| } |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_MSG_DEAUTH_STA, |
| sessionId, pDelStaParams->reason_code)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(pMac, sessionId)) |
| status = |
| csr_roam_issue_deauth_sta_cmd(pMac, sessionId, |
| pDelStaParams); |
| else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_roam_get_associated_stas() - |
| * To probe the list of associated stations from various modules |
| * of CORE stack. |
| * This is an asynchronous API. |
| * |
| * sessionId - sessionId of SoftAP |
| * modId - Module from whom list of associtated stations is |
| * to be probed. If an invalid module is passed then |
| * by default QDF_MODULE_ID_PE will be probed. |
| * pUsrContext - Opaque HDD context |
| * pfnSapEventCallback - Sap event callback in HDD |
| * pAssocBuf - Caller allocated memory to be filled with associatd |
| * stations info |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_roam_get_associated_stas(mac_handle_t mac_handle, |
| uint8_t sessionId, |
| QDF_MODULE_ID modId, void *pUsrContext, |
| void *pfnSapEventCallback, |
| uint8_t *pAssocStasBuf) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (NULL == pMac) { |
| QDF_ASSERT(0); |
| return status; |
| } |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(pMac, sessionId)) |
| status = |
| csr_roam_get_associated_stas(pMac, sessionId, |
| modId, |
| pUsrContext, |
| pfnSapEventCallback, |
| pAssocStasBuf); |
| else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_roam_get_connect_state() - |
| * A wrapper function to request CSR to return the current connect state |
| * of Roaming |
| * This is a synchronous call. |
| * |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_roam_get_connect_state(mac_handle_t mac_handle, |
| uint8_t sessionId, |
| eCsrConnectState *pState) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(pMac, sessionId)) |
| status = csr_roam_get_connect_state(pMac, sessionId, |
| pState); |
| else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_roam_get_connect_profile() - |
| * A wrapper function to request CSR to return the current connect |
| * profile. Caller must call csr_roam_free_connect_profile after it is done |
| * and before reuse for another csr_roam_get_connect_profile call. |
| * This is a synchronous call. |
| * |
| * pProfile - pointer to a caller allocated structure |
| * tCsrRoamConnectedProfile |
| * eturn QDF_STATUS. Failure if not connected |
| */ |
| QDF_STATUS sme_roam_get_connect_profile(mac_handle_t mac_handle, |
| uint8_t sessionId, |
| tCsrRoamConnectedProfile *pProfile) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_ROAM_GET_CONNECTPROFILE, |
| sessionId, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(pMac, sessionId)) |
| status = csr_roam_get_connect_profile(pMac, sessionId, |
| pProfile); |
| else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /** |
| * sme_roam_free_connect_profile - a wrapper function to request CSR to free and |
| * reinitialize the profile returned previously by csr_roam_get_connect_profile. |
| * |
| * @profile - pointer to a caller allocated structure tCsrRoamConnectedProfile |
| * |
| * Return: none |
| */ |
| void sme_roam_free_connect_profile(tCsrRoamConnectedProfile *profile) |
| { |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_ROAM_FREE_CONNECTPROFILE, |
| NO_SESSION, 0)); |
| csr_roam_free_connect_profile(profile); |
| } |
| |
| /* |
| * sme_roam_set_pmkid_cache() - |
| * A wrapper function to request CSR to return the PMKID candidate list |
| * This is a synchronous call. |
| |
| * pPMKIDCache - caller allocated buffer point to an array of |
| * tPmkidCacheInfo |
| * numItems - a variable that has the number of tPmkidCacheInfo |
| * allocated when retruning, this is either the number needed |
| * or number of items put into pPMKIDCache |
| * update_entire_cache - this bool value specifies if the entire pmkid |
| * cache should be overwritten or should it be |
| * updated entry by entry. |
| * Return QDF_STATUS - when fail, it usually means the buffer allocated is not |
| * big enough and pNumItems has the number of |
| * tPmkidCacheInfo. |
| * \Note: pNumItems is a number of tPmkidCacheInfo, |
| * not sizeof(tPmkidCacheInfo) * something |
| */ |
| QDF_STATUS sme_roam_set_pmkid_cache(mac_handle_t mac_handle, uint8_t sessionId, |
| tPmkidCacheInfo *pPMKIDCache, |
| uint32_t numItems, bool update_entire_cache) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_ROAM_SET_PMKIDCACHE, sessionId, |
| numItems)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(pMac, sessionId)) |
| status = csr_roam_set_pmkid_cache(pMac, sessionId, |
| pPMKIDCache, |
| numItems, update_entire_cache); |
| else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_roam_del_pmkid_from_cache(mac_handle_t mac_handle, |
| uint8_t sessionId, |
| tPmkidCacheInfo *pmksa, |
| bool flush_cache) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_ROAM_DEL_PMKIDCACHE, |
| sessionId, flush_cache)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(pMac, sessionId)) |
| status = csr_roam_del_pmkid_from_cache(pMac, sessionId, |
| pmksa, flush_cache); |
| else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| #ifdef WLAN_FEATURE_ROAM_OFFLOAD |
| void sme_get_pmk_info(mac_handle_t hal, uint8_t session_id, |
| tPmkidCacheInfo *pmk_cache) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| QDF_STATUS status = sme_acquire_global_lock(&mac_ctx->sme); |
| |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(mac_ctx, session_id)) |
| csr_get_pmk_info(mac_ctx, session_id, pmk_cache); |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| } |
| #else |
| static inline |
| void sme_get_pmk_info(mac_handle_t hal, uint8_t session_id, |
| tPmkidCacheInfo *pmk_cache) |
| {} |
| #endif |
| |
| #ifdef WLAN_FEATURE_ROAM_OFFLOAD |
| /* |
| * \fn sme_roam_set_psk_pmk |
| * \brief a wrapper function to request CSR to save PSK/PMK |
| * This is a synchronous call. |
| * \param mac_handle - Global structure |
| * \param sessionId - SME sessionId |
| * \param pPSK_PMK - pointer to an array of Psk[]/Pmk |
| * \param pmk_len - Length could be only 16 bytes in case if LEAP |
| * connections. Need to pass this information to |
| * firmware. |
| * \return QDF_STATUS -status whether PSK/PMK is set or not |
| */ |
| QDF_STATUS sme_roam_set_psk_pmk(mac_handle_t mac_handle, uint8_t sessionId, |
| uint8_t *pPSK_PMK, size_t pmk_len) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(pMac, sessionId)) |
| status = csr_roam_set_psk_pmk(pMac, sessionId, pPSK_PMK, |
| pmk_len); |
| else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| #endif |
| |
| QDF_STATUS sme_roam_get_wpa_rsn_req_ie(mac_handle_t hal, uint8_t session_id, |
| uint32_t *len, uint8_t *buf) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(mac, session_id)) |
| status = csr_roam_get_wpa_rsn_req_ie(mac, session_id, |
| len, buf); |
| else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&mac->sme); |
| } |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_roam_get_wpa_rsn_rsp_ie(mac_handle_t hal, uint8_t session_id, |
| uint32_t *len, uint8_t *buf) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(mac, session_id)) |
| status = csr_roam_get_wpa_rsn_rsp_ie(mac, session_id, |
| len, buf); |
| else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&mac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_roam_get_num_pmkid_cache() - |
| * A wrapper function to request CSR to return number of PMKID cache |
| * entries |
| * This is a synchronous call. |
| * |
| * Return uint32_t - the number of PMKID cache entries |
| */ |
| uint32_t sme_roam_get_num_pmkid_cache(mac_handle_t mac_handle, |
| uint8_t sessionId) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| uint32_t numPmkidCache = 0; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(pMac, sessionId)) { |
| numPmkidCache = |
| csr_roam_get_num_pmkid_cache(pMac, sessionId); |
| status = QDF_STATUS_SUCCESS; |
| } else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return numPmkidCache; |
| } |
| |
| /* |
| * sme_roam_get_pmkid_cache() - |
| * A wrapper function to request CSR to return PMKID cache from CSR |
| * This is a synchronous call. |
| * |
| * pNum - caller allocated memory that has the space of the number of |
| * pBuf tPmkidCacheInfo as input. Upon returned, *pNum has the |
| * needed or actually number in tPmkidCacheInfo. |
| * pPmkidCache - Caller allocated memory that contains PMKID cache, if |
| * any, upon return |
| * Return QDF_STATUS - when fail, it usually means the buffer allocated is not |
| * big enough |
| */ |
| QDF_STATUS sme_roam_get_pmkid_cache(mac_handle_t mac_handle, uint8_t sessionId, |
| uint32_t *pNum, tPmkidCacheInfo *pPmkidCache) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_ROAM_GET_PMKIDCACHE, sessionId, |
| 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(pMac, sessionId)) |
| status = csr_roam_get_pmkid_cache(pMac, sessionId, pNum, |
| pPmkidCache); |
| else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_get_config_param() - |
| * A wrapper function that HDD calls to get the global settings |
| * currently maintained by CSR. |
| * This is a synchronous call. |
| * |
| * pParam - caller allocated memory |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_get_config_param(mac_handle_t mac_handle, |
| tSmeConfigParams *pParam) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_GET_CONFIGPARAM, NO_SESSION, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_get_config_param(pMac, &pParam->csrConfig); |
| if (status != QDF_STATUS_SUCCESS) { |
| sme_err("csr_get_config_param failed"); |
| sme_release_global_lock(&pMac->sme); |
| return status; |
| } |
| qdf_mem_copy(&pParam->rrmConfig, |
| &pMac->rrm.rrmSmeContext.rrmConfig, |
| sizeof(pMac->rrm.rrmSmeContext.rrmConfig)); |
| pParam->snr_monitor_enabled = pMac->snr_monitor_enabled; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /** |
| * sme_cfg_set_int() - Sets the cfg parameter value. |
| * @hal: Handle to hal. |
| * @cfg_id: Configuration parameter ID. |
| * @value: value to be saved in the cfg parameter. |
| * |
| * This function sets the string value in cfg parameter. |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_cfg_set_int(mac_handle_t hal, uint16_t cfg_id, uint32_t value) |
| { |
| tpAniSirGlobal pmac = PMAC_STRUCT(hal); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| if (QDF_STATUS_SUCCESS != cfg_set_int(pmac, cfg_id, value)) |
| status = QDF_STATUS_E_FAILURE; |
| |
| return status; |
| } |
| |
| /** |
| * sme_cfg_set_str() - Sets the cfg parameter string. |
| * @hal: Handle to hal. |
| * @cfg_id: Configuration parameter ID. |
| * @str: Pointer to the string buffer. |
| * @length: Length of the string. |
| * |
| * This function sets the string value in cfg parameter. |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_cfg_set_str(mac_handle_t hal, uint16_t cfg_id, uint8_t *str, |
| uint32_t length) |
| { |
| tpAniSirGlobal pmac = PMAC_STRUCT(hal); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| if (QDF_STATUS_SUCCESS != cfg_set_str(pmac, cfg_id, str, length)) |
| status = QDF_STATUS_E_FAILURE; |
| |
| return status; |
| } |
| |
| /** |
| * sme_cfg_get_int() - Gets the cfg parameter value. |
| * @hal: Handle to hal. |
| * @cfg_id: Configuration parameter ID. |
| * @cfg_value: Pointer to variable in which cfg value |
| * will be saved. |
| * |
| * This function gets the value of the cfg parameter. |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_cfg_get_int(mac_handle_t hal, uint16_t cfg_id, |
| uint32_t *cfg_value) |
| { |
| tpAniSirGlobal pmac = PMAC_STRUCT(hal); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| if (QDF_STATUS_SUCCESS != wlan_cfg_get_int(pmac, cfg_id, cfg_value)) |
| status = QDF_STATUS_E_FAILURE; |
| |
| return status; |
| } |
| |
| /** |
| * sme_cfg_get_str() - Gets the cfg parameter string. |
| * @hal: Handle to hal. |
| * @cfg_id: Configuration parameter ID. |
| * @str: Pointer to the string buffer. |
| * @length: Pointer to length of the string. |
| * |
| * This function gets the string value of the cfg parameter. |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_cfg_get_str(mac_handle_t hal, uint16_t cfg_id, uint8_t *str, |
| uint32_t *length) |
| { |
| tpAniSirGlobal pmac = PMAC_STRUCT(hal); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| if (QDF_STATUS_SUCCESS != wlan_cfg_get_str(pmac, cfg_id, str, length)) |
| status = QDF_STATUS_E_INVAL; |
| |
| return status; |
| } |
| |
| /* |
| * sme_get_modify_profile_fields() - |
| * HDD or SME - QOS calls this function to get the current values of |
| * connected profile fields, changing which can cause reassoc. |
| * This function must be called after CFG is downloaded and STA is in connected |
| * state. Also, make sure to call this function to get the current profile |
| * fields before calling the reassoc. So that pModifyProfileFields will have |
| * all the latest values plus the one(s) has been updated as part of reassoc |
| * request. |
| * |
| * pModifyProfileFields - pointer to the connected profile fields |
| * changing which can cause reassoc |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_get_modify_profile_fields(mac_handle_t mac_handle, |
| uint8_t sessionId, |
| tCsrRoamModifyProfileFields * |
| pModifyProfileFields) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_GET_MODPROFFIELDS, sessionId, |
| 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(pMac, sessionId)) |
| status = csr_get_modify_profile_fields(pMac, sessionId, |
| pModifyProfileFields); |
| else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_set_dhcp_till_power_active_flag() - |
| * Sets/Clears DHCP related flag to disable/enable auto PS |
| * |
| * hal - The handle returned by mac_open. |
| */ |
| void sme_set_dhcp_till_power_active_flag(mac_handle_t hal, uint8_t flag) |
| { |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| struct ps_global_info *ps_global_info = &mac->sme.ps_global_info; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_SET_DHCP_FLAG, NO_SESSION, |
| flag)); |
| /* Set/Clear the DHCP flag which will disable/enable auto PS */ |
| ps_global_info->remain_in_power_active_till_dhcp = flag; |
| } |
| |
| #ifdef FEATURE_OEM_DATA_SUPPORT |
| /** |
| * sme_register_oem_data_rsp_callback() - Register a routine of |
| * type send_oem_data_rsp_msg |
| * @mac_handle: Handle returned by mac_open. |
| * @callback: Callback to send response |
| * to oem application. |
| * |
| * sme_oem_data_rsp_callback is used to register sme_send_oem_data_rsp_msg |
| * callback function. |
| * |
| * Return: QDF_STATUS. |
| */ |
| QDF_STATUS sme_register_oem_data_rsp_callback(mac_handle_t mac_handle, |
| sme_send_oem_data_rsp_msg callback) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pmac = PMAC_STRUCT(mac_handle); |
| |
| pmac->sme.oem_data_rsp_callback = callback; |
| |
| return status; |
| |
| } |
| |
| /** |
| * sme_deregister_oem_data_rsp_callback() - De-register OEM datarsp callback |
| * @mac_handle: Handler return by mac_open |
| * This function De-registers the OEM data response callback to SME |
| * |
| * Return: None |
| */ |
| void sme_deregister_oem_data_rsp_callback(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pmac; |
| |
| if (!mac_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("mac_handle is not valid")); |
| return; |
| } |
| pmac = PMAC_STRUCT(mac_handle); |
| |
| pmac->sme.oem_data_rsp_callback = NULL; |
| } |
| |
| /** |
| * sme_oem_update_capability() - update UMAC's oem related capability. |
| * @hal: Handle returned by mac_open |
| * @oem_cap: pointer to oem_capability |
| * |
| * This function updates OEM capability to UMAC. Currently RTT |
| * related capabilities are updated. More capabilities can be |
| * added in future. |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_oem_update_capability(mac_handle_t hal, |
| struct sme_oem_capability *cap) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pmac = PMAC_STRUCT(hal); |
| uint8_t *bytes; |
| |
| bytes = pmac->rrm.rrmSmeContext.rrmConfig.rm_capability; |
| |
| if (cap->ftm_rr) |
| bytes[4] |= RM_CAP_FTM_RANGE_REPORT; |
| if (cap->lci_capability) |
| bytes[4] |= RM_CAP_CIVIC_LOC_MEASUREMENT; |
| |
| return status; |
| } |
| |
| /** |
| * sme_oem_get_capability() - get oem capability |
| * @hal: Handle returned by mac_open |
| * @oem_cap: pointer to oem_capability |
| * |
| * This function is used to get the OEM capability from UMAC. |
| * Currently RTT related capabilities are received. More |
| * capabilities can be added in future. |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_oem_get_capability(mac_handle_t hal, |
| struct sme_oem_capability *cap) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pmac = PMAC_STRUCT(hal); |
| uint8_t *bytes; |
| |
| bytes = pmac->rrm.rrmSmeContext.rrmConfig.rm_capability; |
| |
| cap->ftm_rr = bytes[4] & RM_CAP_FTM_RANGE_REPORT; |
| cap->lci_capability = bytes[4] & RM_CAP_CIVIC_LOC_MEASUREMENT; |
| |
| return status; |
| } |
| #endif |
| |
| /** |
| * sme_roam_set_key() - To set encryption key. |
| * @hal: hal global context |
| * @session_id: session id |
| * @set_key: pointer to a caller allocated object of tCsrSetContextInfo |
| * @ptr_roam_id: Upon success return, this is the id caller can use to |
| * identify the request in roamcallback |
| * |
| * This function should be called only when connected. This is an asynchronous |
| * API. |
| * |
| * Return: Status of operation |
| */ |
| QDF_STATUS sme_roam_set_key(mac_handle_t hal, uint8_t session_id, |
| tCsrRoamSetKey *set_key, uint32_t *ptr_roam_id) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| uint32_t roam_id; |
| struct csr_roam_session *session = NULL; |
| struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_RX_HDD_SET_KEY, |
| session_id, 0)); |
| if (set_key->keyLength > CSR_MAX_KEY_LEN) { |
| sme_err("Invalid key length: %d", set_key->keyLength); |
| return QDF_STATUS_E_FAILURE; |
| } |
| /*Once Setkey is done, we can go in BMPS */ |
| if (set_key->keyLength) |
| ps_global_info->remain_in_power_active_till_dhcp = false; |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| return status; |
| |
| roam_id = GET_NEXT_ROAM_ID(&mac_ctx->roam); |
| if (ptr_roam_id) |
| *ptr_roam_id = roam_id; |
| |
| sme_debug("keyLength: %d", set_key->keyLength); |
| |
| sme_debug("Session_id: %d roam_id: %d", session_id, roam_id); |
| session = CSR_GET_SESSION(mac_ctx, session_id); |
| if (!session) { |
| sme_err("session %d not found", session_id); |
| sme_release_global_lock(&mac_ctx->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| if (CSR_IS_INFRA_AP(&session->connectedProfile) |
| && set_key->keyDirection == eSIR_TX_DEFAULT) { |
| if ((eCSR_ENCRYPT_TYPE_WEP40 == set_key->encType) |
| || (eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == |
| set_key->encType)) { |
| session->pCurRoamProfile->negotiatedUCEncryptionType = |
| eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; |
| } |
| if ((eCSR_ENCRYPT_TYPE_WEP104 == set_key->encType) |
| || (eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == |
| set_key->encType)) { |
| session->pCurRoamProfile->negotiatedUCEncryptionType = |
| eCSR_ENCRYPT_TYPE_WEP104_STATICKEY; |
| } |
| } |
| status = csr_roam_set_key(mac_ctx, session_id, set_key, roam_id); |
| sme_release_global_lock(&mac_ctx->sme); |
| return status; |
| } |
| |
| /** |
| * sme_roam_set_default_key_index - To set default wep key idx |
| * @hal: pointer to hal handler |
| * @session_id: session id |
| * @default_idx: default wep key index |
| * |
| * This function prepares a message and post to WMA to set wep default |
| * key index |
| * |
| * Return: Success:QDF_STATUS_SUCCESS Failure: Error value |
| */ |
| QDF_STATUS sme_roam_set_default_key_index(mac_handle_t hal, uint8_t session_id, |
| uint8_t default_idx) |
| { |
| struct scheduler_msg msg = {0}; |
| struct wep_update_default_key_idx *update_key; |
| |
| update_key = qdf_mem_malloc(sizeof(*update_key)); |
| if (!update_key) |
| return QDF_STATUS_E_NOMEM; |
| |
| update_key->session_id = session_id; |
| update_key->default_idx = default_idx; |
| |
| msg.type = WMA_UPDATE_WEP_DEFAULT_KEY; |
| msg.reserved = 0; |
| msg.bodyptr = (void *)update_key; |
| |
| if (QDF_STATUS_SUCCESS != |
| scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg)) { |
| sme_err("Failed to post WMA_UPDATE_WEP_DEFAULT_KEY to WMA"); |
| qdf_mem_free(update_key); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| |
| /** |
| * sme_get_rssi() - API to retrieve current RSSI |
| * @mac_handle: HAL handle for device |
| * @callback: SME sends back the requested stats using the callback |
| * @staId: The station ID for which the RSSI is requested for |
| * @bssid: The bssid of the connected session |
| * @lastRSSI: RSSI value at time of request. In case fw cannot provide |
| * RSSI, do not hold up but return this value. |
| * @pContext: user context to be passed back along with the callback |
| * |
| * A wrapper function that client calls to register a callback to get RSSI |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_get_rssi(mac_handle_t mac_handle, |
| tCsrRssiCallback callback, uint8_t staId, |
| struct qdf_mac_addr bssId, int8_t lastRSSI, |
| void *pContext) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_GET_RSSI, NO_SESSION, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_get_rssi(pMac, callback, |
| staId, bssId, lastRSSI, |
| pContext); |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_get_snr() - |
| * A wrapper function that client calls to register a callback to get SNR |
| * |
| * callback - SME sends back the requested stats using the callback |
| * staId - The station ID for which the stats is requested for |
| * pContext - user context to be passed back along with the callback |
| * p_cds_context - cds context |
| * \return QDF_STATUS |
| */ |
| QDF_STATUS sme_get_snr(mac_handle_t mac_handle, |
| tCsrSnrCallback callback, |
| uint8_t staId, struct qdf_mac_addr bssId, void *pContext) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_get_snr(pMac, callback, staId, bssId, pContext); |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| #ifndef QCA_SUPPORT_CP_STATS |
| /* |
| * sme_get_statistics() - |
| * A wrapper function that client calls to register a callback to get |
| * different PHY level statistics from CSR. |
| * |
| * requesterId - different client requesting for statistics, |
| * HDD, UMA/GAN etc |
| * statsMask - The different category/categories of stats requester |
| * is looking for |
| * callback - SME sends back the requested stats using the callback |
| * periodicity - If requester needs periodic update in millisec, 0 means |
| * it's an one time request |
| * cache - If requester is happy with cached stats |
| * staId - The station ID for which the stats is requested for |
| * pContext - user context to be passed back along with the callback |
| * sessionId - sme session interface |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_get_statistics(mac_handle_t mac_handle, |
| eCsrStatsRequesterType requesterId, |
| uint32_t statsMask, tCsrStatsCallback callback, |
| uint8_t staId, void *pContext, uint8_t sessionId) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_get_statistics(pMac, requesterId, statsMask, |
| callback, staId, pContext, |
| sessionId); |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| |
| } |
| #endif |
| |
| QDF_STATUS sme_get_link_status(mac_handle_t mac_handle, |
| csr_link_status_callback callback, |
| void *context, uint8_t session_id) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| tAniGetLinkStatus *msg; |
| struct scheduler_msg message = {0}; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| msg = qdf_mem_malloc(sizeof(*msg)); |
| if (!msg) { |
| sme_release_global_lock(&mac->sme); |
| return QDF_STATUS_E_NOMEM; |
| } |
| |
| msg->msgType = WMA_LINK_STATUS_GET_REQ; |
| msg->msgLen = sizeof(*msg); |
| msg->sessionId = session_id; |
| mac->sme.link_status_context = context; |
| mac->sme.link_status_callback = callback; |
| |
| message.type = WMA_LINK_STATUS_GET_REQ; |
| message.bodyptr = msg; |
| message.reserved = 0; |
| |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| if (QDF_IS_STATUS_ERROR(status)) { |
| sme_err("post msg failed, %d", status); |
| qdf_mem_free(msg); |
| mac->sme.link_status_context = NULL; |
| mac->sme.link_status_callback = NULL; |
| } |
| |
| sme_release_global_lock(&mac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_get_country_code() - |
| * To return the current country code. If no country code is applied, |
| * default country code is used to fill the buffer. |
| * If 11d supported is turned off, an error is return and the last |
| * applied/default country code is used. |
| * This is a synchronous API. |
| * |
| * pBuf - pointer to a caller allocated buffer for returned country code. |
| * pbLen For input, this parameter indicates how big is the buffer. |
| * Upon return, this parameter has the number of bytes for |
| * country. If pBuf doesn't have enough space, this function |
| * returns fail status and this parameter contains the number |
| * that is needed. |
| * |
| * Return QDF_STATUS SUCCESS. |
| * |
| * FAILURE or RESOURCES The API finished and failed. |
| */ |
| QDF_STATUS sme_get_country_code(mac_handle_t mac_handle, uint8_t *pBuf, |
| uint8_t *pbLen) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_GET_CNTRYCODE, NO_SESSION, 0)); |
| |
| return csr_get_country_code(pMac, pBuf, pbLen); |
| } |
| |
| /* some support functions */ |
| bool sme_is11d_supported(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return wlan_reg_11d_enabled_on_host(pMac->psoc); |
| } |
| |
| bool sme_is11h_supported(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return csr_is11h_supported(pMac); |
| } |
| |
| bool sme_is_wmm_supported(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return csr_is_wmm_supported(pMac); |
| } |
| |
| /* |
| * sme_generic_change_country_code() - |
| * Change Country code from upperlayer during WLAN driver operation. |
| * This is a synchronous API. |
| * |
| * mac_handle - The handle returned by mac_open. |
| * pCountry New Country Code String |
| * reg_domain regulatory domain |
| * Return QDF_STATUS SUCCESS. |
| * FAILURE or RESOURCES The API finished and failed. |
| */ |
| QDF_STATUS sme_generic_change_country_code(mac_handle_t mac_handle, |
| uint8_t *pCountry) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg msg = {0}; |
| tAniGenericChangeCountryCodeReq *pMsg; |
| |
| if (NULL == pMac) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL, |
| "%s: pMac is null", __func__); |
| return status; |
| } |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| pMsg = qdf_mem_malloc(sizeof(tAniGenericChangeCountryCodeReq)); |
| if (!pMsg) { |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_NOMEM; |
| } |
| |
| pMsg->msgType = eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE; |
| pMsg->msgLen = |
| (uint16_t) sizeof(tAniGenericChangeCountryCodeReq); |
| qdf_mem_copy(pMsg->countryCode, pCountry, 2); |
| pMsg->countryCode[2] = ' '; |
| |
| msg.type = eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE; |
| msg.bodyptr = pMsg; |
| msg.reserved = 0; |
| |
| if (QDF_STATUS_SUCCESS != |
| scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_SME, &msg)) { |
| sme_err("sme_generic_change_country_code failed to post msg to self"); |
| qdf_mem_free(pMsg); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_dhcp_start_ind() - |
| * API to signal the FW about the DHCP Start event. |
| * |
| * mac_handle - HAL handle for device. |
| * device_mode - mode(AP,SAP etc) of the device. |
| * macAddr - MAC address of the adapter. |
| * sessionId - session ID. |
| * Return QDF_STATUS SUCCESS. |
| * FAILURE or RESOURCES The API finished and failed. |
| */ |
| QDF_STATUS sme_dhcp_start_ind(mac_handle_t mac_handle, |
| uint8_t device_mode, |
| uint8_t *macAddr, uint8_t sessionId) |
| { |
| QDF_STATUS status; |
| QDF_STATUS qdf_status; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| tAniDHCPInd *pMsg; |
| struct csr_roam_session *pSession; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| pSession = CSR_GET_SESSION(pMac, sessionId); |
| |
| if (!pSession) { |
| sme_err("Session: %d not found", sessionId); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| pSession->dhcp_done = false; |
| |
| pMsg = qdf_mem_malloc(sizeof(tAniDHCPInd)); |
| if (!pMsg) { |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_NOMEM; |
| } |
| pMsg->msgType = WMA_DHCP_START_IND; |
| pMsg->msgLen = (uint16_t) sizeof(tAniDHCPInd); |
| pMsg->device_mode = device_mode; |
| qdf_mem_copy(pMsg->adapterMacAddr.bytes, macAddr, |
| QDF_MAC_ADDR_SIZE); |
| qdf_copy_macaddr(&pMsg->peerMacAddr, |
| &pSession->connectedProfile.bssid); |
| |
| message.type = WMA_DHCP_START_IND; |
| message.bodyptr = pMsg; |
| message.reserved = 0; |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| sessionId, message.type)); |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Post DHCP Start MSG fail", __func__); |
| qdf_mem_free(pMsg); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_dhcp_stop_ind() - |
| * API to signal the FW about the DHCP complete event. |
| * |
| * mac_handle - HAL handle for device. |
| * device_mode - mode(AP, SAP etc) of the device. |
| * macAddr - MAC address of the adapter. |
| * sessionId - session ID. |
| * Return QDF_STATUS SUCCESS. |
| * FAILURE or RESOURCES The API finished and failed. |
| */ |
| QDF_STATUS sme_dhcp_stop_ind(mac_handle_t mac_handle, |
| uint8_t device_mode, |
| uint8_t *macAddr, uint8_t sessionId) |
| { |
| QDF_STATUS status; |
| QDF_STATUS qdf_status; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| tAniDHCPInd *pMsg; |
| struct csr_roam_session *pSession; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| pSession = CSR_GET_SESSION(pMac, sessionId); |
| |
| if (!pSession) { |
| sme_err("Session: %d not found", sessionId); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| pSession->dhcp_done = true; |
| |
| pMsg = qdf_mem_malloc(sizeof(tAniDHCPInd)); |
| if (!pMsg) { |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_NOMEM; |
| } |
| |
| pMsg->msgType = WMA_DHCP_STOP_IND; |
| pMsg->msgLen = (uint16_t) sizeof(tAniDHCPInd); |
| pMsg->device_mode = device_mode; |
| qdf_mem_copy(pMsg->adapterMacAddr.bytes, macAddr, |
| QDF_MAC_ADDR_SIZE); |
| qdf_copy_macaddr(&pMsg->peerMacAddr, |
| &pSession->connectedProfile.bssid); |
| |
| message.type = WMA_DHCP_STOP_IND; |
| message.bodyptr = pMsg; |
| message.reserved = 0; |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| sessionId, message.type)); |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Post DHCP Stop MSG fail", __func__); |
| qdf_mem_free(pMsg); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_TXFailMonitorStopInd() - |
| * API to signal the FW to start monitoring TX failures |
| * |
| * Return QDF_STATUS SUCCESS. |
| * FAILURE or RESOURCES The API finished and failed. |
| */ |
| QDF_STATUS sme_tx_fail_monitor_start_stop_ind(mac_handle_t mac_handle, |
| uint8_t tx_fail_count, |
| void *txFailIndCallback) |
| { |
| QDF_STATUS status; |
| QDF_STATUS qdf_status; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| tAniTXFailMonitorInd *pMsg; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| pMsg = qdf_mem_malloc(sizeof(tAniTXFailMonitorInd)); |
| if (!pMsg) { |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_NOMEM; |
| } |
| |
| pMsg->msgType = WMA_TX_FAIL_MONITOR_IND; |
| pMsg->msgLen = (uint16_t) sizeof(tAniTXFailMonitorInd); |
| |
| /* tx_fail_count = 0 should disable the Monitoring in FW */ |
| pMsg->tx_fail_count = tx_fail_count; |
| pMsg->txFailIndCallback = txFailIndCallback; |
| |
| message.type = WMA_TX_FAIL_MONITOR_IND; |
| message.bodyptr = pMsg; |
| message.reserved = 0; |
| |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Post TX Fail monitor Start MSG fail", |
| __func__); |
| qdf_mem_free(pMsg); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_neighbor_report_request() - |
| * API to request neighbor report. |
| * |
| * mac_handle - The handle returned by mac_open. |
| * pRrmNeighborReq - Pointer to a caller allocated object of type |
| * tRrmNeighborReq. Caller owns the memory and is |
| * responsible for freeing it. |
| * Return QDF_STATUS |
| * QDF_STATUS_E_FAILURE - failure |
| * QDF_STATUS_SUCCESS success |
| */ |
| QDF_STATUS sme_neighbor_report_request( |
| mac_handle_t mac_handle, |
| uint8_t sessionId, |
| tpRrmNeighborReq pRrmNeighborReq, |
| tpRrmNeighborRspCallbackInfo callbackInfo) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_NEIGHBOR_REPORTREQ, NO_SESSION, |
| 0)); |
| |
| if (pRrmNeighborReq->neighbor_report_offload) { |
| status = csr_invoke_neighbor_report_request(sessionId, |
| pRrmNeighborReq, |
| false); |
| return status; |
| } |
| |
| if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { |
| status = |
| sme_rrm_neighbor_report_request(pMac, sessionId, |
| pRrmNeighborReq, callbackInfo); |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_get_wcnss_wlan_compiled_version() - |
| * This API returns the version of the WCNSS WLAN API with |
| * which the HOST driver was built |
| * |
| * mac_handle - The handle returned by mac_open. |
| * pVersion - Points to the Version structure to be filled |
| * Return QDF_STATUS |
| * QDF_STATUS_E_INVAL - failure |
| * QDF_STATUS_SUCCESS success |
| */ |
| QDF_STATUS sme_get_wcnss_wlan_compiled_version(mac_handle_t mac_handle, |
| tSirVersionType *pVersion) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { |
| if (pVersion != NULL) |
| status = QDF_STATUS_SUCCESS; |
| else |
| status = QDF_STATUS_E_INVAL; |
| |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_get_wcnss_wlan_reported_version() - |
| * This API returns the version of the WCNSS WLAN API with |
| * which the WCNSS driver reports it was built |
| * mac_handle - The handle returned by mac_open. |
| * pVersion - Points to the Version structure to be filled |
| * Return QDF_STATUS |
| * QDF_STATUS_E_INVAL - failure |
| * QDF_STATUS_SUCCESS success |
| */ |
| QDF_STATUS sme_get_wcnss_wlan_reported_version(mac_handle_t mac_handle, |
| tSirVersionType *pVersion) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { |
| if (pVersion != NULL) |
| status = QDF_STATUS_SUCCESS; |
| else |
| status = QDF_STATUS_E_INVAL; |
| |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_get_wcnss_software_version() - |
| * This API returns the version string of the WCNSS driver |
| * |
| * mac_handle - The handle returned by mac_open. |
| * pVersion - Points to the Version string buffer to be filled |
| * versionBufferSize - THe size of the Version string buffer |
| * Return QDF_STATUS |
| * QDF_STATUS_E_INVAL - failure |
| * QDF_STATUS_SUCCESS success |
| */ |
| QDF_STATUS sme_get_wcnss_software_version(mac_handle_t mac_handle, |
| uint8_t *pVersion, |
| uint32_t versionBufferSize) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { |
| if (pVersion != NULL) |
| status = |
| wma_get_wcnss_software_version( |
| pVersion, |
| versionBufferSize); |
| else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_get_wcnss_hardware_version() - |
| * This API returns the version string of the WCNSS hardware |
| * |
| * mac_handle - The handle returned by mac_open. |
| * pVersion - Points to the Version string buffer to be filled |
| * versionBufferSize - THe size of the Version string buffer |
| * Return QDF_STATUS |
| * QDF_STATUS_E_INVAL - failure |
| * QDF_STATUS_SUCCESS success |
| */ |
| QDF_STATUS sme_get_wcnss_hardware_version(mac_handle_t mac_handle, |
| uint8_t *pVersion, |
| uint32_t versionBufferSize) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { |
| if (pVersion != NULL) |
| status = QDF_STATUS_SUCCESS; |
| else |
| status = QDF_STATUS_E_INVAL; |
| |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| #ifdef FEATURE_OEM_DATA_SUPPORT |
| /** |
| * sme_oem_data_req() - send oem data request to WMA |
| * @hal: HAL handle |
| * @hdd_oem_req: OEM data request from HDD |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_oem_data_req(mac_handle_t hal, struct oem_data_req *hdd_oem_req) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| struct oem_data_req *oem_data_req; |
| void *wma_handle; |
| |
| SME_ENTER(); |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| sme_err("wma_handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| oem_data_req = qdf_mem_malloc(sizeof(*oem_data_req)); |
| if (!oem_data_req) |
| return QDF_STATUS_E_NOMEM; |
| |
| oem_data_req->data_len = hdd_oem_req->data_len; |
| oem_data_req->data = qdf_mem_malloc(oem_data_req->data_len); |
| if (!oem_data_req->data) |
| return QDF_STATUS_E_NOMEM; |
| |
| qdf_mem_copy(oem_data_req->data, hdd_oem_req->data, |
| oem_data_req->data_len); |
| |
| status = wma_start_oem_data_req(wma_handle, oem_data_req); |
| |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| sme_err("Post oem data request msg fail"); |
| else |
| sme_debug("OEM request(length: %d) sent to WMA", |
| oem_data_req->data_len); |
| |
| if (oem_data_req->data_len) |
| qdf_mem_free(oem_data_req->data); |
| qdf_mem_free(oem_data_req); |
| |
| SME_EXIT(); |
| return status; |
| } |
| #endif /*FEATURE_OEM_DATA_SUPPORT */ |
| |
| QDF_STATUS sme_open_session(mac_handle_t hal, struct sme_session_params *params) |
| { |
| QDF_STATUS status = QDF_STATUS_E_INVAL; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct cdp_pdev *pdev; |
| ol_txrx_peer_handle peer; |
| uint8_t peer_id; |
| void *soc = cds_get_context(QDF_MODULE_ID_SOC); |
| |
| QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_DEBUG, |
| "%s: type=%d, session_id %d subType=%d addr:%pM", |
| __func__, params->type_of_persona, |
| params->sme_session_id, params->subtype_of_persona, |
| params->self_mac_addr); |
| |
| pdev = cds_get_context(QDF_MODULE_ID_TXRX); |
| |
| if (NULL == pdev) { |
| QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, |
| "%s: Failed to get pdev handler", __func__); |
| return status; |
| } |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_ERROR(status)) |
| return status; |
| |
| peer = cdp_peer_find_by_addr(soc, pdev, params->self_mac_addr, |
| &peer_id); |
| if (peer) { |
| QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, |
| "%s: Peer=%d exist with same MAC", |
| __func__, peer_id); |
| status = QDF_STATUS_E_INVAL; |
| } else { |
| status = csr_roam_open_session(mac_ctx, params); |
| } |
| sme_release_global_lock(&mac_ctx->sme); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_RX_HDD_OPEN_SESSION, |
| params->sme_session_id, 0)); |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_close_session(mac_handle_t hal, uint8_t session_id) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal pMac = PMAC_STRUCT(hal); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_CLOSE_SESSION, session_id, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_roam_close_session(pMac, session_id, false); |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_change_mcc_beacon_interval() - |
| * To update P2P-GO beaconInterval. This function should be called after |
| * disassociating all the station is done |
| * This is an asynchronous API. |
| * |
| * @sessionId: Session Identifier |
| * Return QDF_STATUS SUCCESS |
| * FAILURE or RESOURCES |
| * The API finished and failed. |
| */ |
| QDF_STATUS sme_change_mcc_beacon_interval(uint8_t sessionId) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal mac_ctx = sme_get_mac_context(); |
| |
| if (!mac_ctx) { |
| sme_err("mac_ctx is NULL"); |
| return status; |
| } |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_send_chng_mcc_beacon_interval(mac_ctx, |
| sessionId); |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| return status; |
| } |
| |
| /** |
| * sme_set_host_offload(): API to set the host offload feature. |
| * @mac_handle: The handle returned by mac_open. |
| * @sessionId: Session Identifier |
| * @request: Pointer to the offload request. |
| * |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_set_host_offload(mac_handle_t mac_handle, uint8_t sessionId, |
| tpSirHostOffloadReq request) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_SET_HOSTOFFLOAD, sessionId, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| #ifdef WLAN_NS_OFFLOAD |
| if (SIR_IPV6_NS_OFFLOAD == request->offloadType) { |
| status = sme_set_ps_ns_offload(mac_handle, request, |
| sessionId); |
| } else |
| #endif /* WLAN_NS_OFFLOAD */ |
| { |
| status = sme_set_ps_host_offload(mac_handle, request, |
| sessionId); |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_set_keep_alive() - |
| * API to set the Keep Alive feature. |
| * |
| * mac_handle - The handle returned by mac_open. |
| * request - Pointer to the Keep Alive request. |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_set_keep_alive(mac_handle_t mac_handle, uint8_t session_id, |
| tpSirKeepAliveReq request) |
| { |
| tpSirKeepAliveReq request_buf; |
| struct scheduler_msg msg = {0}; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct csr_roam_session *pSession = CSR_GET_SESSION(pMac, session_id); |
| |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| FL("WMA_SET_KEEP_ALIVE message")); |
| |
| if (pSession == NULL) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Session not Found")); |
| return QDF_STATUS_E_FAILURE; |
| } |
| request_buf = qdf_mem_malloc(sizeof(tSirKeepAliveReq)); |
| if (!request_buf) |
| return QDF_STATUS_E_NOMEM; |
| |
| qdf_copy_macaddr(&request->bssid, &pSession->connectedProfile.bssid); |
| qdf_mem_copy(request_buf, request, sizeof(tSirKeepAliveReq)); |
| |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "buff TP %d input TP %d ", request_buf->timePeriod, |
| request->timePeriod); |
| request_buf->sessionId = session_id; |
| |
| msg.type = WMA_SET_KEEP_ALIVE; |
| msg.reserved = 0; |
| msg.bodyptr = request_buf; |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| session_id, msg.type)); |
| if (QDF_STATUS_SUCCESS != |
| scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "Not able to post WMA_SET_KEEP_ALIVE message to WMA"); |
| qdf_mem_free(request_buf); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /* |
| * sme_get_operation_channel() - |
| * API to get current channel on which STA is parked his function gives |
| * channel information only of infra station or IBSS station |
| * |
| * mac_handle, pointer to memory location and sessionId |
| * Returns QDF_STATUS_SUCCESS |
| * QDF_STATUS_E_FAILURE |
| */ |
| QDF_STATUS sme_get_operation_channel(mac_handle_t mac_handle, |
| uint32_t *pChannel, |
| uint8_t sessionId) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct csr_roam_session *pSession; |
| |
| if (CSR_IS_SESSION_VALID(pMac, sessionId)) { |
| pSession = CSR_GET_SESSION(pMac, sessionId); |
| |
| if ((pSession->connectedProfile.BSSType == |
| eCSR_BSS_TYPE_INFRASTRUCTURE) |
| || (pSession->connectedProfile.BSSType == |
| eCSR_BSS_TYPE_IBSS) |
| || (pSession->connectedProfile.BSSType == |
| eCSR_BSS_TYPE_INFRA_AP) |
| || (pSession->connectedProfile.BSSType == |
| eCSR_BSS_TYPE_START_IBSS)) { |
| *pChannel = pSession->connectedProfile.operationChannel; |
| return QDF_STATUS_SUCCESS; |
| } |
| } |
| return QDF_STATUS_E_FAILURE; |
| } /* sme_get_operation_channel ends here */ |
| |
| /** |
| * sme_register_mgmt_frame_ind_callback() - Register a callback for |
| * management frame indication to PE. |
| * |
| * @hal: hal pointer |
| * @callback: callback pointer to be registered |
| * |
| * This function is used to register a callback for management |
| * frame indication to PE. |
| * |
| * Return: Success if msg is posted to PE else Failure. |
| */ |
| QDF_STATUS sme_register_mgmt_frame_ind_callback(mac_handle_t hal, |
| sir_mgmt_frame_ind_callback callback) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct sir_sme_mgmt_frame_cb_req *msg; |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| if (QDF_STATUS_SUCCESS == |
| sme_acquire_global_lock(&mac_ctx->sme)) { |
| msg = qdf_mem_malloc(sizeof(*msg)); |
| if (!msg) { |
| sme_release_global_lock(&mac_ctx->sme); |
| return QDF_STATUS_E_NOMEM; |
| } |
| msg->message_type = eWNI_SME_REGISTER_MGMT_FRAME_CB; |
| msg->length = sizeof(*msg); |
| |
| msg->callback = callback; |
| status = umac_send_mb_message_to_mac(msg); |
| sme_release_global_lock(&mac_ctx->sme); |
| return status; |
| } |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| /* |
| * sme_RegisterMgtFrame() - |
| * To register management frame of specified type and subtype. |
| * |
| * frameType - type of the frame that needs to be passed to HDD. |
| * matchData - data which needs to be matched before passing frame |
| * to HDD. |
| * matchDataLen - Length of matched data. |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_register_mgmt_frame(mac_handle_t mac_handle, uint8_t sessionId, |
| uint16_t frameType, uint8_t *matchData, |
| uint16_t matchLen) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| tSirRegisterMgmtFrame *pMsg; |
| uint16_t len; |
| struct csr_roam_session *pSession = CSR_GET_SESSION(pMac, |
| sessionId); |
| |
| if (!CSR_IS_SESSION_ANY(sessionId) && !pSession) { |
| sme_err("Session %d not found", sessionId); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| if (!CSR_IS_SESSION_ANY(sessionId) && |
| !pSession->sessionActive) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s Invalid Sessionid", __func__); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| len = sizeof(tSirRegisterMgmtFrame) + matchLen; |
| |
| pMsg = qdf_mem_malloc(len); |
| if (NULL == pMsg) |
| status = QDF_STATUS_E_NOMEM; |
| else { |
| pMsg->messageType = eWNI_SME_REGISTER_MGMT_FRAME_REQ; |
| pMsg->length = len; |
| pMsg->sessionId = sessionId; |
| pMsg->registerFrame = true; |
| pMsg->frameType = frameType; |
| pMsg->matchLen = matchLen; |
| qdf_mem_copy(pMsg->matchData, matchData, matchLen); |
| status = umac_send_mb_message_to_mac(pMsg); |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_DeregisterMgtFrame() - |
| * To De-register management frame of specified type and subtype. |
| * |
| * frameType - type of the frame that needs to be passed to HDD. |
| * matchData - data which needs to be matched before passing frame |
| * to HDD. |
| * matchDataLen - Length of matched data. |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_deregister_mgmt_frame(mac_handle_t mac_handle, uint8_t sessionId, |
| uint16_t frameType, uint8_t *matchData, |
| uint16_t matchLen) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_DEREGISTER_MGMTFR, sessionId, |
| 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| tSirRegisterMgmtFrame *pMsg; |
| uint16_t len; |
| struct csr_roam_session *pSession = CSR_GET_SESSION(pMac, |
| sessionId); |
| |
| if (!CSR_IS_SESSION_ANY(sessionId) && !pSession) { |
| sme_err("Session %d not found", sessionId); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| if (!CSR_IS_SESSION_ANY(sessionId) && |
| !pSession->sessionActive) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s Invalid Sessionid", __func__); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| len = sizeof(tSirRegisterMgmtFrame) + matchLen; |
| |
| pMsg = qdf_mem_malloc(len); |
| if (NULL == pMsg) |
| status = QDF_STATUS_E_NOMEM; |
| else { |
| pMsg->messageType = eWNI_SME_REGISTER_MGMT_FRAME_REQ; |
| pMsg->length = len; |
| pMsg->registerFrame = false; |
| pMsg->frameType = frameType; |
| pMsg->matchLen = matchLen; |
| qdf_mem_copy(pMsg->matchData, matchData, matchLen); |
| status = umac_send_mb_message_to_mac(pMsg); |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /** |
| * sme_prepare_mgmt_tx() - Prepares mgmt frame |
| * @hal: The handle returned by mac_open |
| * @session_id: session id |
| * @buf: pointer to frame |
| * @len: frame length |
| * |
| * Return: QDF_STATUS |
| */ |
| static QDF_STATUS sme_prepare_mgmt_tx(mac_handle_t hal, uint8_t session_id, |
| const uint8_t *buf, uint32_t len) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| struct sir_mgmt_msg *msg; |
| uint16_t msg_len; |
| struct scheduler_msg sch_msg = {0}; |
| |
| sme_debug("prepares auth frame"); |
| |
| msg_len = sizeof(*msg) + len; |
| msg = qdf_mem_malloc(msg_len); |
| if (msg == NULL) { |
| status = QDF_STATUS_E_NOMEM; |
| } else { |
| msg->type = eWNI_SME_SEND_MGMT_FRAME_TX; |
| msg->msg_len = msg_len; |
| msg->session_id = session_id; |
| msg->data = (uint8_t *)msg + sizeof(*msg); |
| qdf_mem_copy(msg->data, buf, len); |
| |
| sch_msg.type = eWNI_SME_SEND_MGMT_FRAME_TX; |
| sch_msg.bodyptr = msg; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_PE, |
| QDF_MODULE_ID_PE, &sch_msg); |
| } |
| return status; |
| } |
| |
| QDF_STATUS sme_send_mgmt_tx(mac_handle_t hal, uint8_t session_id, |
| const uint8_t *buf, uint32_t len) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = sme_prepare_mgmt_tx(hal, session_id, buf, len); |
| sme_release_global_lock(&mac->sme); |
| } |
| |
| return status; |
| } |
| |
| #ifdef WLAN_FEATURE_EXTWOW_SUPPORT |
| /** |
| * sme_configure_ext_wow() - configure Extr WoW |
| * @mac_handle - The handle returned by mac_open. |
| * @wlanExtParams - Depicts the wlan Ext params. |
| * @callback - ext_wow callback to be registered. |
| * @callback_context - ext_wow callback context |
| * |
| * SME will pass this request to lower mac to configure Extr WoW |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_configure_ext_wow(mac_handle_t mac_handle, |
| tpSirExtWoWParams wlanExtParams, |
| csr_readyToExtWoWCallback callback, |
| void *callback_context) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| tpSirExtWoWParams MsgPtr = qdf_mem_malloc(sizeof(*MsgPtr)); |
| |
| if (!MsgPtr) |
| return QDF_STATUS_E_NOMEM; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_CONFIG_EXTWOW, NO_SESSION, 0)); |
| |
| pMac->readyToExtWoWCallback = callback; |
| pMac->readyToExtWoWContext = callback_context; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| |
| /* serialize the req through MC thread */ |
| qdf_mem_copy(MsgPtr, wlanExtParams, sizeof(*MsgPtr)); |
| message.bodyptr = MsgPtr; |
| message.type = WMA_WLAN_EXT_WOW; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| pMac->readyToExtWoWCallback = NULL; |
| pMac->readyToExtWoWContext = NULL; |
| qdf_mem_free(MsgPtr); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } else { |
| pMac->readyToExtWoWCallback = NULL; |
| pMac->readyToExtWoWContext = NULL; |
| qdf_mem_free(MsgPtr); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_configure_app_type1_params() - |
| * SME will pass this request to lower mac to configure Indoor WoW parameters. |
| * |
| * mac_handle - The handle returned by mac_open. |
| * wlanAppType1Params- Depicts the wlan App Type 1(Indoor) params |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_configure_app_type1_params(mac_handle_t mac_handle, |
| tpSirAppType1Params wlanAppType1Params) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| tpSirAppType1Params MsgPtr = qdf_mem_malloc(sizeof(*MsgPtr)); |
| |
| if (!MsgPtr) |
| return QDF_STATUS_E_NOMEM; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_CONFIG_APP_TYPE1, NO_SESSION, |
| 0)); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| /* serialize the req through MC thread */ |
| qdf_mem_copy(MsgPtr, wlanAppType1Params, sizeof(*MsgPtr)); |
| message.bodyptr = MsgPtr; |
| message.type = WMA_WLAN_SET_APP_TYPE1_PARAMS; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| qdf_mem_free(MsgPtr); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } else { |
| qdf_mem_free(MsgPtr); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_configure_app_type2_params() - |
| * SME will pass this request to lower mac to configure Indoor WoW parameters. |
| * |
| * mac_handle - The handle returned by mac_open. |
| * wlanAppType2Params- Depicts the wlan App Type 2 (Outdoor) params |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_configure_app_type2_params(mac_handle_t mac_handle, |
| tpSirAppType2Params wlanAppType2Params) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| tpSirAppType2Params MsgPtr = qdf_mem_malloc(sizeof(*MsgPtr)); |
| |
| if (!MsgPtr) |
| return QDF_STATUS_E_NOMEM; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_CONFIG_APP_TYPE2, NO_SESSION, |
| 0)); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| /* serialize the req through MC thread */ |
| qdf_mem_copy(MsgPtr, wlanAppType2Params, sizeof(*MsgPtr)); |
| message.bodyptr = MsgPtr; |
| message.type = WMA_WLAN_SET_APP_TYPE2_PARAMS; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| qdf_mem_free(MsgPtr); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } else { |
| qdf_mem_free(MsgPtr); |
| } |
| |
| return status; |
| } |
| #endif |
| |
| /* |
| * sme_get_infra_session_id |
| * To get the session ID for infra session, if connected |
| * This is a synchronous API. |
| * |
| * mac_handle - The handle returned by mac_open. |
| * sessionid, -1 if infra session is not connected |
| */ |
| int8_t sme_get_infra_session_id(mac_handle_t mac_handle) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| int8_t sessionid = -1; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| |
| sessionid = csr_get_infra_session_id(pMac); |
| |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return sessionid; |
| } |
| |
| /* |
| * sme_get_infra_operation_channel() - |
| * To get the operating channel for infra session, if connected |
| * This is a synchronous API. |
| * |
| * mac_handle - The handle returned by mac_open. |
| * sessionId - the sessionId returned by sme_open_session. |
| * Return operating channel, 0 if infra session is not connected |
| */ |
| uint8_t sme_get_infra_operation_channel(mac_handle_t mac_handle, |
| uint8_t sessionId) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| uint8_t channel = 0; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| |
| channel = csr_get_infra_operation_channel(pMac, sessionId); |
| |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return channel; |
| } |
| |
| /* This routine will return poerating channel on which other BSS is operating |
| * to be used for concurrency mode. If other BSS is not up or not connected it |
| * will return 0 |
| */ |
| uint8_t sme_get_concurrent_operation_channel(mac_handle_t mac_handle) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| uint8_t channel = 0; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| |
| channel = csr_get_concurrent_operation_channel(pMac); |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO, |
| "%s: Other Concurrent Channel: %d", __func__, channel); |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return channel; |
| } |
| |
| #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH |
| uint16_t sme_check_concurrent_channel_overlap(mac_handle_t mac_handle, |
| uint16_t sap_ch, |
| eCsrPhyMode sapPhyMode, |
| uint8_t cc_switch_mode) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| uint16_t channel = 0; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| channel = |
| csr_check_concurrent_channel_overlap(pMac, sap_ch, |
| sapPhyMode, |
| cc_switch_mode); |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return channel; |
| } |
| #endif |
| |
| /** |
| * sme_set_tsfcb() - Set callback for TSF capture |
| * @mac_handle: Handler return by mac_open |
| * @cb_fn: Callback function pointer |
| * @db_ctx: Callback data |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_set_tsfcb(mac_handle_t mac_handle, |
| int (*cb_fn)(void *cb_ctx, struct stsf *ptsf), void *cb_ctx) |
| { |
| tpAniSirGlobal mac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| mac->sme.get_tsf_cb = cb_fn; |
| mac->sme.get_tsf_cxt = cb_ctx; |
| sme_release_global_lock(&mac->sme); |
| } |
| return status; |
| } |
| |
| /** |
| * sme_reset_tsfcb() - Reset callback for TSF capture |
| * @mac_handle: Handler return by mac_open |
| * |
| * This function reset the tsf capture callback to SME |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_reset_tsfcb(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal mac; |
| QDF_STATUS status; |
| |
| if (!mac_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("mac_handle is not valid")); |
| return QDF_STATUS_E_INVAL; |
| } |
| mac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| mac->sme.get_tsf_cb = NULL; |
| mac->sme.get_tsf_cxt = NULL; |
| sme_release_global_lock(&mac->sme); |
| } |
| return status; |
| } |
| |
| #if defined(WLAN_FEATURE_TSF) && !defined(WLAN_FEATURE_TSF_PLUS_NOIRQ) |
| /* |
| * sme_set_tsf_gpio() - set gpio pin that be toggled when capture tsf |
| * @mac_handle: Handler return by mac_open |
| * @pinvalue: gpio pin id |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_set_tsf_gpio(mac_handle_t mac_handle, uint32_t pinvalue) |
| { |
| QDF_STATUS status; |
| struct scheduler_msg tsf_msg = {0}; |
| tpAniSirGlobal mac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| tsf_msg.type = WMA_TSF_GPIO_PIN; |
| tsf_msg.reserved = 0; |
| tsf_msg.bodyval = pinvalue; |
| |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &tsf_msg); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("Unable to post WMA_TSF_GPIO_PIN"); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&mac->sme); |
| } |
| return status; |
| } |
| #endif |
| |
| QDF_STATUS sme_get_cfg_valid_channels(uint8_t *aValidChannels, |
| uint32_t *len) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal mac_ctx = sme_get_mac_context(); |
| |
| if (NULL == mac_ctx) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid MAC context")); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_get_cfg_valid_channels(mac_ctx, |
| aValidChannels, len); |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| |
| return status; |
| } |
| |
| static uint8_t *sme_reg_hint_to_str(const enum country_src src) |
| { |
| switch (src) { |
| case SOURCE_CORE: |
| return "WORLD MODE"; |
| |
| case SOURCE_DRIVER: |
| return "BDF file"; |
| |
| case SOURCE_USERSPACE: |
| return "user-space"; |
| |
| case SOURCE_11D: |
| return "802.11D IEs in beacons"; |
| |
| default: |
| return "unknown"; |
| } |
| } |
| |
| void sme_set_cc_src(mac_handle_t mac_handle, enum country_src cc_src) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| |
| mac_ctx->reg_hint_src = cc_src; |
| |
| sme_debug("Country source is %s", |
| sme_reg_hint_to_str(cc_src)); |
| } |
| |
| /** |
| * sme_handle_generic_change_country_code() - handles country ch req |
| * @mac_ctx: mac global context |
| * @msg: request msg packet |
| * |
| * If Supplicant country code is priority than 11d is disabled. |
| * If 11D is enabled, we update the country code after every scan. |
| * Hence when Supplicant country code is priority, we don't need 11D info. |
| * Country code from Supplicant is set as current country code. |
| * |
| * Return: status of operation |
| */ |
| static QDF_STATUS |
| sme_handle_generic_change_country_code(tpAniSirGlobal mac_ctx, |
| void *pMsgBuf) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| v_REGDOMAIN_t reg_domain_id = 0; |
| bool user_ctry_priority = |
| mac_ctx->roam.configParam.fSupplicantCountryCodeHasPriority; |
| tAniGenericChangeCountryCodeReq *msg = pMsgBuf; |
| |
| if (SOURCE_11D != mac_ctx->reg_hint_src) { |
| if (SOURCE_DRIVER != mac_ctx->reg_hint_src) { |
| if (user_ctry_priority) |
| mac_ctx->roam.configParam.Is11dSupportEnabled = |
| false; |
| else { |
| if (mac_ctx->roam.configParam. |
| Is11dSupportEnabled && |
| mac_ctx->scan.countryCode11d[0] != 0) { |
| |
| sme_debug("restore 11d"); |
| |
| status = |
| csr_get_regulatory_domain_for_country( |
| mac_ctx, |
| mac_ctx->scan.countryCode11d, |
| ®_domain_id, |
| SOURCE_11D); |
| return QDF_STATUS_E_FAILURE; |
| } |
| } |
| } |
| } else { |
| /* if kernel gets invalid country code; it |
| * resets the country code to world |
| */ |
| if (('0' != msg->countryCode[0]) || |
| ('0' != msg->countryCode[1])) |
| qdf_mem_copy(mac_ctx->scan.countryCode11d, |
| msg->countryCode, |
| WNI_CFG_COUNTRY_CODE_LEN); |
| } |
| |
| qdf_mem_copy(mac_ctx->scan.countryCodeCurrent, |
| msg->countryCode, |
| WNI_CFG_COUNTRY_CODE_LEN); |
| |
| /* get the channels based on new cc */ |
| status = csr_get_channel_and_power_list(mac_ctx); |
| |
| if (status != QDF_STATUS_SUCCESS) { |
| sme_err("fail to get Channels"); |
| return status; |
| } |
| |
| /* reset info based on new cc, and we are done */ |
| csr_apply_channel_power_info_wrapper(mac_ctx); |
| |
| csr_scan_filter_results(mac_ctx); |
| |
| /* scans after the country is set by User hints or |
| * Country IE |
| */ |
| mac_ctx->scan.curScanType = eSIR_ACTIVE_SCAN; |
| |
| mac_ctx->reg_hint_src = SOURCE_UNKNOWN; |
| |
| sme_disconnect_connected_sessions(mac_ctx); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS sme_update_channel_list(mac_handle_t hal) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| QDF_STATUS status; |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| /* Update umac channel (enable/disable) from cds channels */ |
| status = csr_get_channel_and_power_list(mac_ctx); |
| if (status != QDF_STATUS_SUCCESS) { |
| sme_err("fail to get Channels"); |
| sme_release_global_lock(&mac_ctx->sme); |
| return status; |
| } |
| |
| csr_apply_channel_power_info_wrapper(mac_ctx); |
| csr_scan_filter_results(mac_ctx); |
| sme_disconnect_connected_sessions(mac_ctx); |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| |
| return status; |
| } |
| |
| static bool |
| sme_search_in_base_ch_lst(tpAniSirGlobal mac_ctx, uint8_t curr_ch) |
| { |
| uint8_t i; |
| struct csr_channel *ch_lst_info; |
| |
| ch_lst_info = &mac_ctx->scan.base_channels; |
| for (i = 0; i < ch_lst_info->numChannels; i++) { |
| if (ch_lst_info->channelList[i] == curr_ch) |
| return true; |
| } |
| |
| return false; |
| } |
| /** |
| * sme_disconnect_connected_sessions() - Disconnect STA and P2P client session |
| * if channel is not supported |
| * @mac_ctx: mac global context |
| * |
| * If new country code does not support the channel on which STA/P2P client |
| * is connetced, it sends the disconnect to the AP/P2P GO |
| * |
| * Return: void |
| */ |
| static void sme_disconnect_connected_sessions(tpAniSirGlobal mac_ctx) |
| { |
| uint8_t session_id, found = false; |
| uint8_t curr_ch; |
| |
| for (session_id = 0; session_id < CSR_ROAM_SESSION_MAX; session_id++) { |
| if (!csr_is_session_client_and_connected(mac_ctx, session_id)) |
| continue; |
| found = false; |
| /* Session is connected.Check the channel */ |
| curr_ch = csr_get_infra_operation_channel(mac_ctx, |
| session_id); |
| sme_debug("Current Operating channel : %d, session :%d", |
| curr_ch, session_id); |
| found = sme_search_in_base_ch_lst(mac_ctx, curr_ch); |
| if (!found) { |
| sme_debug("Disconnect Session: %d", session_id); |
| csr_roam_disconnect(mac_ctx, session_id, |
| eCSR_DISCONNECT_REASON_UNSPECIFIED); |
| } |
| } |
| } |
| |
| #ifdef WLAN_FEATURE_PACKET_FILTERING |
| QDF_STATUS sme_8023_multicast_list(mac_handle_t mac_handle, uint8_t sessionId, |
| tpSirRcvFltMcAddrList pMulticastAddrs) |
| { |
| tpSirRcvFltMcAddrList request_buf; |
| struct scheduler_msg msg = {0}; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct csr_roam_session *pSession = NULL; |
| |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: ulMulticastAddrCnt: %d, multicastAddr[0]: %pK", __func__, |
| pMulticastAddrs->ulMulticastAddrCnt, |
| pMulticastAddrs->multicastAddr[0].bytes); |
| |
| /* Find the connected Infra / P2P_client connected session */ |
| pSession = CSR_GET_SESSION(pMac, sessionId); |
| if (!CSR_IS_SESSION_VALID(pMac, sessionId) || |
| (!csr_is_conn_state_infra(pMac, sessionId) && |
| !csr_is_ndi_started(pMac, sessionId))) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Unable to find the session Id: %d", __func__, |
| sessionId); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| request_buf = qdf_mem_malloc(sizeof(tSirRcvFltMcAddrList)); |
| if (!request_buf) |
| return QDF_STATUS_E_NOMEM; |
| |
| if (!csr_is_conn_state_connected_infra(pMac, sessionId) && |
| !csr_is_ndi_started(pMac, sessionId)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Request ignored, session %d is not connected or started", |
| __func__, sessionId); |
| qdf_mem_free(request_buf); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| qdf_mem_copy(request_buf, pMulticastAddrs, |
| sizeof(tSirRcvFltMcAddrList)); |
| |
| qdf_copy_macaddr(&request_buf->self_macaddr, &pSession->selfMacAddr); |
| qdf_copy_macaddr(&request_buf->bssid, |
| &pSession->connectedProfile.bssid); |
| |
| msg.type = WMA_8023_MULTICAST_LIST_REQ; |
| msg.reserved = 0; |
| msg.bodyptr = request_buf; |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| sessionId, msg.type)); |
| if (QDF_STATUS_SUCCESS != scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &msg)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post WMA_8023_MULTICAST_LIST message to WMA", |
| __func__); |
| qdf_mem_free(request_buf); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| #endif /* WLAN_FEATURE_PACKET_FILTERING */ |
| |
| /* |
| * sme_is_channel_valid() - |
| * To check if the channel is valid for currently established domain |
| * This is a synchronous API. |
| * |
| * mac_handle - The handle returned by mac_open. |
| * channel - channel to verify |
| * Return true/false, true if channel is valid |
| */ |
| bool sme_is_channel_valid(mac_handle_t mac_handle, uint8_t channel) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| bool valid = false; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| |
| valid = csr_roam_is_channel_valid(pMac, channel); |
| |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return valid; |
| } |
| |
| /* |
| * sme_get_freq_band() - |
| * Used to get the current band settings. |
| * |
| * mac_handle |
| * pBand pointer to hold band value |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_get_freq_band(mac_handle_t mac_handle, enum band_info *pBand) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| *pBand = csr_get_current_band(pMac); |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_set_max_tx_power_per_band() - |
| * Set the Maximum Transmit Power specific to band dynamically. |
| * Note: this setting will not persist over reboots. |
| * |
| * band |
| * power to set in dB |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_set_max_tx_power_per_band(enum band_info band, int8_t dB) |
| { |
| struct scheduler_msg msg = {0}; |
| tpMaxTxPowerPerBandParams pMaxTxPowerPerBandParams = NULL; |
| |
| pMaxTxPowerPerBandParams = |
| qdf_mem_malloc(sizeof(tMaxTxPowerPerBandParams)); |
| if (!pMaxTxPowerPerBandParams) |
| return QDF_STATUS_E_NOMEM; |
| |
| pMaxTxPowerPerBandParams->power = dB; |
| pMaxTxPowerPerBandParams->bandInfo = band; |
| |
| msg.type = WMA_SET_MAX_TX_POWER_PER_BAND_REQ; |
| msg.reserved = 0; |
| msg.bodyptr = pMaxTxPowerPerBandParams; |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| NO_SESSION, msg.type)); |
| if (QDF_STATUS_SUCCESS != scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &msg)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s:Not able to post WMA_SET_MAX_TX_POWER_PER_BAND_REQ", |
| __func__); |
| qdf_mem_free(pMaxTxPowerPerBandParams); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /* |
| * sme_set_max_tx_power() - |
| * Set the Maximum Transmit Power dynamically. Note: this setting will |
| * not persist over reboots. |
| * |
| * mac_handle |
| * pBssid BSSID to set the power cap for |
| * pBssid pSelfMacAddress self MAC Address |
| * pBssid power to set in dB |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_set_max_tx_power(mac_handle_t mac_handle, |
| struct qdf_mac_addr pBssid, |
| struct qdf_mac_addr pSelfMacAddress, int8_t dB) |
| { |
| struct scheduler_msg msg = {0}; |
| tpMaxTxPowerParams pMaxTxParams = NULL; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_SET_MAXTXPOW, NO_SESSION, 0)); |
| pMaxTxParams = qdf_mem_malloc(sizeof(tMaxTxPowerParams)); |
| if (!pMaxTxParams) |
| return QDF_STATUS_E_NOMEM; |
| |
| qdf_copy_macaddr(&pMaxTxParams->bssId, &pBssid); |
| qdf_copy_macaddr(&pMaxTxParams->selfStaMacAddr, &pSelfMacAddress); |
| pMaxTxParams->power = dB; |
| |
| msg.type = WMA_SET_MAX_TX_POWER_REQ; |
| msg.reserved = 0; |
| msg.bodyptr = pMaxTxParams; |
| |
| if (QDF_STATUS_SUCCESS != scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &msg)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post WMA_SET_MAX_TX_POWER_REQ message to WMA", |
| __func__); |
| qdf_mem_free(pMaxTxParams); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /* |
| * sme_set_custom_mac_addr() - |
| * Set the customer Mac Address. |
| * |
| * customMacAddr customer MAC Address |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_set_custom_mac_addr(tSirMacAddr customMacAddr) |
| { |
| struct scheduler_msg msg = {0}; |
| tSirMacAddr *pBaseMacAddr; |
| |
| pBaseMacAddr = qdf_mem_malloc(sizeof(tSirMacAddr)); |
| if (!pBaseMacAddr) |
| return QDF_STATUS_E_NOMEM; |
| |
| qdf_mem_copy(*pBaseMacAddr, customMacAddr, sizeof(tSirMacAddr)); |
| |
| msg.type = SIR_HAL_SET_BASE_MACADDR_IND; |
| msg.reserved = 0; |
| msg.bodyptr = pBaseMacAddr; |
| |
| if (QDF_STATUS_SUCCESS != scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &msg)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "Not able to post SIR_HAL_SET_BASE_MACADDR_IND message to WMA"); |
| qdf_mem_free(pBaseMacAddr); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /* |
| * sme_set_tx_power() - |
| * Set Transmit Power dynamically. |
| * |
| * mac_handle |
| * sessionId Target Session ID |
| * BSSID |
| * dev_mode dev_mode such as station, P2PGO, SAP |
| * dBm power to set |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_set_tx_power(mac_handle_t mac_handle, uint8_t sessionId, |
| struct qdf_mac_addr pBSSId, |
| enum QDF_OPMODE dev_mode, int dBm) |
| { |
| struct scheduler_msg msg = {0}; |
| tpMaxTxPowerParams pTxParams = NULL; |
| int8_t power = (int8_t) dBm; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_SET_TXPOW, sessionId, 0)); |
| |
| /* make sure there is no overflow */ |
| if ((int)power != dBm) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: error, invalid power = %d", __func__, dBm); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| pTxParams = qdf_mem_malloc(sizeof(tMaxTxPowerParams)); |
| if (!pTxParams) |
| return QDF_STATUS_E_NOMEM; |
| |
| qdf_copy_macaddr(&pTxParams->bssId, &pBSSId); |
| pTxParams->power = power; /* unit is dBm */ |
| pTxParams->dev_mode = dev_mode; |
| msg.type = WMA_SET_TX_POWER_REQ; |
| msg.reserved = 0; |
| msg.bodyptr = pTxParams; |
| |
| if (QDF_STATUS_SUCCESS != scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &msg)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: failed to post WMA_SET_TX_POWER_REQ to WMA", |
| __func__); |
| qdf_mem_free(pTxParams); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS sme_update_session_param(mac_handle_t hal, uint8_t session_id, |
| uint32_t param_type, uint32_t param_val) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| uint16_t len; |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| struct sir_update_session_param *msg; |
| struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, |
| session_id); |
| |
| if (!session) { |
| sme_err("Session: %d not found", session_id); |
| sme_release_global_lock(&mac_ctx->sme); |
| return status; |
| } |
| |
| if (param_type == SIR_PARAM_IGNORE_ASSOC_DISALLOWED) |
| mac_ctx->ignore_assoc_disallowed = param_val; |
| |
| if (!session->sessionActive) |
| QDF_ASSERT(0); |
| |
| len = sizeof(*msg); |
| msg = qdf_mem_malloc(len); |
| if (!msg) |
| status = QDF_STATUS_E_NOMEM; |
| else { |
| msg->message_type = eWNI_SME_SESSION_UPDATE_PARAM; |
| msg->length = len; |
| msg->session_id = session_id; |
| msg->param_type = param_type; |
| msg->param_val = param_val; |
| status = umac_send_mb_message_to_mac(msg); |
| } |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_set_tm_level() - |
| * Set Thermal Mitigation Level to RIVA |
| * |
| * mac_handle - The handle returned by mac_open. |
| * newTMLevel - new Thermal Mitigation Level |
| * tmMode - Thermal Mitigation handle mode, default 0 |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_set_tm_level(mac_handle_t mac_handle, |
| uint16_t newTMLevel, |
| uint16_t tmMode) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| tAniSetTmLevelReq *setTmLevelReq = NULL; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_SET_TMLEVEL, NO_SESSION, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| setTmLevelReq = |
| (tAniSetTmLevelReq *) |
| qdf_mem_malloc(sizeof(tAniSetTmLevelReq)); |
| if (NULL == setTmLevelReq) { |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_NOMEM; |
| } |
| |
| setTmLevelReq->tmMode = tmMode; |
| setTmLevelReq->newTmLevel = newTMLevel; |
| |
| /* serialize the req through MC thread */ |
| message.bodyptr = setTmLevelReq; |
| message.type = WMA_SET_TM_LEVEL_REQ; |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| NO_SESSION, message.type)); |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Post Set TM Level MSG fail", __func__); |
| qdf_mem_free(setTmLevelReq); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_feature_caps_exchange() - SME interface to exchange capabilities between |
| * Host and FW. |
| * |
| * mac_handle - HAL handle for device |
| * Return NONE |
| */ |
| void sme_feature_caps_exchange(mac_handle_t mac_handle) |
| { |
| MTRACE(qdf_trace |
| (QDF_MODULE_ID_SME, TRACE_CODE_SME_RX_HDD_CAPS_EXCH, |
| NO_SESSION, 0)); |
| } |
| |
| /* |
| * sme_disable_feature_capablity() - SME interface to disable Active mode |
| * offload capablity in Host. |
| * |
| * mac_handle - HAL handle for device |
| * Return NONE |
| */ |
| void sme_disable_feature_capablity(uint8_t feature_index) |
| { |
| } |
| |
| /* |
| * sme_reset_power_values_for5_g |
| * Reset the power values for 5G band with default power values. |
| * |
| * mac_handle - HAL handle for device |
| * Return NONE |
| */ |
| void sme_reset_power_values_for5_g(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_RESET_PW5G, NO_SESSION, 0)); |
| csr_save_channel_power_for_band(pMac, true); |
| /* Store the channel+power info in the global place: Cfg */ |
| csr_apply_power2_current(pMac); |
| } |
| |
| /* |
| * sme_update_roam_prefer5_g_hz() - |
| * Enable/disable Roam prefer 5G runtime option |
| * This function is called through dynamic setConfig callback function |
| * to configure the Roam prefer 5G runtime option |
| * |
| * mac_handle - HAL handle for device |
| * nRoamPrefer5GHz Enable/Disable Roam prefer 5G runtime option |
| * Return Success or failure |
| */ |
| |
| QDF_STATUS sme_update_roam_prefer5_g_hz(mac_handle_t mac_handle, |
| bool nRoamPrefer5GHz) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_UPDATE_RP5G, NO_SESSION, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: gRoamPrefer5GHz is changed from %d to %d", |
| __func__, pMac->roam.configParam.nRoamPrefer5GHz, |
| nRoamPrefer5GHz); |
| pMac->roam.configParam.nRoamPrefer5GHz = nRoamPrefer5GHz; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_set_roam_intra_band() - |
| * enable/disable Intra band roaming |
| * This function is called through dynamic setConfig callback function |
| * to configure the intra band roaming |
| * mac_handle - HAL handle for device |
| * nRoamIntraBand Enable/Disable Intra band roaming |
| * Return Success or failure |
| */ |
| QDF_STATUS sme_set_roam_intra_band(mac_handle_t mac_handle, |
| const bool nRoamIntraBand) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_SET_ROAMIBAND, NO_SESSION, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: gRoamIntraBand is changed from %d to %d", |
| __func__, pMac->roam.configParam.nRoamIntraBand, |
| nRoamIntraBand); |
| pMac->roam.configParam.nRoamIntraBand = nRoamIntraBand; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_update_roam_scan_n_probes() - |
| * Function to update roam scan N probes |
| * This function is called through dynamic setConfig callback function |
| * to update roam scan N probes |
| * mac_handle - HAL handle for device |
| * sessionId - Session Identifier |
| * nProbes number of probe requests to be sent out |
| * Return Success or failure |
| */ |
| QDF_STATUS sme_update_roam_scan_n_probes(mac_handle_t mac_handle, |
| uint8_t sessionId, |
| const uint8_t nProbes) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_UPDATE_ROAM_SCAN_N_PROBES, |
| NO_SESSION, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: gRoamScanNProbes is changed from %d to %d", |
| __func__, pMac->roam.configParam.nProbes, nProbes); |
| pMac->roam.configParam.nProbes = nProbes; |
| |
| if (pMac->roam.configParam.isRoamOffloadScanEnabled) { |
| csr_roam_offload_scan(pMac, sessionId, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, |
| REASON_NPROBES_CHANGED); |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_update_roam_scan_home_away_time() - |
| * Function to update roam scan Home away time |
| * This function is called through dynamic setConfig callback function |
| * to update roam scan home away time |
| * |
| * mac_handle - HAL handle for device |
| * sessionId - Session Identifier |
| * nRoamScanAwayTime Scan home away time |
| * bSendOffloadCmd If true then send offload command to firmware |
| * If false then command is not sent to firmware |
| * Return Success or failure |
| */ |
| QDF_STATUS sme_update_roam_scan_home_away_time( |
| mac_handle_t mac_handle, |
| uint8_t sessionId, |
| const uint16_t nRoamScanHomeAwayTime, |
| const bool bSendOffloadCmd) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_UPDATE_ROAM_SCAN_HOME_AWAY_TIME, |
| NO_SESSION, 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: gRoamScanHomeAwayTime is changed from %d to %d", |
| __func__, |
| pMac->roam.configParam.nRoamScanHomeAwayTime, |
| nRoamScanHomeAwayTime); |
| pMac->roam.configParam.nRoamScanHomeAwayTime = |
| nRoamScanHomeAwayTime; |
| |
| if (pMac->roam.configParam.isRoamOffloadScanEnabled && |
| bSendOffloadCmd) { |
| csr_roam_offload_scan(pMac, sessionId, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, |
| REASON_HOME_AWAY_TIME_CHANGED); |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /** |
| * sme_ext_change_channel()- function to post send ECSA |
| * action frame to csr. |
| * @mac_handle: Hal context |
| * @channel: new channel to switch |
| * @session_id: senssion it should be sent on. |
| * |
| * This function is called to post ECSA frame to csr. |
| * |
| * Return: success if msg is sent else return failure |
| */ |
| QDF_STATUS sme_ext_change_channel(mac_handle_t mac_handle, uint32_t channel, |
| uint8_t session_id) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| uint8_t channel_state; |
| |
| sme_err("Set Channel: %d", channel); |
| channel_state = |
| wlan_reg_get_channel_state(mac_ctx->pdev, channel); |
| |
| if (CHANNEL_STATE_DISABLE == channel_state) { |
| sme_err("Invalid channel: %d", channel); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| |
| if (QDF_STATUS_SUCCESS == status) { |
| /* update the channel list to the firmware */ |
| status = csr_send_ext_change_channel(mac_ctx, |
| channel, session_id); |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_get_roam_intra_band() - |
| * get Intra band roaming |
| * |
| * mac_handle - HAL handle for device |
| * Return Success or failure |
| */ |
| bool sme_get_roam_intra_band(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_GET_ROAMIBAND, NO_SESSION, 0)); |
| return pMac->roam.configParam.nRoamIntraBand; |
| } |
| |
| /* |
| * sme_get_roam_scan_n_probes() - |
| * get N Probes |
| * |
| * mac_handle - HAL handle for device |
| * Return Success or failure |
| */ |
| uint8_t sme_get_roam_scan_n_probes(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.nProbes; |
| } |
| |
| /* |
| * sme_get_roam_scan_home_away_time() - |
| * get Roam scan home away time |
| * |
| * mac_handle - HAL handle for device |
| * Return Success or failure |
| */ |
| uint16_t sme_get_roam_scan_home_away_time(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.nRoamScanHomeAwayTime; |
| } |
| |
| /* |
| * sme_update_roam_rssi_diff() - |
| * Update RoamRssiDiff |
| * This function is called through dynamic setConfig callback function |
| * to configure RoamRssiDiff |
| * Usage: adb shell iwpriv wlan0 setConfig RoamRssiDiff=[0 .. 125] |
| * |
| * mac_handle - HAL handle for device |
| * sessionId - Session Identifier |
| * RoamRssiDiff - minimum rssi difference between potential |
| * candidate and current AP. |
| * Return Success or failure |
| */ |
| |
| QDF_STATUS sme_update_roam_rssi_diff(mac_handle_t mac_handle, uint8_t sessionId, |
| uint8_t RoamRssiDiff) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| if (sessionId >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), sessionId); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "LFR runtime successfully set roam rssi diff to %d - old value is %d - roam state is %s", |
| RoamRssiDiff, |
| pMac->roam.configParam.RoamRssiDiff, |
| mac_trace_get_neighbour_roam_state(pMac->roam. |
| neighborRoamInfo |
| [sessionId]. |
| neighborRoamState)); |
| pMac->roam.configParam.RoamRssiDiff = RoamRssiDiff; |
| |
| if (pMac->roam.configParam.isRoamOffloadScanEnabled) |
| csr_roam_offload_scan(pMac, sessionId, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, |
| REASON_RSSI_DIFF_CHANGED); |
| |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| #ifdef WLAN_FEATURE_FILS_SK |
| QDF_STATUS sme_update_fils_config(mac_handle_t hal, uint8_t session_id, |
| struct csr_roam_profile *src_profile) |
| { |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpCsrNeighborRoamControlInfo neighbor_roam_info = |
| &mac->roam.neighborRoamInfo[session_id]; |
| |
| if (session_id >= CSR_ROAM_SESSION_MAX) { |
| sme_err("Invalid sme session id: %d", session_id); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| if (!src_profile) { |
| sme_err("src roam profile NULL"); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| if (!mac->roam.configParam.isFastRoamIniFeatureEnabled || |
| (neighbor_roam_info->neighborRoamState != |
| eCSR_NEIGHBOR_ROAM_STATE_CONNECTED)) { |
| sme_info("Fast roam is disabled or not connected(%d)", |
| neighbor_roam_info->neighborRoamState); |
| return QDF_STATUS_E_PERM; |
| } |
| |
| csr_update_fils_config(mac, session_id, src_profile); |
| if (csr_roamIsRoamOffloadEnabled(mac)) { |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| sme_debug("Updating fils config to fw"); |
| csr_roam_offload_scan(mac, session_id, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, |
| REASON_FILS_PARAMS_CHANGED); |
| sme_release_global_lock(&mac->sme); |
| } else { |
| sme_err("Failed to acquire SME lock"); |
| } |
| } else { |
| sme_info("LFR3 not enabled"); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| return status; |
| } |
| |
| void sme_send_hlp_ie_info(mac_handle_t hal, uint8_t session_id, |
| struct csr_roam_profile *profile, uint32_t if_addr) |
| { |
| int i; |
| struct scheduler_msg msg; |
| QDF_STATUS status; |
| struct hlp_params *params; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| struct csr_roam_session *session = CSR_GET_SESSION(mac, session_id); |
| tpCsrNeighborRoamControlInfo neighbor_roam_info = |
| &mac->roam.neighborRoamInfo[session_id]; |
| |
| if (!session) { |
| sme_err("session NULL"); |
| return; |
| } |
| |
| if (!mac->roam.configParam.isFastRoamIniFeatureEnabled || |
| (neighbor_roam_info->neighborRoamState != |
| eCSR_NEIGHBOR_ROAM_STATE_CONNECTED)) { |
| sme_debug("Fast roam is disabled or not connected(%d)", |
| neighbor_roam_info->neighborRoamState); |
| return; |
| } |
| |
| params = qdf_mem_malloc(sizeof(*params)); |
| if (!params) |
| return; |
| |
| if ((profile->hlp_ie_len + |
| SIR_IPV4_ADDR_LEN) > FILS_MAX_HLP_DATA_LEN) { |
| sme_err("HLP IE len exceeds %d", |
| profile->hlp_ie_len); |
| qdf_mem_free(params); |
| return; |
| } |
| |
| params->vdev_id = session_id; |
| params->hlp_ie_len = profile->hlp_ie_len + SIR_IPV4_ADDR_LEN; |
| |
| for (i = 0; i < SIR_IPV4_ADDR_LEN; i++) |
| params->hlp_ie[i] = (if_addr >> (i * 8)) & 0xFF; |
| |
| qdf_mem_copy(params->hlp_ie + SIR_IPV4_ADDR_LEN, |
| profile->hlp_ie, profile->hlp_ie_len); |
| |
| msg.type = SIR_HAL_HLP_IE_INFO; |
| msg.reserved = 0; |
| msg.bodyptr = params; |
| status = sme_acquire_global_lock(&mac->sme); |
| if (status != QDF_STATUS_SUCCESS) { |
| sme_err("sme lock acquire fails"); |
| qdf_mem_free(params); |
| return; |
| } |
| |
| if (!QDF_IS_STATUS_SUCCESS |
| (scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg))) { |
| sme_err("Not able to post WMA_HLP_IE_INFO message to HAL"); |
| sme_release_global_lock(&mac->sme); |
| qdf_mem_free(params); |
| return; |
| } |
| |
| sme_release_global_lock(&mac->sme); |
| } |
| |
| void sme_free_join_rsp_fils_params(struct csr_roam_info *roam_info) |
| { |
| struct fils_join_rsp_params *roam_fils_params; |
| |
| if (!roam_info) { |
| sme_err("FILS Roam Info NULL"); |
| return; |
| } |
| |
| roam_fils_params = roam_info->fils_join_rsp; |
| if (!roam_fils_params) { |
| sme_err("FILS Roam Param NULL"); |
| return; |
| } |
| |
| if (roam_fils_params->fils_pmk) |
| qdf_mem_free(roam_fils_params->fils_pmk); |
| |
| qdf_mem_free(roam_fils_params); |
| |
| roam_info->fils_join_rsp = NULL; |
| } |
| |
| #else |
| inline void sme_send_hlp_ie_info(mac_handle_t hal, uint8_t session_id, |
| struct csr_roam_profile *profile, uint32_t if_addr) |
| {} |
| #endif |
| |
| /* |
| * sme_update_fast_transition_enabled() - enable/disable Fast Transition |
| * support at runtime |
| * It is used at in the REG_DYNAMIC_VARIABLE macro definition of |
| * isFastTransitionEnabled. |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * Return QDF_STATUS_SUCCESS - SME update isFastTransitionEnabled config |
| * successfully. |
| * Other status means SME is failed to update isFastTransitionEnabled. |
| */ |
| QDF_STATUS sme_update_fast_transition_enabled(mac_handle_t mac_handle, |
| bool isFastTransitionEnabled) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_UPDATE_FTENABLED, NO_SESSION, |
| 0)); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: FastTransitionEnabled is changed from %d to %d", |
| __func__, |
| pMac->roam.configParam.isFastTransitionEnabled, |
| isFastTransitionEnabled); |
| pMac->roam.configParam.isFastTransitionEnabled = |
| isFastTransitionEnabled; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_update_wes_mode() - |
| * Update WES Mode |
| * This function is called through dynamic setConfig callback function |
| * to configure isWESModeEnabled |
| * |
| * mac_handle - HAL handle for device |
| * isWESModeEnabled - WES mode |
| * sessionId - Session Identifier |
| * Return QDF_STATUS_SUCCESS - SME update isWESModeEnabled config successfully. |
| * Other status means SME is failed to update isWESModeEnabled. |
| */ |
| |
| QDF_STATUS sme_update_wes_mode(mac_handle_t mac_handle, bool isWESModeEnabled, |
| uint8_t sessionId) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| if (sessionId >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), sessionId); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "LFR runtime successfully set WES Mode to %d - old value is %d - roam state is %s", |
| isWESModeEnabled, |
| pMac->roam.configParam.isWESModeEnabled, |
| mac_trace_get_neighbour_roam_state(pMac->roam. |
| neighborRoamInfo |
| [sessionId]. |
| neighborRoamState)); |
| pMac->roam.configParam.isWESModeEnabled = isWESModeEnabled; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_set_roam_scan_control() - |
| * Set roam scan control |
| * This function is called to set roam scan control |
| * if roam scan control is set to 0, roaming scan cache is cleared |
| * any value other than 0 is treated as invalid value |
| * mac_handle - HAL handle for device |
| * sessionId - Session Identifier |
| * Return QDF_STATUS_SUCCESS - SME update config successfully. |
| * Other status means SME failure to update |
| */ |
| QDF_STATUS sme_set_roam_scan_control(mac_handle_t mac_handle, uint8_t sessionId, |
| bool roamScanControl) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, |
| TRACE_CODE_SME_RX_HDD_SET_SCANCTRL, NO_SESSION, 0)); |
| |
| if (sessionId >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), sessionId); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "LFR runtime successfully set roam scan control to %d - old value is %d - roam state is %s", |
| roamScanControl, |
| pMac->roam.configParam.nRoamScanControl, |
| mac_trace_get_neighbour_roam_state(pMac->roam. |
| neighborRoamInfo |
| [sessionId]. |
| neighborRoamState)); |
| pMac->roam.configParam.nRoamScanControl = roamScanControl; |
| if (0 == roamScanControl) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "LFR runtime successfully cleared roam scan cache"); |
| csr_flush_cfg_bg_scan_roam_channel_list(pMac, |
| sessionId); |
| if (pMac->roam.configParam.isRoamOffloadScanEnabled) { |
| csr_roam_offload_scan(pMac, sessionId, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, |
| REASON_FLUSH_CHANNEL_LIST); |
| } |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_update_is_fast_roam_ini_feature_enabled() - enable/disable LFR |
| * support at runtime |
| * It is used at in the REG_DYNAMIC_VARIABLE macro definition of |
| * isFastRoamIniFeatureEnabled. |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * sessionId - Session Identifier |
| * Return QDF_STATUS_SUCCESS - SME update isFastRoamIniFeatureEnabled config |
| * successfully. |
| * Other status means SME is failed to update isFastRoamIniFeatureEnabled. |
| */ |
| QDF_STATUS sme_update_is_fast_roam_ini_feature_enabled(mac_handle_t mac_handle, |
| uint8_t sessionId, const bool isFastRoamIniFeatureEnabled) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (pMac->roam.configParam.isFastRoamIniFeatureEnabled == |
| isFastRoamIniFeatureEnabled) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: FastRoam is already enabled or disabled, nothing to do (returning) old(%d) new(%d)", |
| __func__, |
| pMac->roam.configParam.isFastRoamIniFeatureEnabled, |
| isFastRoamIniFeatureEnabled); |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: FastRoamEnabled is changed from %d to %d", __func__, |
| pMac->roam.configParam.isFastRoamIniFeatureEnabled, |
| isFastRoamIniFeatureEnabled); |
| pMac->roam.configParam.isFastRoamIniFeatureEnabled = |
| isFastRoamIniFeatureEnabled; |
| csr_neighbor_roam_update_fast_roaming_enabled(pMac, sessionId, |
| isFastRoamIniFeatureEnabled); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_config_fast_roaming() - enable/disable LFR support at runtime |
| * @hal - The handle returned by macOpen. |
| * @session_id - Session Identifier |
| * @is_fast_roam_enabled - flag to enable/disable roaming |
| * |
| * When Supplicant issues enabled/disable fast roaming on the basis |
| * of the Bssid modification in network block (e.g. AutoJoin mode N/W block) |
| * |
| * Return: QDF_STATUS |
| */ |
| |
| QDF_STATUS sme_config_fast_roaming(mac_handle_t hal, uint8_t session_id, |
| const bool is_fast_roam_enabled) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, session_id); |
| QDF_STATUS status; |
| |
| /* |
| * supplicant_disabled_roaming flag is set to true in |
| * wlan_hdd_cfg80211_connect_start when supplicant initiate connect |
| * request with BSSID. This flag is reset when supplicant sends |
| * vendor command to enable roaming after association. |
| * |
| * This request from wpa_supplicant will be skipped in this function |
| * if roaming is disabled using driver command or INI and |
| * supplicant_disabled_roaming flag remains set. So make sure to set |
| * supplicant_disabled_roaming flag as per wpa_supplicant even if roam |
| * request from wpa_supplicant ignored. |
| */ |
| if (session && session->pCurRoamProfile) |
| session->pCurRoamProfile->supplicant_disabled_roaming = |
| !is_fast_roam_enabled; |
| |
| if (!mac_ctx->roam.configParam.isFastRoamIniFeatureEnabled) { |
| sme_debug("Fast roam is disabled through ini"); |
| if (!is_fast_roam_enabled) |
| return QDF_STATUS_SUCCESS; |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| status = csr_neighbor_roam_update_fast_roaming_enabled(mac_ctx, |
| session_id, is_fast_roam_enabled); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("update fast roaming failed. status: %d", status); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /* |
| * sme_update_is_mawc_ini_feature_enabled() - |
| * Enable/disable LFR MAWC support at runtime |
| * It is used at in the REG_DYNAMIC_VARIABLE macro definition of |
| * isMAWCIniFeatureEnabled. |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * Return QDF_STATUS_SUCCESS - SME update MAWCEnabled config successfully. |
| * Other status means SME is failed to update MAWCEnabled. |
| */ |
| QDF_STATUS sme_update_is_mawc_ini_feature_enabled(mac_handle_t mac_handle, |
| const bool MAWCEnabled) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: MAWCEnabled is changed from %d to %d", __func__, |
| pMac->roam.configParam.csr_mawc_config.mawc_enabled, |
| MAWCEnabled); |
| pMac->roam.configParam.csr_mawc_config.mawc_enabled = |
| MAWCEnabled; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| |
| } |
| |
| /** |
| * sme_stop_roaming() - Stop roaming for a given sessionId |
| * This is a synchronous call |
| * |
| * @mac_handle - The handle returned by mac_open |
| * @sessionId - Session Identifier |
| * |
| * Return QDF_STATUS_SUCCESS on success |
| * Other status on failure |
| */ |
| QDF_STATUS sme_stop_roaming(mac_handle_t mac_handle, uint8_t session_id, |
| uint8_t reason) |
| { |
| struct scheduler_msg wma_msg = {0}; |
| QDF_STATUS status; |
| tSirRoamOffloadScanReq *req; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| tpCsrNeighborRoamControlInfo roam_info; |
| struct csr_roam_session *session; |
| |
| if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) { |
| sme_err("incorrect session/vdev ID"); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| session = CSR_GET_SESSION(mac_ctx, session_id); |
| |
| /* |
| * set the driver_disabled_roaming flag to true even if roaming |
| * is not enabled on this session so that roam start requests for |
| * this session can be blocked until driver enables roaming |
| */ |
| if (reason == ecsr_driver_disabled && session->pCurRoamProfile && |
| session->pCurRoamProfile->csrPersona == QDF_STA_MODE) { |
| session->pCurRoamProfile->driver_disabled_roaming = true; |
| sme_debug("driver_disabled_roaming set for session %d", |
| session_id); |
| } |
| |
| roam_info = &mac_ctx->roam.neighborRoamInfo[session_id]; |
| if (!roam_info->b_roam_scan_offload_started) { |
| sme_debug("Roaming already disabled for session %d", session_id); |
| return QDF_STATUS_SUCCESS; |
| } |
| req = qdf_mem_malloc(sizeof(*req)); |
| if (!req) |
| return QDF_STATUS_E_NOMEM; |
| |
| req->Command = ROAM_SCAN_OFFLOAD_STOP; |
| if ((reason == eCsrForcedDisassoc) || reason == ecsr_driver_disabled) |
| req->reason = REASON_ROAM_STOP_ALL; |
| else |
| req->reason = REASON_SME_ISSUED; |
| req->sessionId = session_id; |
| if (csr_neighbor_middle_of_roaming(mac_ctx, session_id)) |
| req->middle_of_roaming = 1; |
| else |
| csr_roam_reset_roam_params(mac_ctx); |
| |
| wma_msg.type = WMA_ROAM_SCAN_OFFLOAD_REQ; |
| wma_msg.bodyptr = req; |
| |
| status = wma_post_ctrl_msg(mac_ctx, &wma_msg); |
| if (QDF_STATUS_SUCCESS != status) { |
| sme_err("WMA_ROAM_SCAN_OFFLOAD_REQ failed, session_id: %d", |
| session_id); |
| qdf_mem_free(req); |
| return QDF_STATUS_E_FAULT; |
| } |
| roam_info->b_roam_scan_offload_started = false; |
| roam_info->last_sent_cmd = ROAM_SCAN_OFFLOAD_STOP; |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /* |
| * sme_start_roaming() - Start roaming for a given sessionId |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open |
| * sessionId - Session Identifier |
| * Return QDF_STATUS_SUCCESS on success |
| * Other status on failure |
| */ |
| QDF_STATUS sme_start_roaming(mac_handle_t mac_handle, uint8_t sessionId, |
| uint8_t reason) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| csr_roam_offload_scan(pMac, sessionId, ROAM_SCAN_OFFLOAD_START, |
| reason); |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_update_enable_fast_roam_in_concurrency() - enable/disable LFR if |
| * Concurrent session exists |
| * This is a synchronuous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * Return QDF_STATUS_SUCCESS |
| * Other status means SME is failed |
| */ |
| QDF_STATUS sme_update_enable_fast_roam_in_concurrency(mac_handle_t mac_handle, |
| bool |
| bFastRoamInConIniFeatureEnabled) |
| { |
| |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| pMac->roam.configParam.bFastRoamInConIniFeatureEnabled = |
| bFastRoamInConIniFeatureEnabled; |
| if (0 == pMac->roam.configParam.isRoamOffloadScanEnabled) { |
| pMac->roam.configParam.bFastRoamInConIniFeatureEnabled = |
| 0; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_set_roam_opportunistic_scan_threshold_diff() - |
| * Update Opportunistic Scan threshold diff |
| * This function is called through dynamic setConfig callback function |
| * to configure nOpportunisticThresholdDiff |
| * |
| * mac_handle - HAL handle for device |
| * sessionId - Session Identifier |
| * nOpportunisticThresholdDiff - Opportunistic Scan threshold diff |
| * Return QDF_STATUS_SUCCESS - SME update nOpportunisticThresholdDiff config |
| * successfully. |
| * else SME is failed to update nOpportunisticThresholdDiff. |
| */ |
| QDF_STATUS sme_set_roam_opportunistic_scan_threshold_diff( |
| mac_handle_t mac_handle, |
| uint8_t sessionId, |
| const uint8_t nOpportunisticThresholdDiff) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_neighbor_roam_update_config(pMac, sessionId, |
| nOpportunisticThresholdDiff, |
| REASON_OPPORTUNISTIC_THRESH_DIFF_CHANGED); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| pMac->roam.configParam.neighborRoamConfig. |
| nOpportunisticThresholdDiff = |
| nOpportunisticThresholdDiff; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_get_roam_opportunistic_scan_threshold_diff() |
| * gets Opportunistic Scan threshold diff |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open |
| * Return uint8_t - nOpportunisticThresholdDiff |
| */ |
| uint8_t sme_get_roam_opportunistic_scan_threshold_diff(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.neighborRoamConfig. |
| nOpportunisticThresholdDiff; |
| } |
| |
| /* |
| * sme_set_roam_rescan_rssi_diff() - Update roam rescan rssi diff |
| * This function is called through dynamic setConfig callback function |
| * to configure nRoamRescanRssiDiff |
| * |
| * mac_handle - HAL handle for device |
| * sessionId - Session Identifier |
| * nRoamRescanRssiDiff - roam rescan rssi diff |
| * Return QDF_STATUS_SUCCESS - SME update nRoamRescanRssiDiff config |
| * successfully. |
| * else SME is failed to update nRoamRescanRssiDiff. |
| */ |
| QDF_STATUS sme_set_roam_rescan_rssi_diff(mac_handle_t mac_handle, |
| uint8_t sessionId, |
| const uint8_t nRoamRescanRssiDiff) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_neighbor_roam_update_config(pMac, sessionId, |
| nRoamRescanRssiDiff, |
| REASON_ROAM_RESCAN_RSSI_DIFF_CHANGED); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| pMac->roam.configParam.neighborRoamConfig. |
| nRoamRescanRssiDiff = nRoamRescanRssiDiff; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_get_roam_rescan_rssi_diff() |
| * gets roam rescan rssi diff |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open |
| * Return int8_t - nRoamRescanRssiDiff |
| */ |
| uint8_t sme_get_roam_rescan_rssi_diff(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.neighborRoamConfig.nRoamRescanRssiDiff; |
| } |
| |
| /* |
| * sme_set_roam_bmiss_first_bcnt() - |
| * Update Roam count for first beacon miss |
| * This function is called through dynamic setConfig callback function |
| * to configure nRoamBmissFirstBcnt |
| * mac_handle - HAL handle for device |
| * sessionId - Session Identifier |
| * nRoamBmissFirstBcnt - Roam first bmiss count |
| * Return QDF_STATUS_SUCCESS - SME update nRoamBmissFirstBcnt |
| * successfully. |
| * else SME is failed to update nRoamBmissFirstBcnt |
| */ |
| QDF_STATUS sme_set_roam_bmiss_first_bcnt(mac_handle_t mac_handle, |
| uint8_t sessionId, |
| const uint8_t nRoamBmissFirstBcnt) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_neighbor_roam_update_config(pMac, sessionId, |
| nRoamBmissFirstBcnt, |
| REASON_ROAM_BMISS_FIRST_BCNT_CHANGED); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| pMac->roam.configParam.neighborRoamConfig. |
| nRoamBmissFirstBcnt = nRoamBmissFirstBcnt; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_get_roam_bmiss_first_bcnt() - |
| * get neighbor roam beacon miss first count |
| * |
| * mac_handle - The handle returned by mac_open. |
| * Return uint8_t - neighbor roam beacon miss first count |
| */ |
| uint8_t sme_get_roam_bmiss_first_bcnt(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.neighborRoamConfig.nRoamBmissFirstBcnt; |
| } |
| |
| /* |
| * sme_set_roam_bmiss_final_bcnt() - |
| * Update Roam count for final beacon miss |
| * This function is called through dynamic setConfig callback function |
| * to configure nRoamBmissFinalBcnt |
| * mac_handle - HAL handle for device |
| * sessionId - Session Identifier |
| * nRoamBmissFinalBcnt - Roam final bmiss count |
| * Return QDF_STATUS_SUCCESS - SME update nRoamBmissFinalBcnt |
| * successfully. |
| * else SME is failed to update nRoamBmissFinalBcnt |
| */ |
| QDF_STATUS sme_set_roam_bmiss_final_bcnt(mac_handle_t mac_handle, |
| uint8_t sessionId, |
| const uint8_t nRoamBmissFinalBcnt) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_neighbor_roam_update_config(pMac, sessionId, |
| nRoamBmissFinalBcnt, |
| REASON_ROAM_BMISS_FINAL_BCNT_CHANGED); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| pMac->roam.configParam.neighborRoamConfig. |
| nRoamBmissFinalBcnt = nRoamBmissFinalBcnt; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_get_roam_bmiss_final_bcnt() - |
| * gets Roam count for final beacon miss |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open |
| * Return uint8_t - nRoamBmissFinalBcnt |
| */ |
| uint8_t sme_get_roam_bmiss_final_bcnt(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.neighborRoamConfig.nRoamBmissFinalBcnt; |
| } |
| |
| /* |
| * sme_set_roam_beacon_rssi_weight() - |
| * Update Roam beacon rssi weight |
| * This function is called through dynamic setConfig callback function |
| * to configure nRoamBeaconRssiWeight |
| * |
| * mac_handle - HAL handle for device |
| * sessionId - Session Identifier |
| * nRoamBeaconRssiWeight - Roam beacon rssi weight |
| * Return QDF_STATUS_SUCCESS - SME update nRoamBeaconRssiWeight config |
| * successfully. |
| * else SME is failed to update nRoamBeaconRssiWeight |
| */ |
| QDF_STATUS sme_set_roam_beacon_rssi_weight(mac_handle_t mac_handle, |
| uint8_t sessionId, |
| const uint8_t nRoamBeaconRssiWeight) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_neighbor_roam_update_config(pMac, sessionId, |
| nRoamBeaconRssiWeight, |
| REASON_ROAM_BEACON_RSSI_WEIGHT_CHANGED); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| pMac->roam.configParam.neighborRoamConfig. |
| nRoamBeaconRssiWeight = nRoamBeaconRssiWeight; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_get_roam_beacon_rssi_weight() - |
| * gets Roam beacon rssi weight |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open |
| * Return uint8_t - nRoamBeaconRssiWeight |
| */ |
| uint8_t sme_get_roam_beacon_rssi_weight(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.neighborRoamConfig.nRoamBeaconRssiWeight; |
| } |
| |
| /* |
| * sme_set_neighbor_lookup_rssi_threshold() - update neighbor lookup |
| * rssi threshold |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * sessionId - Session Identifier |
| * Return QDF_STATUS_SUCCESS - SME update config successful. |
| * Other status means SME is failed to update |
| */ |
| QDF_STATUS sme_set_neighbor_lookup_rssi_threshold(mac_handle_t mac_handle, |
| uint8_t sessionId, uint8_t neighborLookupRssiThreshold) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_neighbor_roam_update_config(pMac, |
| sessionId, neighborLookupRssiThreshold, |
| REASON_LOOKUP_THRESH_CHANGED); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| pMac->roam.configParam.neighborRoamConfig. |
| nNeighborLookupRssiThreshold = |
| neighborLookupRssiThreshold; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_set_delay_before_vdev_stop() - update delay before VDEV_STOP |
| * This is a synchronous call |
| * |
| * hal - The handle returned by macOpen. |
| * session_id - Session Identifier |
| * delay_before_vdev_stop - value to be set |
| * Return QDF_STATUS_SUCCESS - SME update config successful. |
| * Other status means SME is failed to update |
| */ |
| QDF_STATUS sme_set_delay_before_vdev_stop(mac_handle_t hal, |
| uint8_t session_id, |
| uint8_t delay_before_vdev_stop) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(hal); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| if (session_id >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), session_id); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "LFR param delay_before_vdev_stop changed from %d to %d", |
| pMac->roam.configParam.neighborRoamConfig. |
| delay_before_vdev_stop, |
| delay_before_vdev_stop); |
| pMac->roam.neighborRoamInfo[session_id].cfgParams. |
| delay_before_vdev_stop = delay_before_vdev_stop; |
| pMac->roam.configParam.neighborRoamConfig. |
| delay_before_vdev_stop = delay_before_vdev_stop; |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_get_neighbor_lookup_rssi_threshold() - get neighbor lookup |
| * rssi threshold |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * Return QDF_STATUS_SUCCESS - SME update config successful. |
| * Other status means SME is failed to update |
| */ |
| uint8_t sme_get_neighbor_lookup_rssi_threshold(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.neighborRoamConfig. |
| nNeighborLookupRssiThreshold; |
| } |
| |
| /* |
| * sme_set_neighbor_scan_refresh_period() - set neighbor scan results |
| * refresh period |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * sessionId - Session Identifier |
| * Return QDF_STATUS_SUCCESS - SME update config successful. |
| * Other status means SME is failed to update |
| */ |
| QDF_STATUS sme_set_neighbor_scan_refresh_period(mac_handle_t mac_handle, |
| uint8_t sessionId, uint16_t neighborScanResultsRefreshPeriod) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| struct csr_neighbor_roamconfig *pNeighborRoamConfig = NULL; |
| tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; |
| |
| if (sessionId >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), sessionId); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| pNeighborRoamConfig = |
| &pMac->roam.configParam.neighborRoamConfig; |
| pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "LFR runtime successfully set roam scan refresh period to %d- old value is %d - roam state is %s", |
| neighborScanResultsRefreshPeriod, |
| pMac->roam.configParam.neighborRoamConfig. |
| nNeighborResultsRefreshPeriod, |
| mac_trace_get_neighbour_roam_state(pMac->roam. |
| neighborRoamInfo |
| [sessionId]. |
| neighborRoamState)); |
| pNeighborRoamConfig->nNeighborResultsRefreshPeriod = |
| neighborScanResultsRefreshPeriod; |
| pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod = |
| neighborScanResultsRefreshPeriod; |
| |
| if (pMac->roam.configParam.isRoamOffloadScanEnabled) { |
| csr_roam_offload_scan(pMac, sessionId, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, |
| REASON_NEIGHBOR_SCAN_REFRESH_PERIOD_CHANGED); |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_update_roam_scan_offload_enabled() - enable/disable roam scan |
| * offload feaure |
| * It is used at in the REG_DYNAMIC_VARIABLE macro definition of |
| * gRoamScanOffloadEnabled. |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * Return QDF_STATUS_SUCCESS - SME update config successfully. |
| * Other status means SME is failed to update. |
| */ |
| QDF_STATUS sme_update_roam_scan_offload_enabled(mac_handle_t mac_handle, |
| bool nRoamScanOffloadEnabled) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "gRoamScanOffloadEnabled is changed from %d to %d", |
| pMac->roam.configParam.isRoamOffloadScanEnabled, |
| nRoamScanOffloadEnabled); |
| pMac->roam.configParam.isRoamOffloadScanEnabled = |
| nRoamScanOffloadEnabled; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_get_neighbor_scan_refresh_period() - get neighbor scan results |
| * refresh period |
| * This is a synchronous call |
| * |
| * \param mac_handle - The handle returned by mac_open. |
| * \return uint16_t - Neighbor scan results refresh period value |
| */ |
| uint16_t sme_get_neighbor_scan_refresh_period(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.neighborRoamConfig. |
| nNeighborResultsRefreshPeriod; |
| } |
| |
| /* |
| * sme_get_empty_scan_refresh_period() - get empty scan refresh period |
| * This is a synchronuous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * Return QDF_STATUS_SUCCESS - SME update config successful. |
| * Other status means SME is failed to update |
| */ |
| uint16_t sme_get_empty_scan_refresh_period(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.neighborRoamConfig. |
| nEmptyScanRefreshPeriod; |
| } |
| |
| /* |
| * sme_update_empty_scan_refresh_period |
| * Update nEmptyScanRefreshPeriod |
| * This function is called through dynamic setConfig callback function |
| * to configure nEmptyScanRefreshPeriod |
| * Usage: adb shell iwpriv wlan0 setConfig |
| * nEmptyScanRefreshPeriod=[0 .. 60] |
| * |
| * mac_handle - HAL handle for device |
| * sessionId - Session Identifier |
| * nEmptyScanRefreshPeriod - scan period following empty scan results. |
| * Return Success or failure |
| */ |
| |
| QDF_STATUS sme_update_empty_scan_refresh_period(mac_handle_t mac_handle, |
| uint8_t sessionId, uint16_t |
| nEmptyScanRefreshPeriod) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| struct csr_neighbor_roamconfig *pNeighborRoamConfig = NULL; |
| tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; |
| |
| if (sessionId >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), sessionId); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| pNeighborRoamConfig = |
| &pMac->roam.configParam.neighborRoamConfig; |
| pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "LFR runtime successfully set roam scan period to %d -old value is %d - roam state is %s", |
| nEmptyScanRefreshPeriod, |
| pMac->roam.configParam.neighborRoamConfig. |
| nEmptyScanRefreshPeriod, |
| mac_trace_get_neighbour_roam_state(pMac->roam. |
| neighborRoamInfo |
| [sessionId]. |
| neighborRoamState)); |
| pNeighborRoamConfig->nEmptyScanRefreshPeriod = |
| nEmptyScanRefreshPeriod; |
| pNeighborRoamInfo->cfgParams.emptyScanRefreshPeriod = |
| nEmptyScanRefreshPeriod; |
| |
| if (pMac->roam.configParam.isRoamOffloadScanEnabled) { |
| csr_roam_offload_scan(pMac, sessionId, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, |
| REASON_EMPTY_SCAN_REF_PERIOD_CHANGED); |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_set_neighbor_scan_min_chan_time() - |
| * Update nNeighborScanMinChanTime |
| * This function is called through dynamic setConfig callback function |
| * to configure gNeighborScanChannelMinTime |
| * Usage: adb shell iwpriv wlan0 setConfig |
| * gNeighborScanChannelMinTime=[0 .. 60] |
| * |
| * mac_handle - HAL handle for device |
| * nNeighborScanMinChanTime - Channel minimum dwell time |
| * sessionId - Session Identifier |
| * Return Success or failure |
| */ |
| QDF_STATUS sme_set_neighbor_scan_min_chan_time(mac_handle_t mac_handle, |
| const uint16_t |
| nNeighborScanMinChanTime, |
| uint8_t sessionId) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| if (sessionId >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), sessionId); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "LFR runtime successfully set channel min dwell time to %d - old value is %d - roam state is %s", |
| nNeighborScanMinChanTime, |
| pMac->roam.configParam.neighborRoamConfig. |
| nNeighborScanMinChanTime, |
| mac_trace_get_neighbour_roam_state(pMac->roam. |
| neighborRoamInfo |
| [sessionId]. |
| neighborRoamState)); |
| |
| pMac->roam.configParam.neighborRoamConfig. |
| nNeighborScanMinChanTime = nNeighborScanMinChanTime; |
| pMac->roam.neighborRoamInfo[sessionId].cfgParams. |
| minChannelScanTime = nNeighborScanMinChanTime; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_set_neighbor_scan_max_chan_time() - |
| * Update nNeighborScanMaxChanTime |
| * This function is called through dynamic setConfig callback function |
| * to configure gNeighborScanChannelMaxTime |
| * Usage: adb shell iwpriv wlan0 setConfig |
| * gNeighborScanChannelMaxTime=[0 .. 60] |
| * |
| * mac_handle - HAL handle for device |
| * sessionId - Session Identifier |
| * nNeighborScanMinChanTime - Channel maximum dwell time |
| * Return Success or failure |
| */ |
| QDF_STATUS sme_set_neighbor_scan_max_chan_time(mac_handle_t mac_handle, |
| uint8_t sessionId, |
| const uint16_t |
| nNeighborScanMaxChanTime) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| struct csr_neighbor_roamconfig *pNeighborRoamConfig = NULL; |
| tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; |
| |
| if (sessionId >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), sessionId); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| pNeighborRoamConfig = |
| &pMac->roam.configParam.neighborRoamConfig; |
| pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "LFR runtime successfully set channel max dwell time to %d - old value is %d - roam state is %s", |
| nNeighborScanMaxChanTime, |
| pMac->roam.configParam.neighborRoamConfig. |
| nNeighborScanMaxChanTime, |
| mac_trace_get_neighbour_roam_state(pMac->roam. |
| neighborRoamInfo |
| [sessionId]. |
| neighborRoamState)); |
| pNeighborRoamConfig->nNeighborScanMaxChanTime = |
| nNeighborScanMaxChanTime; |
| pNeighborRoamInfo->cfgParams.maxChannelScanTime = |
| nNeighborScanMaxChanTime; |
| if (pMac->roam.configParam.isRoamOffloadScanEnabled) { |
| csr_roam_offload_scan(pMac, sessionId, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, |
| REASON_SCAN_CH_TIME_CHANGED); |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| |
| return status; |
| } |
| |
| /* |
| * sme_get_neighbor_scan_min_chan_time() - |
| * get neighbor scan min channel time |
| * |
| * mac_handle - The handle returned by mac_open. |
| * sessionId - Session Identifier |
| * Return uint16_t - channel min time value |
| */ |
| uint16_t sme_get_neighbor_scan_min_chan_time(mac_handle_t mac_handle, |
| uint8_t sessionId) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (sessionId >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), sessionId); |
| return 0; |
| } |
| |
| return pMac->roam.neighborRoamInfo[sessionId].cfgParams. |
| minChannelScanTime; |
| } |
| |
| /* |
| * sme_get_neighbor_roam_state() - |
| * get neighbor roam state |
| * |
| * mac_handle - The handle returned by mac_open. |
| * sessionId - Session Identifier |
| * Return uint32_t - neighbor roam state |
| */ |
| uint32_t sme_get_neighbor_roam_state(mac_handle_t mac_handle, uint8_t sessionId) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (sessionId >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), sessionId); |
| return 0; |
| } |
| |
| return pMac->roam.neighborRoamInfo[sessionId].neighborRoamState; |
| } |
| |
| /* |
| * sme_get_current_roam_state() - |
| * get current roam state |
| * |
| * mac_handle - The handle returned by mac_open. |
| * sessionId - Session Identifier |
| * Return uint32_t - current roam state |
| */ |
| uint32_t sme_get_current_roam_state(mac_handle_t mac_handle, uint8_t sessionId) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.curState[sessionId]; |
| } |
| |
| /* |
| * sme_get_current_roam_sub_state() - |
| * \brief get neighbor roam sub state |
| * |
| * mac_handle - The handle returned by mac_open. |
| * sessionId - Session Identifier |
| * Return uint32_t - current roam sub state |
| */ |
| uint32_t sme_get_current_roam_sub_state(mac_handle_t mac_handle, |
| uint8_t sessionId) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.curSubState[sessionId]; |
| } |
| |
| /* |
| * sme_get_lim_sme_state() - |
| * get Lim Sme state |
| * |
| * mac_handle - The handle returned by mac_open. |
| * Return uint32_t - Lim Sme state |
| */ |
| uint32_t sme_get_lim_sme_state(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->lim.gLimSmeState; |
| } |
| |
| /* |
| * sme_get_lim_mlm_state() - |
| * get Lim Mlm state |
| * |
| * mac_handle - The handle returned by mac_open. |
| * Return uint32_t - Lim Mlm state |
| */ |
| uint32_t sme_get_lim_mlm_state(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->lim.gLimMlmState; |
| } |
| |
| /* |
| * sme_is_lim_session_valid() - |
| * is Lim session valid |
| * |
| * mac_handle - The handle returned by mac_open. |
| * sessionId - Session Identifier |
| * Return bool - true or false |
| */ |
| bool sme_is_lim_session_valid(mac_handle_t mac_handle, uint8_t sessionId) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (sessionId > pMac->lim.maxBssId) |
| return false; |
| |
| return pMac->lim.gpSession[sessionId].valid; |
| } |
| |
| /* |
| * sme_get_lim_sme_session_state() - |
| * get Lim Sme session state |
| * |
| * mac_handle - The handle returned by mac_open. |
| * sessionId - Session Identifier |
| * Return uint32_t - Lim Sme session state |
| */ |
| uint32_t sme_get_lim_sme_session_state(mac_handle_t mac_handle, |
| uint8_t sessionId) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->lim.gpSession[sessionId].limSmeState; |
| } |
| |
| /* |
| * sme_get_lim_mlm_session_state() - |
| * \brief get Lim Mlm session state |
| * |
| * mac_handle - The handle returned by mac_open. |
| * sessionId - Session Identifier |
| * Return uint32_t - Lim Mlm session state |
| */ |
| uint32_t sme_get_lim_mlm_session_state(mac_handle_t mac_handle, |
| uint8_t sessionId) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->lim.gpSession[sessionId].limMlmState; |
| } |
| |
| /* |
| * sme_get_neighbor_scan_max_chan_time() - |
| * get neighbor scan max channel time |
| * |
| * mac_handle - The handle returned by mac_open. |
| * sessionId - Session Identifier |
| * Return uint16_t - channel max time value |
| */ |
| uint16_t sme_get_neighbor_scan_max_chan_time(mac_handle_t mac_handle, |
| uint8_t sessionId) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (sessionId >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), sessionId); |
| return 0; |
| } |
| |
| return pMac->roam.neighborRoamInfo[sessionId].cfgParams. |
| maxChannelScanTime; |
| } |
| |
| /* |
| * sme_set_neighbor_scan_period() - |
| * Update nNeighborScanPeriod |
| * This function is called through dynamic setConfig callback function |
| * to configure nNeighborScanPeriod |
| * Usage: adb shell iwpriv wlan0 setConfig |
| * nNeighborScanPeriod=[0 .. 1000] |
| * |
| * mac_handle - HAL handle for device |
| * sessionId - Session Identifier |
| * nNeighborScanPeriod - neighbor scan period |
| * Return Success or failure |
| */ |
| QDF_STATUS sme_set_neighbor_scan_period(mac_handle_t mac_handle, |
| uint8_t sessionId, |
| const uint16_t nNeighborScanPeriod) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| struct csr_neighbor_roamconfig *pNeighborRoamConfig = NULL; |
| tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; |
| |
| if (sessionId >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), sessionId); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| pNeighborRoamConfig = |
| &pMac->roam.configParam.neighborRoamConfig; |
| pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "LFR runtime successfully set neighbor scan period to %d - old value is %d - roam state is %s", |
| nNeighborScanPeriod, |
| pMac->roam.configParam.neighborRoamConfig. |
| nNeighborScanTimerPeriod, |
| mac_trace_get_neighbour_roam_state(pMac->roam. |
| neighborRoamInfo |
| [sessionId]. |
| neighborRoamState)); |
| pNeighborRoamConfig->nNeighborScanTimerPeriod = |
| nNeighborScanPeriod; |
| pNeighborRoamInfo->cfgParams.neighborScanPeriod = |
| nNeighborScanPeriod; |
| |
| if (pMac->roam.configParam.isRoamOffloadScanEnabled) { |
| csr_roam_offload_scan(pMac, sessionId, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, |
| REASON_SCAN_HOME_TIME_CHANGED); |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_get_neighbor_scan_period() - |
| * get neighbor scan period |
| * |
| * mac_handle - The handle returned by mac_open. |
| * sessionId - Session Identifier |
| * Return uint16_t - neighbor scan period |
| */ |
| uint16_t sme_get_neighbor_scan_period(mac_handle_t mac_handle, |
| uint8_t sessionId) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (sessionId >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), sessionId); |
| return 0; |
| } |
| |
| return pMac->roam.neighborRoamInfo[sessionId].cfgParams. |
| neighborScanPeriod; |
| } |
| |
| /** |
| * sme_set_neighbor_scan_min_period() - Update neighbor_scan_min_period |
| * This function is called through dynamic setConfig callback function |
| * to configure neighbor_scan_min_period |
| * |
| * @hal - HAL handle for device |
| * @session_id - Session Identifier |
| * @neighbor_scan_min_period - neighbor scan min period |
| * |
| * Return - QDF_STATUS |
| */ |
| QDF_STATUS sme_set_neighbor_scan_min_period(mac_handle_t hal, |
| uint8_t session_id, |
| const uint16_t |
| neighbor_scan_min_period) |
| { |
| tpAniSirGlobal pmac = PMAC_STRUCT(hal); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| struct csr_neighbor_roamconfig *p_neighbor_roam_config = NULL; |
| tpCsrNeighborRoamControlInfo p_neighbor_roam_info = NULL; |
| |
| if (session_id >= CSR_ROAM_SESSION_MAX) { |
| sme_err("Invalid sme session id: %d", session_id); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| status = sme_acquire_global_lock(&pmac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| p_neighbor_roam_config = |
| &pmac->roam.configParam.neighborRoamConfig; |
| p_neighbor_roam_info = &pmac-> |
| roam.neighborRoamInfo[session_id]; |
| sme_debug("LFR:set neighbor scan min period, old:%d, " |
| "new: %d, state: %s", |
| pmac->roam.configParam.neighborRoamConfig. |
| neighbor_scan_min_timer_period, |
| neighbor_scan_min_period, |
| mac_trace_get_neighbour_roam_state(pmac->roam. |
| neighborRoamInfo[session_id]. |
| neighborRoamState)); |
| p_neighbor_roam_config->neighbor_scan_min_timer_period = |
| neighbor_scan_min_period; |
| p_neighbor_roam_info->cfgParams.neighbor_scan_min_period = |
| neighbor_scan_min_period; |
| sme_release_global_lock(&pmac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_get_roam_rssi_diff() - get Roam rssi diff |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * Return uint16_t - Rssi diff value |
| */ |
| uint8_t sme_get_roam_rssi_diff(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.RoamRssiDiff; |
| } |
| |
| /** |
| * sme_change_roam_scan_channel_list() - to change scan channel list |
| * @mac_handle: pointer HAL handle returned by mac_open |
| * @sessionId: sme session id |
| * @pChannelList: Output channel list |
| * @numChannels: Output number of channels |
| * |
| * This routine is called to Change roam scan channel list. |
| * This is a synchronous call |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_change_roam_scan_channel_list(mac_handle_t mac_handle, |
| uint8_t sessionId, |
| uint8_t *pChannelList, |
| uint8_t numChannels) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; |
| uint8_t oldChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN * 2] = { 0 }; |
| uint8_t newChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN * 2] = { 0 }; |
| uint8_t i = 0, j = 0; |
| tCsrChannelInfo *chan_info; |
| |
| if (sessionId >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), sessionId); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("Failed to acquire SME lock"); |
| return status; |
| } |
| chan_info = &pNeighborRoamInfo->cfgParams.channelInfo; |
| |
| if (NULL != chan_info->ChannelList) { |
| for (i = 0; i < chan_info->numOfChannels; i++) { |
| if (j < sizeof(oldChannelList)) |
| j += snprintf(oldChannelList + j, |
| sizeof(oldChannelList) - |
| j, "%d", |
| chan_info->ChannelList[i]); |
| else |
| break; |
| } |
| } |
| csr_flush_cfg_bg_scan_roam_channel_list(pMac, sessionId); |
| csr_create_bg_scan_roam_channel_list(pMac, sessionId, pChannelList, |
| numChannels); |
| sme_set_roam_scan_control(mac_handle, sessionId, 1); |
| if (NULL != chan_info->ChannelList) { |
| j = 0; |
| for (i = 0; i < chan_info->numOfChannels; i++) { |
| if (j < sizeof(newChannelList)) |
| j += snprintf(newChannelList + j, |
| sizeof(newChannelList) - |
| j, " %d", |
| chan_info->ChannelList[i]); |
| else |
| break; |
| } |
| } |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "LFR runtime successfully set roam scan channels to %s - old value is %s - roam state is %d", |
| newChannelList, oldChannelList, |
| pMac->roam.neighborRoamInfo[sessionId].neighborRoamState); |
| |
| if (pMac->roam.configParam.isRoamOffloadScanEnabled) |
| csr_roam_offload_scan(pMac, sessionId, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, |
| REASON_CHANNEL_LIST_CHANGED); |
| |
| sme_release_global_lock(&pMac->sme); |
| return status; |
| } |
| |
| /** |
| * sme_get_roam_scan_channel_list() - To get roam scan channel list |
| * @mac_handle: HAL pointer |
| * @pChannelList: Output channel list |
| * @pNumChannels: Output number of channels |
| * @sessionId: Session Identifier |
| * |
| * To get roam scan channel list This is a synchronous call |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_get_roam_scan_channel_list(mac_handle_t mac_handle, |
| uint8_t *pChannelList, uint8_t *pNumChannels, |
| uint8_t sessionId) |
| { |
| int i = 0; |
| uint8_t *pOutPtr = pChannelList; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| if (sessionId >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), sessionId); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| return status; |
| if (NULL == pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_WARN, |
| FL("Roam Scan channel list is NOT yet initialized")); |
| *pNumChannels = 0; |
| sme_release_global_lock(&pMac->sme); |
| return status; |
| } |
| |
| *pNumChannels = pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels; |
| for (i = 0; i < (*pNumChannels); i++) |
| pOutPtr[i] = |
| pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i]; |
| |
| pOutPtr[i] = '\0'; |
| sme_release_global_lock(&pMac->sme); |
| return status; |
| } |
| |
| /* |
| * sme_get_is_ese_feature_enabled() - get ESE feature enabled or not |
| * This is a synchronuous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * Return true (1) - if the ESE feature is enabled |
| * false (0) - if feature is disabled (compile or runtime) |
| */ |
| bool sme_get_is_ese_feature_enabled(mac_handle_t mac_handle) |
| { |
| #ifdef FEATURE_WLAN_ESE |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return csr_roam_is_ese_ini_feature_enabled(pMac); |
| #else |
| return false; |
| #endif |
| } |
| |
| /* |
| * sme_get_wes_mode() - get WES Mode |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open |
| * Return uint8_t - WES Mode Enabled(1)/Disabled(0) |
| */ |
| bool sme_get_wes_mode(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.isWESModeEnabled; |
| } |
| |
| /* |
| * sme_get_roam_scan_control() - get scan control |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * Return bool - Enabled(1)/Disabled(0) |
| */ |
| bool sme_get_roam_scan_control(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.nRoamScanControl; |
| } |
| |
| /* |
| * sme_get_is_lfr_feature_enabled() - get LFR feature enabled or not |
| * This is a synchronuous call |
| * mac_handle - The handle returned by mac_open. |
| * Return true (1) - if the feature is enabled |
| * false (0) - if feature is disabled (compile or runtime) |
| */ |
| bool sme_get_is_lfr_feature_enabled(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.isFastRoamIniFeatureEnabled; |
| } |
| |
| /* |
| * sme_get_is_ft_feature_enabled() - get FT feature enabled or not |
| * This is a synchronuous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * Return true (1) - if the feature is enabled |
| * false (0) - if feature is disabled (compile or runtime) |
| */ |
| bool sme_get_is_ft_feature_enabled(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.isFastTransitionEnabled; |
| } |
| |
| /** |
| * sme_is_feature_supported_by_fw() - check if feature is supported by FW |
| * @feature: enum value of requested feature. |
| * |
| * Retrun: 1 if supported; 0 otherwise |
| */ |
| bool sme_is_feature_supported_by_fw(enum cap_bitmap feature) |
| { |
| return IS_FEATURE_SUPPORTED_BY_FW(feature); |
| } |
| |
| QDF_STATUS sme_get_link_speed(mac_handle_t mac_handle, tSirLinkSpeedInfo *lsReq, |
| void *plsContext, |
| void (*pCallbackfn)(tSirLinkSpeedInfo *indParam, |
| void *pContext)) |
| { |
| |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac; |
| void *wma_handle; |
| |
| if (!mac_handle || !pCallbackfn || !lsReq) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid parameter")); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "wma handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| pMac = PMAC_STRUCT(mac_handle); |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_STATUS_SUCCESS != status) { |
| sme_err("Failed to acquire global lock"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| pMac->sme.pLinkSpeedCbContext = plsContext; |
| pMac->sme.pLinkSpeedIndCb = pCallbackfn; |
| status = wma_get_link_speed(wma_handle, lsReq); |
| sme_release_global_lock(&pMac->sme); |
| return status; |
| } |
| |
| QDF_STATUS sme_get_peer_stats(tpAniSirGlobal mac, |
| struct sir_peer_info_req req) |
| { |
| QDF_STATUS qdf_status; |
| struct scheduler_msg message = {0}; |
| |
| qdf_status = sme_acquire_global_lock(&mac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| sme_debug("Failed to get Lock"); |
| return qdf_status; |
| } |
| /* serialize the req through MC thread */ |
| message.bodyptr = qdf_mem_malloc(sizeof(req)); |
| if (!message.bodyptr) { |
| sme_release_global_lock(&mac->sme); |
| return QDF_STATUS_E_NOMEM; |
| } |
| qdf_mem_copy(message.bodyptr, &req, sizeof(req)); |
| message.type = WMA_GET_PEER_INFO; |
| message.reserved = 0; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Post get peer info msg fail", __func__); |
| qdf_mem_free(message.bodyptr); |
| qdf_status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&mac->sme); |
| return qdf_status; |
| } |
| |
| QDF_STATUS sme_get_peer_info(mac_handle_t hal, struct sir_peer_info_req req, |
| void *context, |
| void (*callbackfn)(struct sir_peer_info_resp *param, |
| void *pcontext)) |
| { |
| |
| QDF_STATUS status; |
| QDF_STATUS qdf_status; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| struct scheduler_msg message = {0}; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| if (NULL == callbackfn) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Indication Call back is NULL", |
| __func__); |
| sme_release_global_lock(&mac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| mac->sme.pget_peer_info_ind_cb = callbackfn; |
| mac->sme.pget_peer_info_cb_context = context; |
| |
| /* serialize the req through MC thread */ |
| message.bodyptr = qdf_mem_malloc(sizeof(req)); |
| if (!message.bodyptr) { |
| sme_release_global_lock(&mac->sme); |
| return QDF_STATUS_E_NOMEM; |
| } |
| qdf_mem_copy(message.bodyptr, &req, sizeof(req)); |
| message.type = WMA_GET_PEER_INFO; |
| message.reserved = 0; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Post get peer info msg fail", __func__); |
| qdf_mem_free(message.bodyptr); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&mac->sme); |
| } |
| return status; |
| } |
| |
| QDF_STATUS sme_get_peer_info_ext(mac_handle_t hal, |
| struct sir_peer_info_ext_req *req, |
| void *context, |
| void (*callbackfn)(struct sir_peer_info_ext_resp *param, |
| void *pcontext)) |
| { |
| QDF_STATUS status; |
| QDF_STATUS qdf_status; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| struct scheduler_msg message = {0}; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| if (NULL == callbackfn) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Indication Call back is NULL", |
| __func__); |
| sme_release_global_lock(&mac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| mac->sme.pget_peer_info_ext_ind_cb = callbackfn; |
| mac->sme.pget_peer_info_ext_cb_context = context; |
| |
| /* serialize the req through MC thread */ |
| message.bodyptr = |
| qdf_mem_malloc(sizeof(struct sir_peer_info_ext_req)); |
| if (!message.bodyptr) { |
| sme_release_global_lock(&mac->sme); |
| return QDF_STATUS_E_NOMEM; |
| } |
| qdf_mem_copy(message.bodyptr, |
| req, |
| sizeof(struct sir_peer_info_ext_req)); |
| message.type = WMA_GET_PEER_INFO_EXT; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Post get rssi msg fail", __func__); |
| qdf_mem_free(message.bodyptr); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&mac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * SME API to enable/disable WLAN driver initiated SSR |
| */ |
| void sme_update_enable_ssr(mac_handle_t mac_handle, bool enableSSR) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| sme_debug("SSR level is changed %d", enableSSR); |
| /* not serializing this message, as this is only going |
| * to set a variable in WMA/WDI |
| */ |
| WMA_SetEnableSSR(enableSSR); |
| sme_release_global_lock(&pMac->sme); |
| } |
| } |
| |
| /*convert the ini value to the ENUM used in csr and MAC for CB state*/ |
| ePhyChanBondState sme_get_cb_phy_state_from_cb_ini_value(uint32_t cb_ini_value) |
| { |
| return csr_convert_cb_ini_value_to_phy_cb_state(cb_ini_value); |
| } |
| |
| /* |
| * sme_set_curr_device_mode() - Sets the current operating device mode. |
| * |
| * mac_handle - The handle returned by mac_open. |
| * currDeviceMode - Current operating device mode. |
| */ |
| void sme_set_curr_device_mode(mac_handle_t mac_handle, |
| enum QDF_OPMODE currDeviceMode) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| pMac->sme.currDeviceMode = currDeviceMode; |
| } |
| |
| /* |
| * sme_handoff_request() - a wrapper function to Request a handoff from CSR. |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open |
| * sessionId - Session Identifier |
| * pHandoffInfo - info provided by HDD with the handoff request (namely: |
| * BSSID, channel etc.) |
| * Return QDF_STATUS_SUCCESS - SME passed the request to CSR successfully. |
| * Other status means SME is failed to send the request. |
| */ |
| |
| QDF_STATUS sme_handoff_request(mac_handle_t mac_handle, |
| uint8_t sessionId, |
| tCsrHandoffRequest *pHandoffInfo) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: invoked", __func__); |
| status = csr_handoff_request(pMac, sessionId, pHandoffInfo); |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * SME API to check if there is any infra station or |
| * P2P client is connected |
| */ |
| QDF_STATUS sme_is_sta_p2p_client_connected(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (csr_is_infra_connected(pMac)) |
| return QDF_STATUS_SUCCESS; |
| |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| /** |
| * sme_add_periodic_tx_ptrn() - Add Periodic TX Pattern |
| * @hal: global hal handle |
| * @addPeriodicTxPtrnParams: request message |
| * |
| * Return: QDF_STATUS enumeration |
| */ |
| QDF_STATUS |
| sme_add_periodic_tx_ptrn(mac_handle_t hal, |
| struct sSirAddPeriodicTxPtrn *addPeriodicTxPtrnParams) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| struct sSirAddPeriodicTxPtrn *req_msg; |
| struct scheduler_msg msg = {0}; |
| |
| SME_ENTER(); |
| |
| req_msg = qdf_mem_malloc(sizeof(*req_msg)); |
| if (!req_msg) |
| return QDF_STATUS_E_NOMEM; |
| |
| *req_msg = *addPeriodicTxPtrnParams; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("sme_acquire_global_lock failed!(status=%d)", |
| status); |
| qdf_mem_free(req_msg); |
| return status; |
| } |
| |
| /* Serialize the req through MC thread */ |
| msg.bodyptr = req_msg; |
| msg.type = WMA_ADD_PERIODIC_TX_PTRN_IND; |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| NO_SESSION, msg.type)); |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("scheduler_post_msg failed!(err=%d)", |
| status); |
| qdf_mem_free(req_msg); |
| } |
| sme_release_global_lock(&mac->sme); |
| return status; |
| } |
| |
| /** |
| * sme_del_periodic_tx_ptrn() - Delete Periodic TX Pattern |
| * @hal: global hal handle |
| * @delPeriodicTxPtrnParams: request message |
| * |
| * Return: QDF_STATUS enumeration |
| */ |
| QDF_STATUS |
| sme_del_periodic_tx_ptrn(mac_handle_t hal, |
| struct sSirDelPeriodicTxPtrn *delPeriodicTxPtrnParams) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| struct sSirDelPeriodicTxPtrn *req_msg; |
| struct scheduler_msg msg = {0}; |
| |
| SME_ENTER(); |
| |
| req_msg = qdf_mem_malloc(sizeof(*req_msg)); |
| if (!req_msg) |
| return QDF_STATUS_E_NOMEM; |
| |
| *req_msg = *delPeriodicTxPtrnParams; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("sme_acquire_global_lock failed!(status=%d)", |
| status); |
| qdf_mem_free(req_msg); |
| return status; |
| } |
| |
| /* Serialize the req through MC thread */ |
| msg.bodyptr = req_msg; |
| msg.type = WMA_DEL_PERIODIC_TX_PTRN_IND; |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| NO_SESSION, msg.type)); |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("scheduler_post_msg failed!(err=%d)", |
| status); |
| qdf_mem_free(req_msg); |
| } |
| sme_release_global_lock(&mac->sme); |
| return status; |
| } |
| |
| #ifdef FEATURE_WLAN_RMC |
| /* |
| * sme_enable_rmc() - enables RMC |
| * @mac_handle : Pointer to global HAL handle |
| * @sessionId : Session ID |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_enable_rmc(mac_handle_t mac_handle, uint32_t sessionId) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| |
| SME_ENTER(); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| message.bodyptr = NULL; |
| message.type = WMA_RMC_ENABLE_IND; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: failed to post message to WMA", |
| __func__); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_disable_rmc() - disables RMC |
| * @mac_handle : Pointer to global HAL handle |
| * @sessionId : Session ID |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_disable_rmc(mac_handle_t mac_handle, uint32_t sessionId) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| |
| SME_ENTER(); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| message.bodyptr = NULL; |
| message.type = WMA_RMC_DISABLE_IND; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: failed to post message to WMA", |
| __func__); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_send_rmc_action_period() - sends RMC action period param to target |
| * @mac_handle : Pointer to global HAL handle |
| * @sessionId : Session ID |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_send_rmc_action_period(mac_handle_t mac_handle, |
| uint32_t sessionId) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| message.bodyptr = NULL; |
| message.type = WMA_RMC_ACTION_PERIOD_IND; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: failed to post message to WMA", |
| __func__); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| #endif /* FEATURE_WLAN_RMC */ |
| |
| /* |
| * sme_request_ibss_peer_info() - request ibss peer info |
| * @mac_handle : Pointer to global HAL handle |
| * @pUserData : Pointer to user data |
| * @peerInfoCbk : Peer info callback |
| * @allPeerInfoReqd : All peer info required or not |
| * @staIdx : sta index |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_request_ibss_peer_info(mac_handle_t mac_handle, void *pUserData, |
| pIbssPeerInfoCb peerInfoCbk, |
| bool allPeerInfoReqd, uint8_t staIdx) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| tSirIbssGetPeerInfoReqParams *pIbssInfoReqParams; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| pMac->sme.peerInfoParams.peerInfoCbk = peerInfoCbk; |
| pMac->sme.peerInfoParams.pUserData = pUserData; |
| |
| pIbssInfoReqParams = (tSirIbssGetPeerInfoReqParams *) |
| qdf_mem_malloc(sizeof(tSirIbssGetPeerInfoReqParams)); |
| if (!pIbssInfoReqParams) { |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_NOMEM; |
| } |
| pIbssInfoReqParams->allPeerInfoReqd = allPeerInfoReqd; |
| pIbssInfoReqParams->staIdx = staIdx; |
| |
| message.type = WMA_GET_IBSS_PEER_INFO_REQ; |
| message.bodyptr = pIbssInfoReqParams; |
| message.reserved = 0; |
| |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (QDF_STATUS_SUCCESS != qdf_status) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Post WMA_GET_IBSS_PEER_INFO_REQ MSG failed", |
| __func__); |
| qdf_mem_free(pIbssInfoReqParams); |
| qdf_status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return qdf_status; |
| } |
| |
| /* |
| * sme_send_cesium_enable_ind() - |
| * Used to send proprietary cesium enable indication to fw |
| * |
| * mac_handle |
| * sessionId |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_send_cesium_enable_ind(mac_handle_t mac_handle, |
| uint32_t sessionId) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| message.bodyptr = NULL; |
| message.type = WMA_IBSS_CESIUM_ENABLE_IND; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: failed to post message to WMA", |
| __func__); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_set_wlm_latency_level(mac_handle_t hal, uint16_t session_id, |
| uint16_t latency_level) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct wlm_latency_level_param params; |
| void *wma = cds_get_context(QDF_MODULE_ID_WMA); |
| |
| if (!wma) |
| return QDF_STATUS_E_FAILURE; |
| |
| if (!mac_ctx->roam.configParam.wlm_latency_enable) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: WLM latency level setting is disabled", |
| __func__); |
| return QDF_STATUS_E_FAILURE; |
| } |
| if (!wma) { |
| sme_err("wma is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| params.wlm_latency_level = latency_level; |
| params.wlm_latency_flags = |
| mac_ctx->roam.configParam.wlm_latency_flags[latency_level]; |
| params.vdev_id = session_id; |
| |
| status = wma_set_wlm_latency_level(wma, ¶ms); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: failed to set latency level", |
| __func__); |
| |
| return status; |
| } |
| |
| void sme_get_command_q_status(mac_handle_t mac_handle) |
| { |
| tSmeCmd *pTempCmd = NULL; |
| tListElem *pEntry; |
| tpAniSirGlobal pMac; |
| |
| if (NULL != mac_handle) { |
| pMac = PMAC_STRUCT(mac_handle); |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Invalid mac_handle pointer", __func__); |
| return; |
| } |
| pEntry = csr_nonscan_active_ll_peek_head(pMac, LL_ACCESS_LOCK); |
| if (pEntry) |
| pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link); |
| |
| sme_err("WLAN_BUG_RCA: Currently smeCmdActiveList has command (0x%X)", |
| (pTempCmd) ? pTempCmd->command : eSmeNoCommand); |
| if (pTempCmd) { |
| if (eSmeCsrCommandMask & pTempCmd->command) |
| /* CSR command is stuck. See what the reason code is |
| * for that command |
| */ |
| dump_csr_command_info(pMac, pTempCmd); |
| } /* if(pTempCmd) */ |
| |
| sme_err("Currently smeCmdPendingList has %d commands", |
| csr_nonscan_pending_ll_count(pMac)); |
| |
| } |
| |
| #ifdef WLAN_FEATURE_DSRC |
| /** |
| * copy_sir_ocb_config() - Performs deep copy of an OCB configuration |
| * @src: the source configuration |
| * |
| * Return: pointer to the copied OCB configuration |
| */ |
| static struct sir_ocb_config *sme_copy_sir_ocb_config( |
| struct sir_ocb_config *src) |
| { |
| struct sir_ocb_config *dst; |
| uint32_t length; |
| void *cursor; |
| |
| length = sizeof(*src) + |
| src->channel_count * sizeof(*src->channels) + |
| src->schedule_size * sizeof(*src->schedule) + |
| src->dcc_ndl_chan_list_len + |
| src->dcc_ndl_active_state_list_len; |
| |
| dst = qdf_mem_malloc(length); |
| if (!dst) |
| return NULL; |
| |
| *dst = *src; |
| |
| cursor = dst; |
| cursor += sizeof(*dst); |
| dst->channels = cursor; |
| cursor += src->channel_count * sizeof(*src->channels); |
| qdf_mem_copy(dst->channels, src->channels, |
| src->channel_count * sizeof(*src->channels)); |
| dst->schedule = cursor; |
| cursor += src->schedule_size * sizeof(*src->schedule); |
| qdf_mem_copy(dst->schedule, src->schedule, |
| src->schedule_size * sizeof(*src->schedule)); |
| dst->dcc_ndl_chan_list = cursor; |
| cursor += src->dcc_ndl_chan_list_len; |
| qdf_mem_copy(dst->dcc_ndl_chan_list, src->dcc_ndl_chan_list, |
| src->dcc_ndl_chan_list_len); |
| dst->dcc_ndl_active_state_list = cursor; |
| cursor += src->dcc_ndl_active_state_list_len; |
| qdf_mem_copy(dst->dcc_ndl_active_state_list, |
| src->dcc_ndl_active_state_list, |
| src->dcc_ndl_active_state_list_len); |
| return dst; |
| } |
| |
| /** |
| * sme_ocb_set_config() - Set the OCB configuration |
| * @mac_handle: reference to the HAL |
| * @context: the context of the call |
| * @callback: the callback to hdd |
| * @config: the OCB configuration |
| * |
| * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure |
| */ |
| QDF_STATUS sme_ocb_set_config(mac_handle_t mac_handle, void *context, |
| ocb_callback callback, |
| struct sir_ocb_config *config) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg msg = {0}; |
| struct sir_ocb_config *msg_body; |
| |
| /* Lock the SME structure */ |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| return status; |
| |
| /* |
| * Check if there is a pending request and return an error if one |
| * exists |
| */ |
| if (pMac->sme.ocb_set_config_callback) { |
| status = QDF_STATUS_E_BUSY; |
| goto end; |
| } |
| |
| msg_body = sme_copy_sir_ocb_config(config); |
| |
| if (!msg_body) { |
| status = QDF_STATUS_E_NOMEM; |
| goto end; |
| } |
| |
| msg.type = WMA_OCB_SET_CONFIG_CMD; |
| msg.bodyptr = msg_body; |
| |
| /* Set the request callback and context */ |
| pMac->sme.ocb_set_config_callback = callback; |
| pMac->sme.ocb_set_config_context = context; |
| |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Error posting message to WDA: %d"), status); |
| pMac->sme.ocb_set_config_callback = callback; |
| pMac->sme.ocb_set_config_context = context; |
| qdf_mem_free(msg_body); |
| goto end; |
| } |
| |
| end: |
| sme_release_global_lock(&pMac->sme); |
| |
| return status; |
| } |
| |
| /** |
| * sme_ocb_set_utc_time() - Set the OCB UTC time |
| * @mac_handle: reference to the HAL |
| * @utc: the UTC time struct |
| * |
| * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure |
| */ |
| QDF_STATUS sme_ocb_set_utc_time(mac_handle_t mac_handle, |
| struct sir_ocb_utc *utc) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg msg = {0}; |
| struct sir_ocb_utc *sme_utc; |
| |
| /* Lock the SME structure */ |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| return status; |
| |
| sme_utc = qdf_mem_malloc(sizeof(*sme_utc)); |
| if (!sme_utc) { |
| status = QDF_STATUS_E_NOMEM; |
| goto end; |
| } |
| *sme_utc = *utc; |
| |
| msg.type = WMA_OCB_SET_UTC_TIME_CMD; |
| msg.reserved = 0; |
| msg.bodyptr = sme_utc; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Not able to post message to WDA")); |
| qdf_mem_free(utc); |
| goto end; |
| } |
| |
| end: |
| sme_release_global_lock(&pMac->sme); |
| |
| return status; |
| } |
| |
| /** |
| * sme_ocb_start_timing_advert() - Start sending timing advert frames |
| * @mac_handle: reference to the HAL |
| * @timing_advert: the timing advertisement struct |
| * |
| * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure |
| */ |
| QDF_STATUS sme_ocb_start_timing_advert(mac_handle_t mac_handle, |
| struct sir_ocb_timing_advert *timing_advert) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg msg = {0}; |
| void *buf; |
| struct sir_ocb_timing_advert *sme_timing_advert; |
| |
| /* Lock the SME structure */ |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| return status; |
| |
| buf = qdf_mem_malloc(sizeof(*sme_timing_advert) + |
| timing_advert->template_length); |
| if (!buf) { |
| status = QDF_STATUS_E_NOMEM; |
| goto end; |
| } |
| |
| sme_timing_advert = (struct sir_ocb_timing_advert *)buf; |
| *sme_timing_advert = *timing_advert; |
| sme_timing_advert->template_value = buf + sizeof(*sme_timing_advert); |
| qdf_mem_copy(sme_timing_advert->template_value, |
| timing_advert->template_value, timing_advert->template_length); |
| |
| msg.type = WMA_OCB_START_TIMING_ADVERT_CMD; |
| msg.reserved = 0; |
| msg.bodyptr = buf; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Not able to post msg to WDA")); |
| goto end; |
| } |
| |
| end: |
| sme_release_global_lock(&pMac->sme); |
| |
| return status; |
| } |
| |
| /** |
| * sme_ocb_stop_timing_advert() - Stop sending timing advert frames on a channel |
| * @mac_handle: reference to the HAL |
| * @timing_advert: the timing advertisement struct |
| * |
| * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure |
| */ |
| QDF_STATUS sme_ocb_stop_timing_advert(mac_handle_t mac_handle, |
| struct sir_ocb_timing_advert *timing_advert) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg msg = {0}; |
| struct sir_ocb_timing_advert *sme_timing_advert; |
| |
| /* Lock the SME structure */ |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| return status; |
| |
| sme_timing_advert = qdf_mem_malloc(sizeof(*timing_advert)); |
| if (!sme_timing_advert) { |
| status = QDF_STATUS_E_NOMEM; |
| goto end; |
| } |
| *sme_timing_advert = *timing_advert; |
| |
| msg.type = WMA_OCB_STOP_TIMING_ADVERT_CMD; |
| msg.reserved = 0; |
| msg.bodyptr = sme_timing_advert; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Not able to post msg to WDA")); |
| goto end; |
| } |
| |
| end: |
| sme_release_global_lock(&pMac->sme); |
| |
| return status; |
| } |
| |
| /** |
| * sme_ocb_gen_timing_advert_frame() - generate TA frame and populate the buffer |
| * @mac_handle: reference to the HAL |
| * @self_addr: the self MAC address |
| * @buf: the buffer that will contain the frame |
| * @timestamp_offset: return for the offset of the timestamp field |
| * @time_value_offset: return for the time_value field in the TA IE |
| * |
| * Return: the length of the buffer. |
| */ |
| int sme_ocb_gen_timing_advert_frame(mac_handle_t mac_handle, |
| tSirMacAddr self_addr, uint8_t **buf, |
| uint32_t *timestamp_offset, |
| uint32_t *time_value_offset) |
| { |
| int template_length; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| |
| template_length = sch_gen_timing_advert_frame(mac_ctx, self_addr, buf, |
| timestamp_offset, |
| time_value_offset); |
| return template_length; |
| } |
| /** |
| * sme_ocb_get_tsf_timer() - Get the TSF timer value |
| * @mac_handle: reference to the HAL |
| * @context: the context of the call |
| * @callback: the callback to hdd |
| * @request: the TSF timer request |
| * |
| * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure |
| */ |
| QDF_STATUS sme_ocb_get_tsf_timer(mac_handle_t mac_handle, void *context, |
| ocb_callback callback, |
| struct sir_ocb_get_tsf_timer *request) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg msg = {0}; |
| struct sir_ocb_get_tsf_timer *msg_body; |
| |
| /* Lock the SME structure */ |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| return status; |
| |
| /* Allocate memory for the WMI request, and copy the parameter */ |
| msg_body = qdf_mem_malloc(sizeof(*msg_body)); |
| if (!msg_body) { |
| status = QDF_STATUS_E_NOMEM; |
| goto end; |
| } |
| *msg_body = *request; |
| |
| msg.type = WMA_OCB_GET_TSF_TIMER_CMD; |
| msg.bodyptr = msg_body; |
| |
| /* Set the request callback and the context */ |
| pMac->sme.ocb_get_tsf_timer_callback = callback; |
| pMac->sme.ocb_get_tsf_timer_context = context; |
| |
| /* Post the message to WDA */ |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Error posting message to WDA: %d"), status); |
| pMac->sme.ocb_get_tsf_timer_callback = NULL; |
| pMac->sme.ocb_get_tsf_timer_context = NULL; |
| qdf_mem_free(msg_body); |
| goto end; |
| } |
| |
| end: |
| sme_release_global_lock(&pMac->sme); |
| |
| return status; |
| } |
| |
| /** |
| * sme_dcc_get_stats() - Get the DCC stats |
| * @mac_handle: reference to the HAL |
| * @context: the context of the call |
| * @callback: the callback to hdd |
| * @request: the get DCC stats request |
| * |
| * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure |
| */ |
| QDF_STATUS sme_dcc_get_stats(mac_handle_t mac_handle, void *context, |
| ocb_callback callback, |
| struct sir_dcc_get_stats *request) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg msg = {0}; |
| struct sir_dcc_get_stats *msg_body; |
| |
| /* Lock the SME structure */ |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| return status; |
| |
| /* Allocate memory for the WMI request, and copy the parameter */ |
| msg_body = qdf_mem_malloc(sizeof(*msg_body) + |
| request->request_array_len); |
| if (!msg_body) { |
| status = QDF_STATUS_E_NOMEM; |
| goto end; |
| } |
| *msg_body = *request; |
| msg_body->request_array = (void *)msg_body + sizeof(*msg_body); |
| qdf_mem_copy(msg_body->request_array, request->request_array, |
| request->request_array_len); |
| |
| msg.type = WMA_DCC_GET_STATS_CMD; |
| msg.bodyptr = msg_body; |
| |
| /* Set the request callback and context */ |
| pMac->sme.dcc_get_stats_callback = callback; |
| pMac->sme.dcc_get_stats_context = context; |
| |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Error posting message to WDA: %d"), status); |
| pMac->sme.dcc_get_stats_callback = callback; |
| pMac->sme.dcc_get_stats_context = context; |
| qdf_mem_free(msg_body); |
| goto end; |
| } |
| |
| end: |
| sme_release_global_lock(&pMac->sme); |
| |
| return status; |
| } |
| |
| /** |
| * sme_dcc_clear_stats() - Clear the DCC stats |
| * @mac_handle: reference to the HAL |
| * @vdev_id: vdev id for OCB interface |
| * @dcc_stats_bitmap: the entries in the stats to clear |
| * |
| * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure |
| */ |
| QDF_STATUS sme_dcc_clear_stats(mac_handle_t mac_handle, uint32_t vdev_id, |
| uint32_t dcc_stats_bitmap) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg msg = {0}; |
| struct sir_dcc_clear_stats *request; |
| |
| /* Lock the SME structure */ |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| return status; |
| |
| request = qdf_mem_malloc(sizeof(struct sir_dcc_clear_stats)); |
| if (!request) { |
| status = QDF_STATUS_E_NOMEM; |
| goto end; |
| } |
| |
| request->vdev_id = vdev_id; |
| request->dcc_stats_bitmap = dcc_stats_bitmap; |
| |
| msg.type = WMA_DCC_CLEAR_STATS_CMD; |
| msg.bodyptr = request; |
| |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Not able to post msg to WDA")); |
| qdf_mem_free(request); |
| goto end; |
| } |
| |
| end: |
| sme_release_global_lock(&pMac->sme); |
| |
| return status; |
| } |
| |
| /** |
| * sme_dcc_update_ndl() - Update the DCC settings |
| * @mac_handle: reference to the HAL |
| * @context: the context of the call |
| * @callback: the callback to hdd |
| * @request: the update DCC request |
| * |
| * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure |
| */ |
| QDF_STATUS sme_dcc_update_ndl(mac_handle_t mac_handle, void *context, |
| ocb_callback callback, |
| struct sir_dcc_update_ndl *request) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg msg = {0}; |
| struct sir_dcc_update_ndl *msg_body; |
| |
| /* Lock the SME structure */ |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| return status; |
| |
| /* Allocate memory for the WMI request, and copy the parameter */ |
| msg_body = qdf_mem_malloc(sizeof(*msg_body) + |
| request->dcc_ndl_chan_list_len + |
| request->dcc_ndl_active_state_list_len); |
| if (!msg_body) { |
| status = QDF_STATUS_E_NOMEM; |
| goto end; |
| } |
| |
| *msg_body = *request; |
| |
| msg_body->dcc_ndl_chan_list = (void *)msg_body + sizeof(*msg_body); |
| msg_body->dcc_ndl_active_state_list = msg_body->dcc_ndl_chan_list + |
| request->dcc_ndl_chan_list_len; |
| qdf_mem_copy(msg_body->dcc_ndl_chan_list, request->dcc_ndl_chan_list, |
| request->dcc_ndl_active_state_list_len); |
| qdf_mem_copy(msg_body->dcc_ndl_active_state_list, |
| request->dcc_ndl_active_state_list, |
| request->dcc_ndl_active_state_list_len); |
| |
| msg.type = WMA_DCC_UPDATE_NDL_CMD; |
| msg.bodyptr = msg_body; |
| |
| /* Set the request callback and the context */ |
| pMac->sme.dcc_update_ndl_callback = callback; |
| pMac->sme.dcc_update_ndl_context = context; |
| |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Error posting message to WDA: %d"), status); |
| pMac->sme.dcc_update_ndl_callback = NULL; |
| pMac->sme.dcc_update_ndl_context = NULL; |
| qdf_mem_free(msg_body); |
| goto end; |
| } |
| |
| end: |
| sme_release_global_lock(&pMac->sme); |
| |
| return status; |
| } |
| |
| /** |
| * sme_register_for_dcc_stats_event() - Register for the periodic DCC stats |
| * event |
| * @mac_handle: reference to the HAL |
| * @context: the context of the call |
| * @callback: the callback to hdd |
| * |
| * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure |
| */ |
| QDF_STATUS sme_register_for_dcc_stats_event(mac_handle_t mac_handle, |
| void *context, |
| ocb_callback callback) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| pMac->sme.dcc_stats_event_callback = callback; |
| pMac->sme.dcc_stats_event_context = context; |
| sme_release_global_lock(&pMac->sme); |
| |
| return 0; |
| } |
| |
| /** |
| * sme_deregister_for_dcc_stats_event() - De-Register for the periodic DCC stats |
| * event |
| * @mac_handle: Hal Handle |
| * |
| * This function de-registers the DCC perioc stats callback |
| * |
| * Return: QDF_STATUS Enumeration |
| */ |
| QDF_STATUS sme_deregister_for_dcc_stats_event(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal mac; |
| QDF_STATUS status; |
| |
| if (!mac_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("mac_handle is not valid")); |
| return QDF_STATUS_E_INVAL; |
| } |
| mac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Failed to acquire global lock")); |
| return status; |
| } |
| mac->sme.dcc_stats_event_callback = NULL; |
| mac->sme.dcc_stats_event_context = NULL; |
| sme_release_global_lock(&mac->sme); |
| |
| return status; |
| } |
| #else |
| void sme_set_etsi13_srd_ch_in_master_mode(mac_handle_t hal, |
| bool etsi13_srd_chan_support) |
| { |
| tpAniSirGlobal mac; |
| |
| mac = PMAC_STRUCT(hal); |
| mac->sap.enable_etsi13_srd_chan_support = etsi13_srd_chan_support; |
| sme_debug("srd_ch_support %d", mac->sap.enable_etsi13_srd_chan_support); |
| } |
| #endif |
| |
| void sme_get_recovery_stats(mac_handle_t mac_handle) |
| { |
| uint8_t i; |
| |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "Self Recovery Stats"); |
| for (i = 0; i < MAX_ACTIVE_CMD_STATS; i++) { |
| if (eSmeNoCommand != |
| g_self_recovery_stats.activeCmdStats[i].command) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "timestamp %llu: command 0x%0X: reason %d: session %d", |
| g_self_recovery_stats.activeCmdStats[i]. |
| timestamp, |
| g_self_recovery_stats.activeCmdStats[i].command, |
| g_self_recovery_stats.activeCmdStats[i].reason, |
| g_self_recovery_stats.activeCmdStats[i]. |
| sessionId); |
| } |
| } |
| } |
| |
| QDF_STATUS sme_notify_modem_power_state(mac_handle_t mac_handle, uint32_t value) |
| { |
| struct scheduler_msg msg = {0}; |
| tpSirModemPowerStateInd request_buf; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (NULL == pMac) |
| return QDF_STATUS_E_FAILURE; |
| |
| request_buf = qdf_mem_malloc(sizeof(tSirModemPowerStateInd)); |
| if (!request_buf) |
| return QDF_STATUS_E_NOMEM; |
| |
| request_buf->param = value; |
| |
| msg.type = WMA_MODEM_POWER_STATE_IND; |
| msg.reserved = 0; |
| msg.bodyptr = request_buf; |
| if (!QDF_IS_STATUS_SUCCESS |
| (scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg))) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post WMA_MODEM_POWER_STATE_IND message to WMA", |
| __func__); |
| qdf_mem_free(request_buf); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| #ifdef QCA_HT_2040_COEX |
| QDF_STATUS sme_notify_ht2040_mode(mac_handle_t mac_handle, uint16_t staId, |
| struct qdf_mac_addr macAddrSTA, |
| uint8_t sessionId, |
| uint8_t channel_type) |
| { |
| struct scheduler_msg msg = {0}; |
| tUpdateVHTOpMode *pHtOpMode = NULL; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (NULL == pMac) |
| return QDF_STATUS_E_FAILURE; |
| |
| pHtOpMode = qdf_mem_malloc(sizeof(tUpdateVHTOpMode)); |
| if (!pHtOpMode) |
| return QDF_STATUS_E_NOMEM; |
| |
| switch (channel_type) { |
| case eHT_CHAN_HT20: |
| pHtOpMode->opMode = eHT_CHANNEL_WIDTH_20MHZ; |
| break; |
| |
| case eHT_CHAN_HT40MINUS: |
| case eHT_CHAN_HT40PLUS: |
| pHtOpMode->opMode = eHT_CHANNEL_WIDTH_40MHZ; |
| break; |
| |
| default: |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Invalid OP mode", __func__); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| pHtOpMode->staId = staId, |
| qdf_mem_copy(pHtOpMode->peer_mac, macAddrSTA.bytes, |
| sizeof(tSirMacAddr)); |
| pHtOpMode->smesessionId = sessionId; |
| |
| msg.type = WMA_UPDATE_OP_MODE; |
| msg.reserved = 0; |
| msg.bodyptr = pHtOpMode; |
| if (!QDF_IS_STATUS_SUCCESS |
| (scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg))) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post WMA_UPDATE_OP_MODE message to WMA", |
| __func__); |
| qdf_mem_free(pHtOpMode); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: Notified FW about OP mode: %d for staId=%d", |
| __func__, pHtOpMode->opMode, staId); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /* |
| * sme_set_ht2040_mode() - |
| * To update HT Operation beacon IE. |
| * |
| * Return QDF_STATUS SUCCESS |
| * FAILURE or RESOURCES |
| * The API finished and failed. |
| */ |
| QDF_STATUS sme_set_ht2040_mode(mac_handle_t mac_handle, uint8_t sessionId, |
| uint8_t channel_type, bool obssEnabled) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| ePhyChanBondState cbMode; |
| struct csr_roam_session *session = CSR_GET_SESSION(pMac, sessionId); |
| |
| if (!CSR_IS_SESSION_VALID(pMac, sessionId)) { |
| sme_err("Session not valid for session id %d", sessionId); |
| return QDF_STATUS_E_INVAL; |
| } |
| session = CSR_GET_SESSION(pMac, sessionId); |
| sme_debug("Update HT operation beacon IE, channel_type=%d cur cbmode %d", |
| channel_type, session->bssParams.cbMode); |
| |
| switch (channel_type) { |
| case eHT_CHAN_HT20: |
| if (!session->bssParams.cbMode) |
| return QDF_STATUS_SUCCESS; |
| cbMode = PHY_SINGLE_CHANNEL_CENTERED; |
| break; |
| case eHT_CHAN_HT40MINUS: |
| if (session->bssParams.cbMode) |
| return QDF_STATUS_SUCCESS; |
| cbMode = PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; |
| break; |
| case eHT_CHAN_HT40PLUS: |
| if (session->bssParams.cbMode) |
| return QDF_STATUS_SUCCESS; |
| cbMode = PHY_DOUBLE_CHANNEL_LOW_PRIMARY; |
| break; |
| default: |
| sme_err("Error!!! Invalid HT20/40 mode !"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| session->bssParams.cbMode = cbMode; |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_set_ht2040_mode(pMac, sessionId, |
| cbMode, obssEnabled); |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| #endif |
| |
| /* |
| * SME API to enable/disable idle mode powersave |
| * This should be called only if powersave offload |
| * is enabled |
| */ |
| QDF_STATUS sme_set_idle_powersave_config(bool value) |
| { |
| void *wmaContext = cds_get_context(QDF_MODULE_ID_WMA); |
| |
| if (NULL == wmaContext) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: wmaContext is NULL", __func__); |
| return QDF_STATUS_E_FAILURE; |
| } |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| " Idle Ps Set Value %d", value); |
| |
| if (QDF_STATUS_SUCCESS != wma_set_idle_ps_config(wmaContext, value)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| " Failed to Set Idle Ps Value %d", value); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| int16_t sme_get_ht_config(mac_handle_t mac_handle, uint8_t session_id, |
| uint16_t ht_capab) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct csr_roam_session *pSession = CSR_GET_SESSION(pMac, session_id); |
| |
| if (NULL == pSession) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: pSession is NULL", __func__); |
| return -EIO; |
| } |
| switch (ht_capab) { |
| case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING: |
| return pSession->htConfig.ht_rx_ldpc; |
| case WNI_CFG_HT_CAP_INFO_TX_STBC: |
| return pSession->htConfig.ht_tx_stbc; |
| case WNI_CFG_HT_CAP_INFO_RX_STBC: |
| return pSession->htConfig.ht_rx_stbc; |
| case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ: |
| return pSession->htConfig.ht_sgi20; |
| case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ: |
| return pSession->htConfig.ht_sgi40; |
| default: |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "invalid ht capability"); |
| return -EIO; |
| } |
| } |
| |
| int sme_update_ht_config(mac_handle_t mac_handle, uint8_t sessionId, |
| uint16_t htCapab, int value) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct csr_roam_session *pSession = CSR_GET_SESSION(pMac, sessionId); |
| |
| if (NULL == pSession) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: pSession is NULL", __func__); |
| return -EIO; |
| } |
| |
| if (QDF_STATUS_SUCCESS != wma_set_htconfig(sessionId, htCapab, value)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "Failed to set ht capability in target"); |
| return -EIO; |
| } |
| |
| switch (htCapab) { |
| case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING: |
| pSession->htConfig.ht_rx_ldpc = value; |
| pMac->roam.configParam.rx_ldpc_enable = value; |
| break; |
| case WNI_CFG_HT_CAP_INFO_TX_STBC: |
| pSession->htConfig.ht_tx_stbc = value; |
| break; |
| case WNI_CFG_HT_CAP_INFO_RX_STBC: |
| pSession->htConfig.ht_rx_stbc = value; |
| break; |
| case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ: |
| value = value ? 1 : 0; /* HT SGI can be only 1 or 0 */ |
| pSession->htConfig.ht_sgi20 = value; |
| break; |
| case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ: |
| value = value ? 1 : 0; /* HT SGI can be only 1 or 0 */ |
| pSession->htConfig.ht_sgi40 = value; |
| break; |
| } |
| |
| csr_roam_update_config(pMac, sessionId, htCapab, value); |
| return 0; |
| } |
| |
| int sme_set_addba_accept(mac_handle_t hal, uint8_t session_id, int value) |
| { |
| struct sme_addba_accept *addba_accept; |
| struct scheduler_msg msg = {0}; |
| QDF_STATUS status; |
| |
| addba_accept = qdf_mem_malloc(sizeof(*addba_accept)); |
| if (!addba_accept) |
| return -EIO; |
| |
| addba_accept->session_id = session_id; |
| addba_accept->addba_accept = value; |
| qdf_mem_zero(&msg, sizeof(msg)); |
| msg.type = eWNI_SME_SET_ADDBA_ACCEPT; |
| msg.reserved = 0; |
| msg.bodyptr = addba_accept; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_PE, |
| QDF_MODULE_ID_PE, &msg); |
| if (status != QDF_STATUS_SUCCESS) { |
| sme_err("Not able to post addba reject"); |
| qdf_mem_free(addba_accept); |
| return -EIO; |
| } |
| return 0; |
| } |
| |
| int sme_set_ba_buff_size(mac_handle_t hal, uint8_t session_id, |
| uint16_t buff_size) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| if (!buff_size) { |
| sme_err("invalid buff size %d", buff_size); |
| return -EINVAL; |
| } |
| mac_ctx->usr_cfg_ba_buff_size = buff_size; |
| sme_debug("addba buff size is set to %d", |
| mac_ctx->usr_cfg_ba_buff_size); |
| |
| return 0; |
| } |
| |
| #define DEFAULT_BA_BUFF_SIZE 64 |
| int sme_send_addba_req(mac_handle_t hal, uint8_t session_id, uint8_t tid, |
| uint16_t buff_size) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| uint16_t ba_buff = 0; |
| QDF_STATUS status; |
| struct scheduler_msg msg = {0}; |
| struct send_add_ba_req *send_ba_req; |
| struct csr_roam_session *csr_session = NULL; |
| |
| if (!csr_is_conn_state_connected_infra(mac_ctx, session_id)) { |
| sme_err("STA not infra/connected state session_id: %d", |
| session_id); |
| return -EINVAL; |
| } |
| csr_session = CSR_GET_SESSION(mac_ctx, session_id); |
| if (!csr_session) { |
| sme_err("CSR session is NULL"); |
| return -EINVAL; |
| } |
| send_ba_req = qdf_mem_malloc(sizeof(*send_ba_req)); |
| if (!send_ba_req) |
| return -EIO; |
| |
| qdf_mem_copy(send_ba_req->mac_addr, |
| csr_session->connectedProfile.bssid.bytes, |
| QDF_MAC_ADDR_SIZE); |
| ba_buff = buff_size; |
| if (!buff_size) { |
| if (mac_ctx->usr_cfg_ba_buff_size) |
| ba_buff = mac_ctx->usr_cfg_ba_buff_size; |
| else |
| ba_buff = DEFAULT_BA_BUFF_SIZE; |
| } |
| send_ba_req->param.vdev_id = session_id; |
| send_ba_req->param.tidno = tid; |
| send_ba_req->param.buffersize = ba_buff; |
| msg.type = WMA_SEND_ADDBA_REQ; |
| msg.bodyptr = send_ba_req; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| if (QDF_STATUS_SUCCESS != status) { |
| sme_err("Failed to post WMA_SEND_ADDBA_REQ"); |
| qdf_mem_free(send_ba_req); |
| return -EIO; |
| } |
| sme_debug("ADDBA_REQ sent to FW: tid %d buff_size %d", tid, ba_buff); |
| |
| return 0; |
| } |
| |
| int sme_set_no_ack_policy(mac_handle_t hal, uint8_t session_id, |
| uint8_t val, uint8_t ac) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| uint8_t i, set_val; |
| struct scheduler_msg msg = {0}; |
| QDF_STATUS status; |
| |
| if (ac > MAX_NUM_AC) { |
| sme_err("invalid ac val %d", ac); |
| return -EINVAL; |
| } |
| if (val) |
| set_val = 1; |
| else |
| set_val = 0; |
| if (ac == MAX_NUM_AC) { |
| for (i = 0; i < ac; i++) |
| mac_ctx->no_ack_policy_cfg[i] = set_val; |
| } else { |
| mac_ctx->no_ack_policy_cfg[ac] = set_val; |
| } |
| sme_debug("no ack is set to %d for ac %d", set_val, ac); |
| qdf_mem_zero(&msg, sizeof(msg)); |
| msg.type = eWNI_SME_UPDATE_EDCA_PROFILE; |
| msg.reserved = 0; |
| msg.bodyval = session_id; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_PE, |
| QDF_MODULE_ID_PE, &msg); |
| if (status != QDF_STATUS_SUCCESS) { |
| sme_err("Not able to post update edca profile"); |
| return -EIO; |
| } |
| |
| return 0; |
| } |
| |
| int sme_set_auto_rate_he_ltf(mac_handle_t hal, uint8_t session_id, |
| uint8_t cfg_val) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| uint32_t set_val; |
| uint32_t bit_mask = 0; |
| int status; |
| |
| if (cfg_val > QCA_WLAN_HE_LTF_4X) { |
| sme_err("invalid HE LTF cfg %d", cfg_val); |
| return -EINVAL; |
| } |
| |
| /*set the corresponding HE LTF cfg BIT*/ |
| if (cfg_val == QCA_WLAN_HE_LTF_AUTO) |
| bit_mask = HE_LTF_ALL; |
| else |
| bit_mask = (1 << (cfg_val - 1)); |
| |
| set_val = mac_ctx->he_sgi_ltf_cfg_bit_mask; |
| |
| SET_AUTO_RATE_HE_LTF_VAL(set_val, bit_mask); |
| |
| mac_ctx->he_sgi_ltf_cfg_bit_mask = set_val; |
| status = wma_cli_set_command(session_id, |
| WMI_VDEV_PARAM_AUTORATE_MISC_CFG, |
| set_val, VDEV_CMD); |
| if (status) { |
| sme_err("failed to set he_ltf_sgi"); |
| return status; |
| } |
| |
| sme_debug("HE SGI_LTF is set to 0x%08X", |
| mac_ctx->he_sgi_ltf_cfg_bit_mask); |
| |
| return 0; |
| } |
| |
| int sme_set_auto_rate_he_sgi(mac_handle_t hal, uint8_t session_id, |
| uint8_t cfg_val) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| uint32_t set_val; |
| uint32_t sgi_bit_mask = 0; |
| int status; |
| |
| if ((cfg_val > AUTO_RATE_GI_3200NS) || |
| (cfg_val < AUTO_RATE_GI_400NS)) { |
| sme_err("invalid auto rate GI cfg %d", cfg_val); |
| return -EINVAL; |
| } |
| |
| sgi_bit_mask = (1 << cfg_val); |
| |
| set_val = mac_ctx->he_sgi_ltf_cfg_bit_mask; |
| SET_AUTO_RATE_SGI_VAL(set_val, sgi_bit_mask); |
| |
| mac_ctx->he_sgi_ltf_cfg_bit_mask = set_val; |
| status = wma_cli_set_command(session_id, |
| WMI_VDEV_PARAM_AUTORATE_MISC_CFG, |
| set_val, VDEV_CMD); |
| if (status) { |
| sme_err("failed to set he_ltf_sgi"); |
| return status; |
| } |
| |
| sme_debug("auto rate HE SGI_LTF is set to 0x%08X", |
| mac_ctx->he_sgi_ltf_cfg_bit_mask); |
| |
| return 0; |
| } |
| |
| #define HT20_SHORT_GI_MCS7_RATE 722 |
| /* |
| * sme_send_rate_update_ind() - |
| * API to Update rate |
| * |
| * mac_handle - The handle returned by mac_open |
| * rateUpdateParams - Pointer to rate update params |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_send_rate_update_ind(mac_handle_t mac_handle, |
| tSirRateUpdateInd *rateUpdateParams) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status; |
| struct scheduler_msg msg = {0}; |
| tSirRateUpdateInd *rate_upd = qdf_mem_malloc(sizeof(tSirRateUpdateInd)); |
| |
| if (!rate_upd) |
| return QDF_STATUS_E_FAILURE; |
| |
| *rate_upd = *rateUpdateParams; |
| |
| if (rate_upd->mcastDataRate24GHz == HT20_SHORT_GI_MCS7_RATE) |
| rate_upd->mcastDataRate24GHzTxFlag = |
| TX_RATE_HT20 | TX_RATE_SGI; |
| else if (rate_upd->reliableMcastDataRate == |
| HT20_SHORT_GI_MCS7_RATE) |
| rate_upd->reliableMcastDataRateTxFlag = |
| TX_RATE_HT20 | TX_RATE_SGI; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| msg.type = WMA_RATE_UPDATE_IND; |
| msg.bodyptr = rate_upd; |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| NO_SESSION, msg.type)); |
| if (!QDF_IS_STATUS_SUCCESS |
| (scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &msg))) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post WMA_RATE_UPDATE_IND to WMA!", |
| __func__); |
| |
| sme_release_global_lock(&pMac->sme); |
| qdf_mem_free(rate_upd); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| return status; |
| } |
| |
| /** |
| * sme_update_access_policy_vendor_ie() - update vendor ie and access policy. |
| * @hal: Pointer to the mac context |
| * @session_id: sme session id |
| * @vendor_ie: vendor ie |
| * @access_policy: vendor ie access policy |
| * |
| * This function updates the vendor ie and access policy to lim. |
| * |
| * Return: success or failure. |
| */ |
| QDF_STATUS sme_update_access_policy_vendor_ie(mac_handle_t hal, |
| uint8_t session_id, uint8_t *vendor_ie, int access_policy) |
| { |
| struct sme_update_access_policy_vendor_ie *msg; |
| uint16_t msg_len; |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| |
| msg_len = sizeof(*msg); |
| |
| msg = qdf_mem_malloc(msg_len); |
| if (!msg) { |
| return QDF_STATUS_E_NOMEM; |
| } |
| |
| msg->msg_type = (uint16_t)eWNI_SME_UPDATE_ACCESS_POLICY_VENDOR_IE; |
| msg->length = (uint16_t)msg_len; |
| |
| qdf_mem_copy(&msg->ie[0], vendor_ie, sizeof(msg->ie)); |
| |
| msg->sme_session_id = session_id; |
| msg->access_policy = access_policy; |
| |
| sme_debug("sme_session_id: %hu, access_policy: %d", session_id, |
| access_policy); |
| |
| status = umac_send_mb_message_to_mac(msg); |
| |
| return status; |
| } |
| |
| /** |
| * sme_update_short_retry_limit_threshold() - update short frame retry limit TH |
| * @hal: Handle returned by mac_open |
| * @session_id: Session ID on which short frame retry limit needs to be |
| * updated to FW |
| * @short_limit_count_th: Retry count TH to retry short frame. |
| * |
| * This function is used to configure count to retry short frame. |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_update_short_retry_limit_threshold(mac_handle_t mac_handle, |
| struct sme_short_retry_limit *short_retry_limit_th) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| struct sme_short_retry_limit *srl; |
| struct scheduler_msg msg = {0}; |
| |
| srl = qdf_mem_malloc(sizeof(*srl)); |
| if (!srl) |
| return QDF_STATUS_E_FAILURE; |
| |
| sme_debug("session_id %d short retry limit count: %d", |
| short_retry_limit_th->session_id, |
| short_retry_limit_th->short_retry_limit); |
| |
| srl->session_id = short_retry_limit_th->session_id; |
| srl->short_retry_limit = short_retry_limit_th->short_retry_limit; |
| |
| qdf_mem_zero(&msg, sizeof(msg)); |
| msg.type = SIR_HAL_SHORT_RETRY_LIMIT_CNT; |
| msg.reserved = 0; |
| msg.bodyptr = srl; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| if (status != QDF_STATUS_SUCCESS) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Not able to post short retry limit count to WDA")); |
| qdf_mem_free(srl); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return status; |
| } |
| |
| /** |
| * sme_update_long_retry_limit_threshold() - update long retry limit TH |
| * @hal: Handle returned by mac_open |
| * @session_id: Session ID on which long frames retry TH needs to be updated |
| * to FW |
| * @long_limit_count_th: Retry count to retry long frame. |
| * |
| * This function is used to configure TH to retry long frame. |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_update_long_retry_limit_threshold(mac_handle_t mac_handle, |
| struct sme_long_retry_limit *long_retry_limit_th) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| struct sme_long_retry_limit *lrl; |
| struct scheduler_msg msg = {0}; |
| |
| lrl = qdf_mem_malloc(sizeof(*lrl)); |
| if (!lrl) |
| return QDF_STATUS_E_FAILURE; |
| |
| sme_debug("session_id %d long retry limit count: %d", |
| long_retry_limit_th->session_id, |
| long_retry_limit_th->long_retry_limit); |
| |
| lrl->session_id = long_retry_limit_th->session_id; |
| lrl->long_retry_limit = long_retry_limit_th->long_retry_limit; |
| |
| qdf_mem_zero(&msg, sizeof(msg)); |
| msg.type = SIR_HAL_LONG_RETRY_LIMIT_CNT; |
| msg.reserved = 0; |
| msg.bodyptr = lrl; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| |
| if (status != QDF_STATUS_SUCCESS) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Not able to post long retry limit count to WDA")); |
| qdf_mem_free(lrl); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return status; |
| } |
| |
| /** |
| * sme_update_sta_inactivity_timeout(): Update sta_inactivity_timeout to FW |
| * @hal: Handle returned by mac_open |
| * @session_id: Session ID on which sta_inactivity_timeout needs |
| * to be updated to FW |
| * @sta_inactivity_timeout: sta inactivity timeout. |
| * |
| * If a station does not send anything in sta_inactivity_timeout seconds, an |
| * empty data frame is sent to it in order to verify whether it is |
| * still in range. If this frame is not ACKed, the station will be |
| * disassociated and then deauthenticated. |
| * |
| * Return: QDF_STATUS_SUCCESS or non-zero on failure. |
| */ |
| QDF_STATUS sme_update_sta_inactivity_timeout(mac_handle_t mac_handle, |
| struct sme_sta_inactivity_timeout *sta_inactivity_timer) |
| { |
| struct sme_sta_inactivity_timeout *inactivity_time; |
| void *wma_handle; |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| inactivity_time = qdf_mem_malloc(sizeof(*inactivity_time)); |
| if (!inactivity_time) |
| return QDF_STATUS_E_FAILURE; |
| |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| FL("sta_inactivity_timeout: %d"), |
| sta_inactivity_timer->sta_inactivity_timeout); |
| inactivity_time->session_id = sta_inactivity_timer->session_id; |
| inactivity_time->sta_inactivity_timeout = |
| sta_inactivity_timer->sta_inactivity_timeout; |
| |
| wma_update_sta_inactivity_timeout(wma_handle, |
| inactivity_time); |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_get_reg_info() - To get registration info |
| * @mac_handle: HAL context |
| * @chanId: channel id |
| * @regInfo1: first reg info to fill |
| * @regInfo2: second reg info to fill |
| * |
| * This routine will give you reg info |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_get_reg_info(mac_handle_t mac_handle, uint8_t chanId, |
| uint32_t *regInfo1, uint32_t *regInfo2) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status; |
| uint8_t i; |
| bool found = false; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| *regInfo1 = 0; |
| *regInfo2 = 0; |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| return status; |
| |
| for (i = 0; i < WNI_CFG_VALID_CHANNEL_LIST_LEN; i++) { |
| if (pMac->scan.defaultPowerTable[i].chan_num == chanId) { |
| SME_SET_CHANNEL_REG_POWER(*regInfo1, |
| pMac->scan.defaultPowerTable[i].tx_power); |
| |
| SME_SET_CHANNEL_MAX_TX_POWER(*regInfo2, |
| pMac->scan.defaultPowerTable[i].tx_power); |
| found = true; |
| break; |
| } |
| } |
| if (!found) |
| status = QDF_STATUS_E_FAILURE; |
| |
| sme_release_global_lock(&pMac->sme); |
| return status; |
| } |
| |
| #ifdef FEATURE_WLAN_AUTO_SHUTDOWN |
| /* |
| * sme_auto_shutdown_cb() - |
| * Used to plug in callback function for receiving auto shutdown evt |
| * |
| * mac_handle |
| * pCallbackfn : callback function pointer should be plugged in |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_set_auto_shutdown_cb(mac_handle_t mac_handle, |
| void (*pCallbackfn)(void)) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Plug in Auto shutdown event callback", __func__); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| if (NULL != pCallbackfn) |
| pMac->sme.pAutoShutdownNotificationCb = pCallbackfn; |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_set_auto_shutdown_timer() - |
| * API to set auto shutdown timer value in FW. |
| * |
| * mac_handle - The handle returned by mac_open |
| * timer_val - The auto shutdown timer value to be set |
| * Return Configuration message posting status, SUCCESS or Fail |
| */ |
| QDF_STATUS sme_set_auto_shutdown_timer(mac_handle_t mac_handle, |
| uint32_t timer_val) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| tSirAutoShutdownCmdParams *auto_sh_cmd; |
| struct scheduler_msg message = {0}; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| auto_sh_cmd = qdf_mem_malloc(sizeof(tSirAutoShutdownCmdParams)); |
| if (!auto_sh_cmd) { |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_NOMEM; |
| } |
| |
| auto_sh_cmd->timer_val = timer_val; |
| |
| /* serialize the req through MC thread */ |
| message.bodyptr = auto_sh_cmd; |
| message.type = WMA_SET_AUTO_SHUTDOWN_TIMER_REQ; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Post Auto shutdown MSG fail", __func__); |
| qdf_mem_free(auto_sh_cmd); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: Posted Auto shutdown MSG", __func__); |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| #endif |
| |
| #ifdef FEATURE_WLAN_CH_AVOID |
| /* |
| * sme_ch_avoid_update_req() - |
| * API to request channel avoidance update from FW. |
| * |
| * mac_handle - The handle returned by mac_open |
| * update_type - The update_type parameter of this request call |
| * Return Configuration message posting status, SUCCESS or Fail |
| */ |
| QDF_STATUS sme_ch_avoid_update_req(mac_handle_t mac_handle) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| tSirChAvoidUpdateReq *cauReq; |
| struct scheduler_msg message = {0}; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| cauReq = qdf_mem_malloc(sizeof(tSirChAvoidUpdateReq)); |
| if (!cauReq) { |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_NOMEM; |
| } |
| |
| cauReq->reserved_param = 0; |
| |
| /* serialize the req through MC thread */ |
| message.bodyptr = cauReq; |
| message.type = WMA_CH_AVOID_UPDATE_REQ; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Post Ch Avoid Update MSG fail", |
| __func__); |
| qdf_mem_free(cauReq); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: Posted Ch Avoid Update MSG", __func__); |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| return status; |
| } |
| #endif |
| |
| /** |
| * sme_set_miracast() - Function to set miracast value to UMAC |
| * @hal: Handle returned by macOpen |
| * @filter_type: 0-Disabled, 1-Source, 2-sink |
| * |
| * This function passes down the value of miracast set by |
| * framework to UMAC |
| * |
| * Return: Configuration message posting status, SUCCESS or Fail |
| * |
| */ |
| QDF_STATUS sme_set_miracast(mac_handle_t hal, uint8_t filter_type) |
| { |
| struct scheduler_msg msg = {0}; |
| uint32_t *val; |
| tpAniSirGlobal mac_ptr = PMAC_STRUCT(hal); |
| |
| if (!mac_ptr) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Invalid pointer", __func__); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| val = qdf_mem_malloc(sizeof(*val)); |
| if (!val) |
| return QDF_STATUS_E_NOMEM; |
| |
| *val = filter_type; |
| |
| msg.type = SIR_HAL_SET_MIRACAST; |
| msg.reserved = 0; |
| msg.bodyptr = val; |
| |
| if (!QDF_IS_STATUS_SUCCESS( |
| scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &msg))) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post WDA_SET_MAS_ENABLE_DISABLE to WMA!", |
| __func__); |
| qdf_mem_free(val); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| mac_ptr->sme.miracast_value = filter_type; |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_set_mas() - Function to set MAS value to UMAC |
| * @val: 1-Enable, 0-Disable |
| * |
| * This function passes down the value of MAS to the UMAC. A |
| * value of 1 will enable MAS and a value of 0 will disable MAS |
| * |
| * Return: Configuration message posting status, SUCCESS or Fail |
| * |
| */ |
| QDF_STATUS sme_set_mas(uint32_t val) |
| { |
| struct scheduler_msg msg = {0}; |
| uint32_t *ptr_val; |
| |
| ptr_val = qdf_mem_malloc(sizeof(*ptr_val)); |
| if (!ptr_val) |
| return QDF_STATUS_E_NOMEM; |
| |
| *ptr_val = val; |
| |
| msg.type = SIR_HAL_SET_MAS; |
| msg.reserved = 0; |
| msg.bodyptr = ptr_val; |
| |
| if (!QDF_IS_STATUS_SUCCESS( |
| scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &msg))) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post WDA_SET_MAS_ENABLE_DISABLE to WMA!", |
| __func__); |
| qdf_mem_free(ptr_val); |
| return QDF_STATUS_E_FAILURE; |
| } |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_roam_channel_change_req() - Channel change to new target channel |
| * @mac_handle: handle returned by mac_open |
| * @bssid: mac address of BSS |
| * @ch_params: target channel information |
| * @profile: CSR profile |
| * |
| * API to Indicate Channel change to new target channel |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_roam_channel_change_req(mac_handle_t mac_handle, |
| struct qdf_mac_addr bssid, |
| struct ch_params *ch_params, |
| struct csr_roam_profile *profile) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| |
| status = csr_roam_channel_change_req(pMac, bssid, ch_params, |
| profile); |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_process_channel_change_resp() - |
| * API to Indicate Channel change response message to SAP. |
| * |
| * Return QDF_STATUS |
| */ |
| static QDF_STATUS sme_process_channel_change_resp(tpAniSirGlobal pMac, |
| uint16_t msg_type, void *pMsgBuf) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| struct csr_roam_info proam_info = { 0 }; |
| eCsrRoamResult roamResult; |
| tpSwitchChannelParams pChnlParams = (tpSwitchChannelParams) pMsgBuf; |
| uint32_t SessionId = pChnlParams->peSessionId; |
| |
| proam_info.channelChangeRespEvent = |
| qdf_mem_malloc(sizeof(tSirChanChangeResponse)); |
| if (!proam_info.channelChangeRespEvent) { |
| status = QDF_STATUS_E_NOMEM; |
| return status; |
| } |
| if (msg_type == eWNI_SME_CHANNEL_CHANGE_RSP) { |
| proam_info.channelChangeRespEvent->sessionId = SessionId; |
| proam_info.channelChangeRespEvent->newChannelNumber = |
| pChnlParams->channelNumber; |
| |
| if (pChnlParams->status == QDF_STATUS_SUCCESS) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "sapdfs: Received success eWNI_SME_CHANNEL_CHANGE_RSP for sessionId[%d]", |
| SessionId); |
| proam_info.channelChangeRespEvent->channelChangeStatus = |
| 1; |
| roamResult = eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS; |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "sapdfs: Received failure eWNI_SME_CHANNEL_CHANGE_RSP for sessionId[%d]", |
| SessionId); |
| proam_info.channelChangeRespEvent->channelChangeStatus = |
| 0; |
| roamResult = eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE; |
| } |
| |
| csr_roam_call_callback(pMac, SessionId, &proam_info, 0, |
| eCSR_ROAM_SET_CHANNEL_RSP, roamResult); |
| |
| } else { |
| status = QDF_STATUS_E_FAILURE; |
| sme_err("Invalid Channel Change Resp Message: %d", |
| status); |
| } |
| qdf_mem_free(proam_info.channelChangeRespEvent); |
| |
| return status; |
| } |
| |
| /* |
| * sme_roam_start_beacon_req() - |
| * API to Indicate LIM to start Beacon Tx after SAP CAC Wait is completed. |
| * |
| * mac_handle - The handle returned by mac_open |
| * sessionId - session ID |
| * dfsCacWaitStatus - CAC WAIT status flag |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_roam_start_beacon_req(mac_handle_t mac_handle, |
| struct qdf_mac_addr bssid, |
| uint8_t dfsCacWaitStatus) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_roam_start_beacon_req(pMac, bssid, |
| dfsCacWaitStatus); |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| #ifdef CONFIG_VDEV_SM |
| QDF_STATUS sme_csa_restart(tpAniSirGlobal mac_ctx, uint8_t session_id) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_csa_restart(mac_ctx, session_id); |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| |
| return status; |
| } |
| #endif |
| |
| /** |
| * sme_roam_csa_ie_request() - request CSA IE transmission from PE |
| * @mac_handle: handle returned by mac_open |
| * @bssid: SAP bssid |
| * @targetChannel: target channel information |
| * @csaIeReqd: CSA IE Request |
| * @ch_params: channel information |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_roam_csa_ie_request(mac_handle_t mac_handle, |
| struct qdf_mac_addr bssid, |
| uint8_t targetChannel, uint8_t csaIeReqd, |
| struct ch_params *ch_params) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_roam_send_chan_sw_ie_request(pMac, bssid, |
| targetChannel, csaIeReqd, ch_params); |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_init_thermal_info() - |
| * SME API to initialize the thermal mitigation parameters |
| * |
| * mac_handle |
| * thermalParam : thermal mitigation parameters |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_init_thermal_info(mac_handle_t mac_handle, tSmeThermalParams |
| thermalParam) |
| { |
| t_thermal_mgmt *pWmaParam; |
| struct scheduler_msg msg = {0}; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| pWmaParam = qdf_mem_malloc(sizeof(t_thermal_mgmt)); |
| if (!pWmaParam) |
| return QDF_STATUS_E_NOMEM; |
| |
| pWmaParam->thermalMgmtEnabled = thermalParam.smeThermalMgmtEnabled; |
| pWmaParam->throttlePeriod = thermalParam.smeThrottlePeriod; |
| |
| pWmaParam->throttle_duty_cycle_tbl[0] = |
| thermalParam.sme_throttle_duty_cycle_tbl[0]; |
| pWmaParam->throttle_duty_cycle_tbl[1] = |
| thermalParam.sme_throttle_duty_cycle_tbl[1]; |
| pWmaParam->throttle_duty_cycle_tbl[2] = |
| thermalParam.sme_throttle_duty_cycle_tbl[2]; |
| pWmaParam->throttle_duty_cycle_tbl[3] = |
| thermalParam.sme_throttle_duty_cycle_tbl[3]; |
| |
| pWmaParam->thermalLevels[0].minTempThreshold = |
| thermalParam.smeThermalLevels[0].smeMinTempThreshold; |
| pWmaParam->thermalLevels[0].maxTempThreshold = |
| thermalParam.smeThermalLevels[0].smeMaxTempThreshold; |
| pWmaParam->thermalLevels[1].minTempThreshold = |
| thermalParam.smeThermalLevels[1].smeMinTempThreshold; |
| pWmaParam->thermalLevels[1].maxTempThreshold = |
| thermalParam.smeThermalLevels[1].smeMaxTempThreshold; |
| pWmaParam->thermalLevels[2].minTempThreshold = |
| thermalParam.smeThermalLevels[2].smeMinTempThreshold; |
| pWmaParam->thermalLevels[2].maxTempThreshold = |
| thermalParam.smeThermalLevels[2].smeMaxTempThreshold; |
| pWmaParam->thermalLevels[3].minTempThreshold = |
| thermalParam.smeThermalLevels[3].smeMinTempThreshold; |
| pWmaParam->thermalLevels[3].maxTempThreshold = |
| thermalParam.smeThermalLevels[3].smeMaxTempThreshold; |
| |
| if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { |
| msg.type = WMA_INIT_THERMAL_INFO_CMD; |
| msg.bodyptr = pWmaParam; |
| |
| if (!QDF_IS_STATUS_SUCCESS |
| (scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &msg))) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post WMA_SET_THERMAL_INFO_CMD to WMA!", |
| __func__); |
| qdf_mem_free(pWmaParam); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_SUCCESS; |
| } |
| qdf_mem_free(pWmaParam); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| /** |
| * sme_add_set_thermal_level_callback() - Plug in set thermal level callback |
| * @hal: Handle returned by macOpen |
| * @callback: sme_set_thermal_level_callback |
| * |
| * Plug in set thermal level callback |
| * |
| * Return: none |
| */ |
| void sme_add_set_thermal_level_callback(mac_handle_t hal, |
| sme_set_thermal_level_callback callback) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(hal); |
| |
| pMac->sme.set_thermal_level_cb = callback; |
| } |
| |
| /** |
| * sme_set_thermal_level() - SME API to set the thermal mitigation level |
| * @hal: Handler to HAL |
| * @level: Thermal mitigation level |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_set_thermal_level(mac_handle_t hal, uint8_t level) |
| { |
| struct scheduler_msg msg = {0}; |
| tpAniSirGlobal pMac = PMAC_STRUCT(hal); |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| |
| if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { |
| qdf_mem_set(&msg, sizeof(msg), 0); |
| msg.type = WMA_SET_THERMAL_LEVEL; |
| msg.bodyval = level; |
| |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post WMA_SET_THERMAL_LEVEL to WMA!", |
| __func__); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_SUCCESS; |
| } |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| /* |
| * sme_txpower_limit() - |
| * SME API to set txpower limits |
| * |
| * mac_handle |
| * psmetx : power limits for 2g/5g |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_txpower_limit(mac_handle_t mac_handle, tSirTxPowerLimit *psmetx) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| struct scheduler_msg message = {0}; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| tSirTxPowerLimit *tx_power_limit; |
| |
| tx_power_limit = qdf_mem_malloc(sizeof(*tx_power_limit)); |
| if (!tx_power_limit) |
| return QDF_STATUS_E_FAILURE; |
| |
| *tx_power_limit = *psmetx; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| message.type = WMA_TX_POWER_LIMIT; |
| message.reserved = 0; |
| message.bodyptr = tx_power_limit; |
| |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: not able to post WMA_TX_POWER_LIMIT", |
| __func__); |
| status = QDF_STATUS_E_FAILURE; |
| qdf_mem_free(tx_power_limit); |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| QDF_STATUS sme_update_connect_debug(mac_handle_t mac_handle, uint32_t set_value) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| pMac->mlme_cfg->gen.debug_packet_log = set_value; |
| return status; |
| } |
| |
| /* |
| * sme_ap_disable_intra_bss_fwd() - |
| * SME will send message to WMA to set Intra BSS in txrx |
| * |
| * mac_handle - The handle returned by mac_open |
| * sessionId - session id ( vdev id) |
| * disablefwd - bool value that indicate disable intrabss fwd disable |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_ap_disable_intra_bss_fwd(mac_handle_t mac_handle, |
| uint8_t sessionId, |
| bool disablefwd) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| int status = QDF_STATUS_SUCCESS; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| struct scheduler_msg message = {0}; |
| tpDisableIntraBssFwd pSapDisableIntraFwd = NULL; |
| |
| /* Prepare the request to send to SME. */ |
| pSapDisableIntraFwd = qdf_mem_malloc(sizeof(tDisableIntraBssFwd)); |
| if (NULL == pSapDisableIntraFwd) { |
| sme_err("Memory Allocation Failure!!!"); |
| return QDF_STATUS_E_NOMEM; |
| } |
| |
| pSapDisableIntraFwd->sessionId = sessionId; |
| pSapDisableIntraFwd->disableintrabssfwd = disablefwd; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| /* serialize the req through MC thread */ |
| message.bodyptr = pSapDisableIntraFwd; |
| message.type = WMA_SET_SAP_INTRABSS_DIS; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| status = QDF_STATUS_E_FAILURE; |
| qdf_mem_free(pSapDisableIntraFwd); |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| #ifdef WLAN_FEATURE_STATS_EXT |
| |
| void sme_stats_ext_register_callback(mac_handle_t mac_handle, |
| stats_ext_cb callback) |
| { |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| |
| if (!mac) { |
| sme_err("Invalid mac context"); |
| return; |
| } |
| |
| mac->sme.stats_ext_cb = callback; |
| } |
| |
| void sme_stats_ext_deregister_callback(mac_handle_t mac_handle) |
| { |
| sme_stats_ext_register_callback(mac_handle, NULL); |
| } |
| |
| void sme_stats_ext2_register_callback(mac_handle_t mac_handle, |
| stats_ext2_cb callback) |
| { |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| |
| if (!mac) { |
| sme_err("Invalid mac context"); |
| return; |
| } |
| |
| mac->sme.stats_ext2_cb = callback; |
| } |
| |
| /* |
| * sme_stats_ext_request() - |
| * Function called when HDD receives STATS EXT vendor command from userspace |
| * |
| * sessionID - vdevID for the stats ext request |
| * input - Stats Ext Request structure ptr |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_stats_ext_request(uint8_t session_id, tpStatsExtRequestReq input) |
| { |
| struct scheduler_msg msg = {0}; |
| tpStatsExtRequest data; |
| size_t data_len; |
| |
| data_len = sizeof(tStatsExtRequest) + input->request_data_len; |
| data = qdf_mem_malloc(data_len); |
| if (!data) |
| return QDF_STATUS_E_NOMEM; |
| |
| data->vdev_id = session_id; |
| data->request_data_len = input->request_data_len; |
| if (input->request_data_len) |
| qdf_mem_copy(data->request_data, |
| input->request_data, input->request_data_len); |
| |
| msg.type = WMA_STATS_EXT_REQUEST; |
| msg.reserved = 0; |
| msg.bodyptr = data; |
| |
| if (QDF_STATUS_SUCCESS != scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &msg)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post WMA_STATS_EXT_REQUEST message to WMA", |
| __func__); |
| qdf_mem_free(data); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_stats_ext_event() - eWNI_SME_STATS_EXT_EVENT processor |
| * @mac: Global MAC context |
| * @msg: "stats ext" message |
| |
| * This callback function called when SME received eWNI_SME_STATS_EXT_EVENT |
| * response from WMA |
| * |
| * Return: QDF_STATUS |
| */ |
| static QDF_STATUS sme_stats_ext_event(tpAniSirGlobal mac, |
| struct stats_ext_event *msg) |
| { |
| if (!msg) { |
| sme_err("Null msg"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| if (mac->sme.stats_ext_cb) |
| mac->sme.stats_ext_cb(mac->hdd_handle, msg); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| #else |
| |
| static QDF_STATUS sme_stats_ext_event(tpAniSirGlobal mac, |
| struct stats_ext_event *msg) |
| { |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| #endif |
| |
| /* |
| * sme_update_dfs_scan_mode() - |
| * Update DFS roam scan mode |
| * This function is called through dynamic setConfig callback function |
| * to configure allowDFSChannelRoam. |
| * mac_handle - HAL handle for device |
| * sessionId - Session Identifier |
| * allowDFSChannelRoam - DFS roaming scan mode 0 (disable), |
| * 1 (passive), 2 (active) |
| * Return QDF_STATUS_SUCCESS - SME update DFS roaming scan config |
| * successfully. |
| * Other status means SME failed to update DFS roaming scan config. |
| */ |
| QDF_STATUS sme_update_dfs_scan_mode(mac_handle_t mac_handle, uint8_t sessionId, |
| uint8_t allowDFSChannelRoam) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| if (sessionId >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), sessionId); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "LFR runtime successfully set AllowDFSChannelRoam Mode to %d - old value is %d - roam state is %s", |
| allowDFSChannelRoam, |
| pMac->roam.configParam.allowDFSChannelRoam, |
| mac_trace_get_neighbour_roam_state(pMac->roam. |
| neighborRoamInfo |
| [sessionId]. |
| neighborRoamState)); |
| pMac->roam.configParam.allowDFSChannelRoam = |
| allowDFSChannelRoam; |
| if (pMac->roam.configParam.isRoamOffloadScanEnabled) { |
| csr_roam_offload_scan(pMac, sessionId, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, |
| REASON_ROAM_DFS_SCAN_MODE_CHANGED); |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| |
| |
| return status; |
| } |
| |
| /* |
| * sme_get_dfs_scan_mode() - get DFS roam scan mode |
| * This is a synchronous call |
| * |
| * mac_handle - The handle returned by mac_open. |
| * Return DFS roaming scan mode 0 (disable), 1 (passive), 2 (active) |
| */ |
| uint8_t sme_get_dfs_scan_mode(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| return pMac->roam.configParam.allowDFSChannelRoam; |
| } |
| |
| /* |
| * sme_modify_add_ie() - |
| * This function sends msg to updates the additional IE buffers in PE |
| * |
| * mac_handle - global structure |
| * pModifyIE - pointer to tModifyIE structure |
| * updateType - type of buffer |
| * Return Success or failure |
| */ |
| QDF_STATUS sme_modify_add_ie(mac_handle_t mac_handle, |
| tSirModifyIE *pModifyIE, eUpdateIEsType updateType) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_roam_modify_add_ies(pMac, pModifyIE, updateType); |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_update_add_ie() - |
| * This function sends msg to updates the additional IE buffers in PE |
| * |
| * mac_handle - global structure |
| * pUpdateIE - pointer to structure tUpdateIE |
| * updateType - type of buffer |
| * Return Success or failure |
| */ |
| QDF_STATUS sme_update_add_ie(mac_handle_t mac_handle, |
| tSirUpdateIE *pUpdateIE, eUpdateIEsType updateType) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = csr_roam_update_add_ies(pMac, pUpdateIE, updateType); |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /** |
| * sme_update_dsc_pto_up_mapping() |
| * @mac_handle: HAL context |
| * @dscpmapping: pointer to DSCP mapping structure |
| * @sessionId: SME session id |
| * |
| * This routine is called to update dscp mapping |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_update_dsc_pto_up_mapping(mac_handle_t mac_handle, |
| enum sme_qos_wmmuptype *dscpmapping, |
| uint8_t sessionId) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| uint8_t i, j, peSessionId; |
| struct csr_roam_session *pCsrSession = NULL; |
| tpPESession pSession = NULL; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| return status; |
| pCsrSession = CSR_GET_SESSION(pMac, sessionId); |
| if (pCsrSession == NULL) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Session lookup fails for CSR session")); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| if (!CSR_IS_SESSION_VALID(pMac, sessionId)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid session Id %u"), sessionId); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| pSession = pe_find_session_by_bssid(pMac, |
| pCsrSession->connectedProfile.bssid.bytes, |
| &peSessionId); |
| |
| if (pSession == NULL) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL(" Session lookup fails for BSSID")); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| if (!pSession->QosMapSet.present) { |
| sme_debug("QOS Mapping IE not present"); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| for (i = 0; i < SME_QOS_WMM_UP_MAX; i++) { |
| for (j = pSession->QosMapSet.dscp_range[i][0]; |
| j <= pSession->QosMapSet.dscp_range[i][1]; |
| j++) { |
| if ((pSession->QosMapSet.dscp_range[i][0] == 255) |
| && (pSession->QosMapSet.dscp_range[i][1] == |
| 255)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, |
| QDF_TRACE_LEVEL_DEBUG, |
| FL("User Priority %d isn't used"), i); |
| break; |
| } else { |
| dscpmapping[j] = i; |
| } |
| } |
| } |
| for (i = 0; i < pSession->QosMapSet.num_dscp_exceptions; i++) |
| if (pSession->QosMapSet.dscp_exceptions[i][0] != 255) |
| dscpmapping[pSession->QosMapSet.dscp_exceptions[i][0]] = |
| pSession->QosMapSet.dscp_exceptions[i][1]; |
| |
| sme_release_global_lock(&pMac->sme); |
| return status; |
| } |
| |
| /* |
| * sme_abort_roam_scan() - |
| * API to abort current roam scan cycle by roam scan offload module. |
| * |
| * mac_handle - The handle returned by mac_open. |
| * sessionId - Session Identifier |
| * Return QDF_STATUS |
| */ |
| |
| QDF_STATUS sme_abort_roam_scan(mac_handle_t mac_handle, uint8_t sessionId) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| if (pMac->roam.configParam.isRoamOffloadScanEnabled) { |
| /* acquire the lock for the sme object */ |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| csr_roam_offload_scan(pMac, sessionId, |
| ROAM_SCAN_OFFLOAD_ABORT_SCAN, |
| REASON_ROAM_ABORT_ROAM_SCAN); |
| /* release the lock for the sme object */ |
| sme_release_global_lock(&pMac->sme); |
| } |
| } |
| |
| return status; |
| } |
| |
| #ifdef FEATURE_WLAN_EXTSCAN |
| /** |
| * sme_get_valid_channels_by_band() - to fetch valid channels filtered by band |
| * @mac_handle: HAL context |
| * @wifiBand: RF band information |
| * @aValidChannels: output array to store channel info |
| * @pNumChannels: output number of channels |
| * |
| * SME API to fetch all valid channels filtered by band |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_get_valid_channels_by_band(mac_handle_t mac_handle, |
| uint8_t wifiBand, |
| uint32_t *aValidChannels, |
| uint8_t *pNumChannels) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| uint8_t chanList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = { 0 }; |
| uint8_t numChannels = 0; |
| uint8_t i = 0; |
| uint32_t totValidChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| |
| if (!aValidChannels || !pNumChannels) { |
| sme_err("Output channel list/NumChannels is NULL"); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| if (wifiBand >= WIFI_BAND_MAX) { |
| sme_err("Invalid wifiBand: %d", wifiBand); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| status = sme_get_cfg_valid_channels(&chanList[0], |
| &totValidChannels); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("Fail to get valid channel list (err=%d)", status); |
| return status; |
| } |
| |
| switch (wifiBand) { |
| case WIFI_BAND_UNSPECIFIED: |
| sme_debug("Unspec Band, return all %d valid channels", |
| totValidChannels); |
| numChannels = totValidChannels; |
| for (i = 0; i < totValidChannels; i++) |
| aValidChannels[i] = cds_chan_to_freq(chanList[i]); |
| break; |
| |
| case WIFI_BAND_BG: |
| sme_debug("WIFI_BAND_BG (2.4 GHz)"); |
| for (i = 0; i < totValidChannels; i++) { |
| if (WLAN_REG_IS_24GHZ_CH(chanList[i])) |
| aValidChannels[numChannels++] = |
| cds_chan_to_freq(chanList[i]); |
| } |
| break; |
| |
| case WIFI_BAND_A: |
| sme_debug("WIFI_BAND_A (5 GHz without DFS)"); |
| for (i = 0; i < totValidChannels; i++) { |
| if (WLAN_REG_IS_5GHZ_CH(chanList[i]) && |
| !wlan_reg_is_dfs_ch(mac_ctx->pdev, chanList[i])) |
| aValidChannels[numChannels++] = |
| cds_chan_to_freq(chanList[i]); |
| } |
| break; |
| |
| case WIFI_BAND_ABG: |
| sme_debug("WIFI_BAND_ABG (2.4 GHz + 5 GHz; no DFS)"); |
| for (i = 0; i < totValidChannels; i++) { |
| if ((WLAN_REG_IS_24GHZ_CH(chanList[i]) || |
| WLAN_REG_IS_5GHZ_CH(chanList[i])) && |
| !wlan_reg_is_dfs_ch(mac_ctx->pdev, chanList[i])) |
| aValidChannels[numChannels++] = |
| cds_chan_to_freq(chanList[i]); |
| } |
| break; |
| |
| case WIFI_BAND_A_DFS_ONLY: |
| sme_debug("WIFI_BAND_A_DFS (5 GHz DFS only)"); |
| for (i = 0; i < totValidChannels; i++) { |
| if (WLAN_REG_IS_5GHZ_CH(chanList[i]) && |
| wlan_reg_is_dfs_ch(mac_ctx->pdev, chanList[i])) |
| aValidChannels[numChannels++] = |
| cds_chan_to_freq(chanList[i]); |
| } |
| break; |
| |
| case WIFI_BAND_A_WITH_DFS: |
| sme_debug("WIFI_BAND_A_WITH_DFS (5 GHz with DFS)"); |
| for (i = 0; i < totValidChannels; i++) { |
| if (WLAN_REG_IS_5GHZ_CH(chanList[i])) |
| aValidChannels[numChannels++] = |
| cds_chan_to_freq(chanList[i]); |
| } |
| break; |
| |
| case WIFI_BAND_ABG_WITH_DFS: |
| sme_debug("WIFI_BAND_ABG_WITH_DFS (2.4 GHz+5 GHz with DFS)"); |
| for (i = 0; i < totValidChannels; i++) { |
| if (WLAN_REG_IS_24GHZ_CH(chanList[i]) || |
| WLAN_REG_IS_5GHZ_CH(chanList[i])) |
| aValidChannels[numChannels++] = |
| cds_chan_to_freq(chanList[i]); |
| } |
| break; |
| |
| default: |
| sme_err("Unknown wifiBand: %d", wifiBand); |
| return QDF_STATUS_E_INVAL; |
| } |
| *pNumChannels = numChannels; |
| |
| return status; |
| } |
| |
| QDF_STATUS |
| sme_ext_scan_get_capabilities(mac_handle_t mac_handle, |
| struct extscan_capabilities_params *params) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| struct scheduler_msg message = {0}; |
| struct extscan_capabilities_params *bodyptr; |
| |
| /* per contract must make a copy of the params when messaging */ |
| bodyptr = qdf_mem_malloc(sizeof(*bodyptr)); |
| if (!bodyptr) |
| return QDF_STATUS_E_NOMEM; |
| *bodyptr = *params; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| /* Serialize the req through MC thread */ |
| message.bodyptr = bodyptr; |
| message.type = WMA_EXTSCAN_GET_CAPABILITIES_REQ; |
| qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| NO_SESSION, message.type); |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| sme_release_global_lock(&mac->sme); |
| } |
| |
| if (QDF_IS_STATUS_ERROR(status)) { |
| sme_err("failure: %d", status); |
| qdf_mem_free(bodyptr); |
| } |
| return status; |
| } |
| |
| QDF_STATUS |
| sme_ext_scan_start(mac_handle_t mac_handle, |
| struct wifi_scan_cmd_req_params *params) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| struct scheduler_msg message = {0}; |
| struct wifi_scan_cmd_req_params *bodyptr; |
| |
| /* per contract must make a copy of the params when messaging */ |
| bodyptr = qdf_mem_malloc(sizeof(*bodyptr)); |
| if (!bodyptr) |
| return QDF_STATUS_E_NOMEM; |
| *bodyptr = *params; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| /* Serialize the req through MC thread */ |
| message.bodyptr = bodyptr; |
| message.type = WMA_EXTSCAN_START_REQ; |
| qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| NO_SESSION, message.type); |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| sme_release_global_lock(&mac->sme); |
| } |
| |
| if (QDF_IS_STATUS_ERROR(status)) { |
| sme_err("failure: %d", status); |
| qdf_mem_free(bodyptr); |
| } |
| return status; |
| } |
| |
| QDF_STATUS sme_ext_scan_stop(mac_handle_t mac_handle, |
| struct extscan_stop_req_params *params) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| struct scheduler_msg message = {0}; |
| struct extscan_stop_req_params *bodyptr; |
| |
| /* per contract must make a copy of the params when messaging */ |
| bodyptr = qdf_mem_malloc(sizeof(*bodyptr)); |
| if (!bodyptr) |
| return QDF_STATUS_E_NOMEM; |
| *bodyptr = *params; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| /* Serialize the req through MC thread */ |
| message.bodyptr = bodyptr; |
| message.type = WMA_EXTSCAN_STOP_REQ; |
| qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| NO_SESSION, message.type); |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| sme_release_global_lock(&mac->sme); |
| } |
| |
| if (QDF_IS_STATUS_ERROR(status)) { |
| sme_err("failure: %d", status); |
| qdf_mem_free(bodyptr); |
| } |
| return status; |
| } |
| |
| QDF_STATUS |
| sme_set_bss_hotlist(mac_handle_t mac_handle, |
| struct extscan_bssid_hotlist_set_params *params) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| struct scheduler_msg message = {0}; |
| struct extscan_bssid_hotlist_set_params *bodyptr; |
| |
| /* per contract must make a copy of the params when messaging */ |
| bodyptr = qdf_mem_malloc(sizeof(*bodyptr)); |
| if (!bodyptr) |
| return QDF_STATUS_E_NOMEM; |
| |
| *bodyptr = *params; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| /* Serialize the req through MC thread */ |
| message.bodyptr = bodyptr; |
| message.type = WMA_EXTSCAN_SET_BSSID_HOTLIST_REQ; |
| qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| NO_SESSION, message.type); |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| sme_release_global_lock(&mac->sme); |
| } |
| |
| if (QDF_IS_STATUS_ERROR(status)) { |
| sme_err("failure: %d", status); |
| qdf_mem_free(bodyptr); |
| } |
| return status; |
| } |
| |
| QDF_STATUS |
| sme_reset_bss_hotlist(mac_handle_t mac_handle, |
| struct extscan_bssid_hotlist_reset_params *params) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| struct scheduler_msg message = {0}; |
| struct extscan_bssid_hotlist_reset_params *bodyptr; |
| |
| /* per contract must make a copy of the params when messaging */ |
| bodyptr = qdf_mem_malloc(sizeof(*bodyptr)); |
| if (!bodyptr) |
| return QDF_STATUS_E_NOMEM; |
| |
| *bodyptr = *params; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| /* Serialize the req through MC thread */ |
| message.bodyptr = bodyptr; |
| message.type = WMA_EXTSCAN_RESET_BSSID_HOTLIST_REQ; |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| NO_SESSION, message.type)); |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| sme_release_global_lock(&mac->sme); |
| } |
| |
| if (QDF_IS_STATUS_ERROR(status)) { |
| sme_err("failure: %d", status); |
| qdf_mem_free(bodyptr); |
| } |
| return status; |
| } |
| |
| QDF_STATUS |
| sme_set_significant_change(mac_handle_t mac_handle, |
| struct extscan_set_sig_changereq_params *params) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| struct scheduler_msg message = {0}; |
| struct extscan_set_sig_changereq_params *bodyptr; |
| |
| /* per contract must make a copy of the params when messaging */ |
| bodyptr = qdf_mem_malloc(sizeof(*bodyptr)); |
| if (!bodyptr) |
| return QDF_STATUS_E_NOMEM; |
| |
| *bodyptr = *params; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| /* Serialize the req through MC thread */ |
| message.bodyptr = bodyptr; |
| message.type = WMA_EXTSCAN_SET_SIGNF_CHANGE_REQ; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| sme_release_global_lock(&mac->sme); |
| } |
| if (QDF_IS_STATUS_ERROR(status)) { |
| sme_err("failure: %d", status); |
| qdf_mem_free(bodyptr); |
| } |
| return status; |
| } |
| |
| QDF_STATUS |
| sme_reset_significant_change(mac_handle_t mac_handle, |
| struct extscan_capabilities_reset_params *params) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| struct scheduler_msg message = {0}; |
| struct extscan_capabilities_reset_params *bodyptr; |
| |
| /* per contract must make a copy of the params when messaging */ |
| bodyptr = qdf_mem_malloc(sizeof(*bodyptr)); |
| if (!bodyptr) |
| return QDF_STATUS_E_NOMEM; |
| |
| *bodyptr = *params; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| /* Serialize the req through MC thread */ |
| message.bodyptr = bodyptr; |
| message.type = WMA_EXTSCAN_RESET_SIGNF_CHANGE_REQ; |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| NO_SESSION, message.type)); |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| sme_release_global_lock(&mac->sme); |
| } |
| if (QDF_IS_STATUS_ERROR(status)) { |
| sme_err("failure: %d", status); |
| qdf_mem_free(bodyptr); |
| } |
| |
| return status; |
| } |
| |
| QDF_STATUS |
| sme_get_cached_results(mac_handle_t mac_handle, |
| struct extscan_cached_result_params *params) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| struct scheduler_msg message = {0}; |
| struct extscan_cached_result_params *bodyptr; |
| |
| /* per contract must make a copy of the params when messaging */ |
| bodyptr = qdf_mem_malloc(sizeof(*bodyptr)); |
| if (!bodyptr) |
| return QDF_STATUS_E_NOMEM; |
| *bodyptr = *params; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| /* Serialize the req through MC thread */ |
| message.bodyptr = bodyptr; |
| message.type = WMA_EXTSCAN_GET_CACHED_RESULTS_REQ; |
| qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| NO_SESSION, message.type); |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| sme_release_global_lock(&mac->sme); |
| } |
| |
| if (QDF_IS_STATUS_ERROR(status)) { |
| sme_err("failure: %d", status); |
| qdf_mem_free(bodyptr); |
| } |
| return status; |
| } |
| |
| QDF_STATUS sme_set_epno_list(mac_handle_t mac_handle, |
| struct wifi_enhanced_pno_params *params) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| struct scheduler_msg message = {0}; |
| struct wifi_enhanced_pno_params *req_msg; |
| int len; |
| |
| SME_ENTER(); |
| |
| /* per contract must make a copy of the params when messaging */ |
| len = sizeof(*req_msg) + |
| (params->num_networks * sizeof(req_msg->networks[0])); |
| |
| req_msg = qdf_mem_malloc(len); |
| if (!req_msg) |
| return QDF_STATUS_E_NOMEM; |
| qdf_mem_copy(req_msg, params, len); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("sme_acquire_global_lock failed!(status=%d)", |
| status); |
| qdf_mem_free(req_msg); |
| return status; |
| } |
| |
| /* Serialize the req through MC thread */ |
| message.bodyptr = req_msg; |
| message.type = WMA_SET_EPNO_LIST_REQ; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("scheduler_post_msg failed!(err=%d)", status); |
| qdf_mem_free(req_msg); |
| } |
| sme_release_global_lock(&mac->sme); |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_set_passpoint_list(mac_handle_t mac_handle, |
| struct wifi_passpoint_req_param *params) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| struct scheduler_msg message = {0}; |
| struct wifi_passpoint_req_param *req_msg; |
| int len; |
| |
| SME_ENTER(); |
| |
| len = sizeof(*req_msg) + |
| (params->num_networks * sizeof(params->networks[0])); |
| req_msg = qdf_mem_malloc(len); |
| if (!req_msg) |
| return QDF_STATUS_E_NOMEM; |
| qdf_mem_copy(req_msg, params, len); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("sme_acquire_global_lock failed!(status=%d)", |
| status); |
| qdf_mem_free(req_msg); |
| return status; |
| } |
| |
| /* Serialize the req through MC thread */ |
| message.bodyptr = req_msg; |
| message.type = WMA_SET_PASSPOINT_LIST_REQ; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("scheduler_post_msg failed!(err=%d)", |
| status); |
| qdf_mem_free(req_msg); |
| } |
| sme_release_global_lock(&mac->sme); |
| return status; |
| } |
| |
| QDF_STATUS sme_reset_passpoint_list(mac_handle_t mac_handle, |
| struct wifi_passpoint_req_param *params) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| struct scheduler_msg message = {0}; |
| struct wifi_passpoint_req_param *req_msg; |
| |
| SME_ENTER(); |
| |
| req_msg = qdf_mem_malloc(sizeof(*req_msg)); |
| if (!req_msg) |
| return QDF_STATUS_E_NOMEM; |
| *req_msg = *params; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("sme_acquire_global_lock failed!(status=%d)", |
| status); |
| qdf_mem_free(req_msg); |
| return status; |
| } |
| |
| /* Serialize the req through MC thread */ |
| message.bodyptr = req_msg; |
| message.type = WMA_RESET_PASSPOINT_LIST_REQ; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("scheduler_post_msg failed!(err=%d)", |
| status); |
| qdf_mem_free(req_msg); |
| } |
| sme_release_global_lock(&mac->sme); |
| return status; |
| } |
| |
| QDF_STATUS sme_ext_scan_register_callback(mac_handle_t mac_handle, |
| ext_scan_ind_cb ext_scan_ind_cb) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| mac->sme.ext_scan_ind_cb = ext_scan_ind_cb; |
| sme_release_global_lock(&mac->sme); |
| } |
| return status; |
| } |
| #endif /* FEATURE_WLAN_EXTSCAN */ |
| |
| /** |
| * sme_send_wisa_params(): Pass WISA mode to WMA |
| * @hal: HAL context |
| * @wisa_params: pointer to WISA params struct |
| * @sessionId: SME session id |
| * |
| * Pass WISA params to WMA |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_set_wisa_params(mac_handle_t hal, |
| struct sir_wisa_params *wisa_params) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| struct scheduler_msg message = {0}; |
| struct sir_wisa_params *cds_msg_wisa_params; |
| |
| cds_msg_wisa_params = qdf_mem_malloc(sizeof(struct sir_wisa_params)); |
| if (!cds_msg_wisa_params) |
| return QDF_STATUS_E_NOMEM; |
| |
| *cds_msg_wisa_params = *wisa_params; |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| message.bodyptr = cds_msg_wisa_params; |
| message.type = WMA_SET_WISA_PARAMS; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| sme_release_global_lock(&mac->sme); |
| } |
| return status; |
| } |
| |
| #ifdef WLAN_FEATURE_LINK_LAYER_STATS |
| |
| /* |
| * sme_ll_stats_clear_req() - |
| * SME API to clear Link Layer Statistics |
| * |
| * mac_handle |
| * pclearStatsReq: Link Layer clear stats request params structure |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_ll_stats_clear_req(mac_handle_t mac_handle, |
| tSirLLStatsClearReq *pclearStatsReq) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| tSirLLStatsClearReq *clear_stats_req; |
| |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "staId = %u", pclearStatsReq->staId); |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "statsClearReqMask = 0x%X", |
| pclearStatsReq->statsClearReqMask); |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "stopReq = %u", pclearStatsReq->stopReq); |
| if (!sme_is_session_id_valid(mac_handle, pclearStatsReq->staId)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: invalid staId %d", |
| __func__, pclearStatsReq->staId); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| clear_stats_req = qdf_mem_malloc(sizeof(*clear_stats_req)); |
| if (!clear_stats_req) |
| return QDF_STATUS_E_NOMEM; |
| |
| *clear_stats_req = *pclearStatsReq; |
| |
| if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { |
| /* Serialize the req through MC thread */ |
| message.bodyptr = clear_stats_req; |
| message.type = WMA_LINK_LAYER_STATS_CLEAR_REQ; |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| NO_SESSION, message.type)); |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: not able to post WMA_LL_STATS_CLEAR_REQ", |
| __func__); |
| qdf_mem_free(clear_stats_req); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: sme_acquire_global_lock error", __func__); |
| qdf_mem_free(clear_stats_req); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_ll_stats_set_req() - |
| * SME API to set the Link Layer Statistics |
| * |
| * mac_handle |
| * psetStatsReq: Link Layer set stats request params structure |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_ll_stats_set_req(mac_handle_t mac_handle, tSirLLStatsSetReq |
| *psetStatsReq) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| tSirLLStatsSetReq *set_stats_req; |
| |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: MPDU Size = %u", __func__, |
| psetStatsReq->mpduSizeThreshold); |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| " Aggressive Stats Collections = %u", |
| psetStatsReq->aggressiveStatisticsGathering); |
| |
| set_stats_req = qdf_mem_malloc(sizeof(*set_stats_req)); |
| if (!set_stats_req) |
| return QDF_STATUS_E_NOMEM; |
| |
| *set_stats_req = *psetStatsReq; |
| |
| if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { |
| /* Serialize the req through MC thread */ |
| message.bodyptr = set_stats_req; |
| message.type = WMA_LINK_LAYER_STATS_SET_REQ; |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| NO_SESSION, message.type)); |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: not able to post WMA_LL_STATS_SET_REQ", |
| __func__); |
| qdf_mem_free(set_stats_req); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: sme_acquire_global_lock error", __func__); |
| qdf_mem_free(set_stats_req); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_ll_stats_get_req(mac_handle_t mac_handle, |
| tSirLLStatsGetReq *get_stats_req, |
| void *context) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| struct scheduler_msg message = {0}; |
| tSirLLStatsGetReq *ll_stats_get_req; |
| |
| ll_stats_get_req = qdf_mem_malloc(sizeof(*ll_stats_get_req)); |
| if (!ll_stats_get_req) |
| return QDF_STATUS_E_NOMEM; |
| |
| *ll_stats_get_req = *get_stats_req; |
| |
| mac->sme.ll_stats_context = context; |
| if (sme_acquire_global_lock(&mac->sme) == QDF_STATUS_SUCCESS) { |
| /* Serialize the req through MC thread */ |
| message.bodyptr = ll_stats_get_req; |
| message.type = WMA_LINK_LAYER_STATS_GET_REQ; |
| qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| NO_SESSION, message.type); |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("Not able to post WMA_LL_STATS_GET_REQ"); |
| qdf_mem_free(ll_stats_get_req); |
| } |
| sme_release_global_lock(&mac->sme); |
| } else { |
| sme_err("sme_acquire_global_lock error"); |
| qdf_mem_free(ll_stats_get_req); |
| } |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_set_link_layer_stats_ind_cb(mac_handle_t mac_handle, |
| link_layer_stats_cb callback) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| mac->sme.link_layer_stats_cb = callback; |
| sme_release_global_lock(&mac->sme); |
| } else { |
| sme_err("sme_acquire_global_lock error"); |
| } |
| |
| return status; |
| } |
| |
| /** |
| * sme_set_link_layer_ext_cb() - Register callback for link layer statistics |
| * @hal: Mac global handle |
| * @ll_stats_ext_cb: HDD callback which needs to be invoked after getting |
| * status notification from FW |
| * |
| * Return: eHalStatus |
| */ |
| QDF_STATUS sme_set_link_layer_ext_cb(mac_handle_t hal, void (*ll_stats_ext_cb) |
| (hdd_handle_t callback_ctx, tSirLLStatsResults |
| *rsp)) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (status == QDF_STATUS_SUCCESS) { |
| mac->sme.link_layer_stats_ext_cb = ll_stats_ext_cb; |
| sme_release_global_lock(&mac->sme); |
| } else |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: sme_qcquire_global_lock error", __func__); |
| return status; |
| } |
| |
| /** |
| * sme_reset_link_layer_stats_ind_cb() - SME API to reset link layer stats |
| * indication |
| * @mac_handle: Hal Handle |
| * |
| * This function reset's the link layer stats indication |
| * |
| * Return: QDF_STATUS Enumeration |
| */ |
| |
| QDF_STATUS sme_reset_link_layer_stats_ind_cb(mac_handle_t mac_handle) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal pmac; |
| |
| if (!mac_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("mac_handle is not valid")); |
| return QDF_STATUS_E_INVAL; |
| } |
| pmac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pmac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| pmac->sme.link_layer_stats_cb = NULL; |
| sme_release_global_lock(&pmac->sme); |
| } else |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: sme_acquire_global_lock error", __func__); |
| |
| return status; |
| } |
| |
| /** |
| * sme_ll_stats_set_thresh - set threshold for mac counters |
| * @hal, hal layer handle |
| * @threshold, threshold for mac counters |
| * |
| * Return: QDF_STATUS Enumeration |
| */ |
| QDF_STATUS sme_ll_stats_set_thresh(mac_handle_t hal, |
| struct sir_ll_ext_stats_threshold *threshold) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac; |
| struct scheduler_msg message = {0}; |
| struct sir_ll_ext_stats_threshold *thresh; |
| |
| if (!threshold) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("threshold is not valid")); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| if (!hal) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("hal is not valid")); |
| return QDF_STATUS_E_INVAL; |
| } |
| mac = PMAC_STRUCT(hal); |
| |
| thresh = qdf_mem_malloc(sizeof(*thresh)); |
| if (!thresh) |
| return QDF_STATUS_E_NOMEM; |
| |
| *thresh = *threshold; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| /* Serialize the req through MC thread */ |
| message.bodyptr = thresh; |
| message.type = WDA_LINK_LAYER_STATS_SET_THRESHOLD; |
| MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG, |
| NO_SESSION, message.type)); |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: not able to post WDA_LL_STATS_GET_REQ", |
| __func__); |
| qdf_mem_free(thresh); |
| } |
| sme_release_global_lock(&mac->sme); |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("sme_acquire_global_lock error")); |
| qdf_mem_free(thresh); |
| } |
| return status; |
| } |
| |
| #endif /* WLAN_FEATURE_LINK_LAYER_STATS */ |
| |
| #ifdef WLAN_POWER_DEBUGFS |
| /** |
| * sme_power_debug_stats_req() - SME API to collect Power debug stats |
| * @callback_fn: Pointer to the callback function for Power stats event |
| * @power_stats_context: Pointer to context |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_power_debug_stats_req(mac_handle_t hal, void (*callback_fn) |
| (struct power_stats_response *response, |
| void *context), void *power_stats_context) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct scheduler_msg msg = {0}; |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (!callback_fn) { |
| sme_err("Indication callback did not registered"); |
| sme_release_global_lock(&mac_ctx->sme); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| mac_ctx->sme.power_debug_stats_context = power_stats_context; |
| mac_ctx->sme.power_stats_resp_callback = callback_fn; |
| msg.bodyptr = NULL; |
| msg.type = WMA_POWER_DEBUG_STATS_REQ; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| sme_err("not able to post WDA_POWER_DEBUG_STATS_REQ"); |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| return status; |
| } |
| #endif |
| |
| #ifdef WLAN_FEATURE_ROAM_OFFLOAD |
| /** |
| * sme_update_roam_key_mgmt_offload_enabled() - enable/disable key mgmt offload |
| * This is a synchronous call |
| * @hal_ctx: The handle returned by mac_open. |
| * @session_id: Session Identifier |
| * @key_mgmt_offload_enabled: key mgmt enable/disable flag |
| * @pmkid_modes: PMKID modes of PMKSA caching and OKC |
| * Return: QDF_STATUS_SUCCESS - SME updated config successfully. |
| * Other status means SME is failed to update. |
| */ |
| |
| QDF_STATUS sme_update_roam_key_mgmt_offload_enabled(mac_handle_t hal_ctx, |
| uint8_t session_id, |
| bool key_mgmt_offload_enabled, |
| struct pmkid_mode_bits *pmkid_modes) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| if (CSR_IS_SESSION_VALID(mac_ctx, session_id)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: LFR3: key_mgmt_offload_enabled changed to %d", |
| __func__, key_mgmt_offload_enabled); |
| status = csr_roam_set_key_mgmt_offload(mac_ctx, |
| session_id, |
| key_mgmt_offload_enabled, |
| pmkid_modes); |
| } else |
| status = QDF_STATUS_E_INVAL; |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| |
| return status; |
| } |
| #endif |
| |
| /* |
| * sme_get_temperature() - |
| * SME API to get the pdev temperature |
| * |
| * mac_handle |
| * temperature context |
| * pCallbackfn: callback fn with response (temperature) |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_get_temperature(mac_handle_t mac_handle, |
| void *tempContext, |
| void (*pCallbackfn)(int temperature, |
| void *pContext)) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| if ((NULL == pCallbackfn) && |
| (NULL == pMac->sme.pGetTemperatureCb)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "Indication Call back did not registered"); |
| sme_release_global_lock(&pMac->sme); |
| return QDF_STATUS_E_FAILURE; |
| } else if (NULL != pCallbackfn) { |
| pMac->sme.pTemperatureCbContext = tempContext; |
| pMac->sme.pGetTemperatureCb = pCallbackfn; |
| } |
| /* serialize the req through MC thread */ |
| message.bodyptr = NULL; |
| message.type = WMA_GET_TEMPERATURE_REQ; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Post Get Temperature msg fail")); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| /* |
| * sme_set_scanning_mac_oui() - |
| * SME API to set scanning mac oui |
| * |
| * mac_handle |
| * pScanMacOui: Scanning Mac Oui (input 3 bytes) |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_set_scanning_mac_oui(mac_handle_t mac_handle, tSirScanMacOui |
| *pScanMacOui) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| /* Serialize the req through MC thread */ |
| message.bodyptr = pScanMacOui; |
| message.type = WMA_SET_SCAN_MAC_OUI_REQ; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Msg post Set Scan Mac OUI failed")); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| #ifdef DHCP_SERVER_OFFLOAD |
| /* |
| * sme_set_dhcp_srv_offload() - |
| * SME API to set DHCP server offload info |
| * |
| * mac_handle |
| * pDhcpSrvInfo : DHCP server offload info struct |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_set_dhcp_srv_offload(mac_handle_t mac_handle, |
| tSirDhcpSrvOffloadInfo *pDhcpSrvInfo) |
| { |
| struct scheduler_msg message = {0}; |
| tSirDhcpSrvOffloadInfo *pSmeDhcpSrvInfo; |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| pSmeDhcpSrvInfo = qdf_mem_malloc(sizeof(*pSmeDhcpSrvInfo)); |
| if (!pSmeDhcpSrvInfo) |
| return QDF_STATUS_E_NOMEM; |
| |
| *pSmeDhcpSrvInfo = *pDhcpSrvInfo; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| /* serialize the req through MC thread */ |
| message.type = WMA_SET_DHCP_SERVER_OFFLOAD_CMD; |
| message.bodyptr = pSmeDhcpSrvInfo; |
| |
| if (!QDF_IS_STATUS_SUCCESS |
| (scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message))) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s:WMA_SET_DHCP_SERVER_OFFLOAD_CMD failed", |
| __func__); |
| qdf_mem_free(pSmeDhcpSrvInfo); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&pMac->sme); |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: sme_acquire_global_lock error!", __func__); |
| qdf_mem_free(pSmeDhcpSrvInfo); |
| } |
| |
| return status; |
| } |
| #endif /* DHCP_SERVER_OFFLOAD */ |
| |
| QDF_STATUS sme_send_unit_test_cmd(uint32_t vdev_id, uint32_t module_id, |
| uint32_t arg_count, uint32_t *arg) |
| { |
| return wma_form_unit_test_cmd_and_send(vdev_id, module_id, |
| arg_count, arg); |
| } |
| |
| #ifdef WLAN_FEATURE_GPIO_LED_FLASHING |
| /* |
| * sme_set_led_flashing() - |
| * API to set the Led flashing parameters. |
| * |
| * mac_handle - The handle returned by mac_open. |
| * x0, x1 - led flashing parameters |
| * Return QDF_STATUS |
| */ |
| QDF_STATUS sme_set_led_flashing(mac_handle_t mac_handle, uint8_t type, |
| uint32_t x0, uint32_t x1) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| struct scheduler_msg message = {0}; |
| struct flashing_req_params *ledflashing; |
| |
| ledflashing = qdf_mem_malloc(sizeof(*ledflashing)); |
| if (!ledflashing) |
| return QDF_STATUS_E_NOMEM; |
| |
| ledflashing->req_id = 0; |
| ledflashing->pattern_id = type; |
| ledflashing->led_x0 = x0; |
| ledflashing->led_x1 = x1; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| /* Serialize the req through MC thread */ |
| message.bodyptr = ledflashing; |
| message.type = WMA_LED_FLASHING_REQ; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| sme_release_global_lock(&pMac->sme); |
| } |
| if (!QDF_IS_STATUS_SUCCESS(status)) |
| qdf_mem_free(ledflashing); |
| |
| return status; |
| } |
| #endif |
| |
| /** |
| * sme_handle_dfS_chan_scan() - handle DFS channel configuration |
| * @mac_handle: corestack handler |
| * @dfs_flag: flag indicating dfs channel enable/disable |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_handle_dfs_chan_scan(mac_handle_t mac_handle, uint8_t dfs_flag) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| |
| if (QDF_STATUS_SUCCESS == status) { |
| |
| mac->scan.fEnableDFSChnlScan = dfs_flag; |
| |
| /* update the channel list to the firmware */ |
| status = csr_update_channel_list(mac); |
| |
| sme_release_global_lock(&mac->sme); |
| } |
| |
| return status; |
| } |
| |
| /** |
| * sme_enable_dfS_chan_scan() - set DFS channel scan enable/disable |
| * @mac_handle: corestack handler |
| * @dfs_flag: flag indicating dfs channel enable/disable |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_enable_dfs_chan_scan(mac_handle_t mac_handle, uint8_t dfs_flag) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac; |
| |
| if (!mac_handle) { |
| sme_err("hal is NULL"); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| mac = PMAC_STRUCT(mac_handle); |
| |
| mac->scan.fEnableDFSChnlScan = dfs_flag; |
| |
| return status; |
| } |
| |
| #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH |
| /** |
| * sme_validate_sap_channel_switch() - validate target channel switch w.r.t |
| * concurreny rules set to avoid channel interference. |
| * @hal - Hal context |
| * @sap_ch - channel to switch |
| * @sap_phy_mode - phy mode of SAP |
| * @cc_switch_mode - concurreny switch mode |
| * @session_id - sme session id. |
| * |
| * Return: true if there is no channel interference else return false |
| */ |
| bool sme_validate_sap_channel_switch(mac_handle_t hal, |
| uint16_t sap_ch, eCsrPhyMode sap_phy_mode, uint8_t cc_switch_mode, |
| uint8_t session_id) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| struct csr_roam_session *session = CSR_GET_SESSION(mac, session_id); |
| uint16_t intf_channel = 0; |
| |
| if (!session) |
| return false; |
| |
| session->ch_switch_in_progress = true; |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| intf_channel = csr_check_concurrent_channel_overlap(mac, sap_ch, |
| sap_phy_mode, |
| cc_switch_mode); |
| sme_release_global_lock(&mac->sme); |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("sme_acquire_global_lock error!")); |
| session->ch_switch_in_progress = false; |
| return false; |
| } |
| |
| session->ch_switch_in_progress = false; |
| return (intf_channel == 0) ? true : false; |
| } |
| #endif |
| |
| /** |
| * sme_configure_stats_avg_factor() - function to config avg. stats factor |
| * @hal: hal |
| * @session_id: session ID |
| * @stats_avg_factor: average stats factor |
| * |
| * This function configures the stats avg factor in firmware |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_configure_stats_avg_factor(mac_handle_t hal, uint8_t session_id, |
| uint16_t stats_avg_factor) |
| { |
| struct scheduler_msg msg = {0}; |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| struct sir_stats_avg_factor *stats_factor; |
| |
| stats_factor = qdf_mem_malloc(sizeof(*stats_factor)); |
| if (!stats_factor) |
| return QDF_STATUS_E_NOMEM; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| |
| if (QDF_STATUS_SUCCESS == status) { |
| |
| stats_factor->vdev_id = session_id; |
| stats_factor->stats_avg_factor = stats_avg_factor; |
| |
| /* serialize the req through MC thread */ |
| msg.type = SIR_HAL_CONFIG_STATS_FACTOR; |
| msg.bodyptr = stats_factor; |
| |
| if (!QDF_IS_STATUS_SUCCESS( |
| scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg))) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post SIR_HAL_CONFIG_STATS_FACTOR to WMA!", |
| __func__); |
| qdf_mem_free(stats_factor); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&mac->sme); |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: sme_acquire_global_lock error!", |
| __func__); |
| qdf_mem_free(stats_factor); |
| } |
| |
| return status; |
| } |
| |
| /** |
| * sme_configure_guard_time() - function to configure guard time |
| * @hal: hal |
| * @session_id: session id |
| * @guard_time: guard time |
| * |
| * This function configures the guard time in firmware |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_configure_guard_time(mac_handle_t hal, uint8_t session_id, |
| uint32_t guard_time) |
| { |
| struct scheduler_msg msg = {0}; |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| struct sir_guard_time_request *g_time; |
| |
| g_time = qdf_mem_malloc(sizeof(*g_time)); |
| if (!g_time) |
| return QDF_STATUS_E_NOMEM; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| |
| if (QDF_STATUS_SUCCESS == status) { |
| |
| g_time->vdev_id = session_id; |
| g_time->guard_time = guard_time; |
| |
| /* serialize the req through MC thread */ |
| msg.type = SIR_HAL_CONFIG_GUARD_TIME; |
| msg.bodyptr = g_time; |
| |
| if (!QDF_IS_STATUS_SUCCESS( |
| scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg))) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post SIR_HAL_CONFIG_GUARD_TIME to WMA!", |
| __func__); |
| qdf_mem_free(g_time); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&mac->sme); |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: sme_acquire_global_lock error!", |
| __func__); |
| qdf_mem_free(g_time); |
| } |
| |
| return status; |
| } |
| |
| /* |
| * sme_wifi_start_logger() - Send the start/stop logging command to WMA |
| * to either start/stop logging |
| * @hal: HAL context |
| * @start_log: Structure containing the wifi start logger params |
| * |
| * This function sends the start/stop logging command to WMA |
| * |
| * Return: QDF_STATUS_SUCCESS on successful posting |
| */ |
| QDF_STATUS sme_wifi_start_logger(mac_handle_t hal, |
| struct sir_wifi_start_log start_log) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| struct scheduler_msg message = {0}; |
| struct sir_wifi_start_log *req_msg; |
| uint32_t len; |
| |
| len = sizeof(*req_msg); |
| req_msg = qdf_mem_malloc(len); |
| if (!req_msg) |
| return QDF_STATUS_E_NOMEM; |
| |
| req_msg->verbose_level = start_log.verbose_level; |
| req_msg->is_iwpriv_command = start_log.is_iwpriv_command; |
| req_msg->ring_id = start_log.ring_id; |
| req_msg->ini_triggered = start_log.ini_triggered; |
| req_msg->user_triggered = start_log.user_triggered; |
| req_msg->size = start_log.size; |
| req_msg->is_pktlog_buff_clear = start_log.is_pktlog_buff_clear; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (status != QDF_STATUS_SUCCESS) { |
| sme_err("sme_acquire_global_lock failed(status=%d)", status); |
| qdf_mem_free(req_msg); |
| return status; |
| } |
| |
| /* Serialize the req through MC thread */ |
| message.bodyptr = req_msg; |
| message.type = SIR_HAL_START_STOP_LOGGING; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("scheduler_post_msg failed!(err=%d)", status); |
| qdf_mem_free(req_msg); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&mac->sme); |
| |
| return status; |
| } |
| |
| /** |
| * sme_neighbor_middle_of_roaming() - Function to know if |
| * STA is in the middle of roaming states |
| * @hal: Handle returned by macOpen |
| * @sessionId: sessionId of the STA session |
| * |
| * This function is a wrapper to call |
| * csr_neighbor_middle_of_roaming to know STA is in the |
| * middle of roaming states |
| * |
| * Return: True or False |
| * |
| */ |
| bool sme_neighbor_middle_of_roaming(mac_handle_t mac_handle, uint8_t sessionId) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| bool val = false; |
| |
| if (CSR_IS_SESSION_VALID(mac_ctx, sessionId)) |
| val = csr_neighbor_middle_of_roaming(mac_ctx, sessionId); |
| else |
| sme_debug("Invalid Session: %d", sessionId); |
| |
| return val; |
| } |
| |
| bool sme_is_any_session_in_middle_of_roaming(mac_handle_t hal) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| uint8_t session_id; |
| |
| for (session_id = 0; session_id < CSR_ROAM_SESSION_MAX; session_id++) { |
| if (CSR_IS_SESSION_VALID(mac_ctx, session_id) && |
| csr_neighbor_middle_of_roaming(mac_ctx, session_id)) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /* |
| * sme_send_flush_logs_cmd_to_fw() - Flush FW logs |
| * @mac: MAC handle |
| * |
| * This function is used to send the command that will |
| * be used to flush the logs in the firmware |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_send_flush_logs_cmd_to_fw(tpAniSirGlobal mac) |
| { |
| QDF_STATUS status; |
| struct scheduler_msg message = {0}; |
| |
| /* Serialize the req through MC thread */ |
| message.bodyptr = NULL; |
| message.type = SIR_HAL_FLUSH_LOG_TO_FW; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("scheduler_post_msg failed!(err=%d)", status); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| return status; |
| } |
| |
| QDF_STATUS sme_enable_uapsd_for_ac(uint8_t sta_id, |
| sme_ac_enum_type ac, uint8_t tid, |
| uint8_t pri, uint32_t srvc_int, |
| uint32_t sus_int, |
| enum sme_qos_wmm_dir_type dir, |
| uint8_t psb, uint32_t sessionId, |
| uint32_t delay_interval) |
| { |
| void *wma_handle; |
| t_wma_trigger_uapsd_params uapsd_params; |
| enum uapsd_ac access_category; |
| |
| if (!psb) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "No need to configure auto trigger:psb is 0"); |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "wma_handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| switch (ac) { |
| case SME_AC_BK: |
| access_category = UAPSD_BK; |
| break; |
| case SME_AC_BE: |
| access_category = UAPSD_BE; |
| break; |
| case SME_AC_VI: |
| access_category = UAPSD_VI; |
| break; |
| case SME_AC_VO: |
| access_category = UAPSD_VO; |
| break; |
| default: |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| uapsd_params.wmm_ac = access_category; |
| uapsd_params.user_priority = pri; |
| uapsd_params.service_interval = srvc_int; |
| uapsd_params.delay_interval = delay_interval; |
| uapsd_params.suspend_interval = sus_int; |
| |
| if (QDF_STATUS_SUCCESS != |
| wma_trigger_uapsd_params(wma_handle, sessionId, &uapsd_params)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "Failed to Trigger Uapsd params for sessionId %d", |
| sessionId); |
| return QDF_STATUS_E_FAILURE; |
| } |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS sme_disable_uapsd_for_ac(uint8_t sta_id, |
| sme_ac_enum_type ac, |
| uint32_t sessionId) |
| { |
| void *wma_handle; |
| enum uapsd_ac access_category; |
| |
| switch (ac) { |
| case SME_AC_BK: |
| access_category = UAPSD_BK; |
| break; |
| case SME_AC_BE: |
| access_category = UAPSD_BE; |
| break; |
| case SME_AC_VI: |
| access_category = UAPSD_VI; |
| break; |
| case SME_AC_VO: |
| access_category = UAPSD_VO; |
| break; |
| default: |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "wma handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| if (QDF_STATUS_SUCCESS != |
| wma_disable_uapsd_per_ac(wma_handle, sessionId, access_category)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "Failed to disable uapsd for ac %d for sessionId %d", |
| ac, sessionId); |
| return QDF_STATUS_E_FAILURE; |
| } |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_update_nss() - SME API to change the number for spatial streams |
| * (1 or 2) |
| * @hal: Handle returned by mac open |
| * @nss: Number of spatial streams |
| * |
| * This function is used to update the number of spatial streams supported. |
| * |
| * Return: Success upon successfully changing nss else failure |
| * |
| */ |
| QDF_STATUS sme_update_nss(mac_handle_t mac_handle, uint8_t nss) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| uint32_t i; |
| struct mlme_ht_capabilities_info *ht_cap_info; |
| struct csr_roam_session *csr_session; |
| struct mlme_vht_capabilities_info vht_cap_info; |
| |
| vht_cap_info = mac_ctx->mlme_cfg->vht_caps.vht_cap_info; |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| |
| if (QDF_STATUS_SUCCESS == status) { |
| vht_cap_info.enable2x2 = (nss == 1) ? 0 : 1; |
| |
| /* get the HT capability info*/ |
| ht_cap_info = &mac_ctx->mlme_cfg->ht_caps.ht_cap_info; |
| |
| for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { |
| if (CSR_IS_SESSION_VALID(mac_ctx, i)) { |
| csr_session = &mac_ctx->roam.roamSession[i]; |
| csr_session->htConfig.ht_tx_stbc = |
| ht_cap_info->tx_stbc; |
| } |
| } |
| |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| return status; |
| } |
| |
| /** |
| * sme_update_user_configured_nss() - sets the nss based on user request |
| * @hal: Pointer to HAL |
| * @nss: number of streams |
| * |
| * Return: None |
| */ |
| void sme_update_user_configured_nss(mac_handle_t hal, uint8_t nss) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| mac_ctx->user_configured_nss = nss; |
| } |
| |
| int sme_update_tx_bfee_supp(mac_handle_t hal, uint8_t session_id, |
| uint8_t cfg_val) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| mac_ctx->mlme_cfg->vht_caps.vht_cap_info.su_bformee = cfg_val; |
| |
| return sme_update_he_tx_bfee_supp(hal, session_id, cfg_val); |
| } |
| |
| int sme_update_tx_bfee_nsts(mac_handle_t hal, uint8_t session_id, |
| uint8_t usr_cfg_val, uint8_t nsts_val) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| uint8_t nsts_set_val; |
| |
| mac_ctx->usr_cfg_tx_bfee_nsts = usr_cfg_val; |
| if (usr_cfg_val) |
| nsts_set_val = usr_cfg_val; |
| else |
| nsts_set_val = nsts_val; |
| |
| mac_ctx->mlme_cfg->vht_caps.vht_cap_info.tx_bfee_ant_supp = |
| nsts_set_val; |
| |
| if (usr_cfg_val) |
| sme_set_he_tx_bf_cbf_rates(session_id); |
| |
| return sme_update_he_tx_bfee_nsts(hal, session_id, nsts_set_val); |
| } |
| #ifdef WLAN_FEATURE_11AX |
| void sme_update_tgt_he_cap(mac_handle_t mac_handle, |
| struct wma_tgt_cfg *cfg, |
| tDot11fIEhe_cap *he_cap_ini) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| |
| qdf_mem_copy(&mac_ctx->he_cap_2g, |
| &cfg->he_cap_2g, |
| sizeof(tDot11fIEhe_cap)); |
| |
| qdf_mem_copy(&mac_ctx->he_cap_5g, |
| &cfg->he_cap_5g, |
| sizeof(tDot11fIEhe_cap)); |
| |
| /* modify HE Caps field according to INI setting */ |
| mac_ctx->he_cap_2g.bfee_sts_lt_80 = |
| QDF_MIN(cfg->he_cap_2g.bfee_sts_lt_80, |
| he_cap_ini->bfee_sts_lt_80); |
| |
| mac_ctx->he_cap_5g.bfee_sts_lt_80 = |
| QDF_MIN(cfg->he_cap_5g.bfee_sts_lt_80, |
| he_cap_ini->bfee_sts_lt_80); |
| } |
| |
| void sme_update_he_cap_nss(mac_handle_t hal, uint8_t session_id, |
| uint8_t nss) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct csr_roam_session *csr_session; |
| uint32_t tx_mcs_map = 0; |
| uint32_t rx_mcs_map = 0; |
| uint32_t mcs_map = 0; |
| |
| if (!nss || (nss > 2)) { |
| sme_err("invalid Nss value %d", nss); |
| } |
| csr_session = CSR_GET_SESSION(mac_ctx, session_id); |
| sme_cfg_get_int(hal, WNI_CFG_HE_RX_MCS_MAP_LT_80, &rx_mcs_map); |
| sme_cfg_get_int(hal, WNI_CFG_HE_TX_MCS_MAP_LT_80, &tx_mcs_map); |
| mcs_map = rx_mcs_map & 0x3; |
| if (nss == 1) { |
| tx_mcs_map = HE_SET_MCS_4_NSS(tx_mcs_map, HE_MCS_DISABLE, 2); |
| rx_mcs_map = HE_SET_MCS_4_NSS(rx_mcs_map, HE_MCS_DISABLE, 2); |
| } else { |
| tx_mcs_map = HE_SET_MCS_4_NSS(tx_mcs_map, mcs_map, 2); |
| rx_mcs_map = HE_SET_MCS_4_NSS(rx_mcs_map, mcs_map, 2); |
| } |
| sme_info("new HE Nss MCS MAP: Rx 0x%0X, Tx: 0x%0X", |
| rx_mcs_map, tx_mcs_map); |
| sme_cfg_set_int(hal, WNI_CFG_HE_RX_MCS_MAP_LT_80, rx_mcs_map); |
| sme_cfg_set_int(hal, WNI_CFG_HE_TX_MCS_MAP_LT_80, tx_mcs_map); |
| csr_update_session_he_cap(mac_ctx, csr_session); |
| |
| } |
| |
| int sme_update_he_mcs(mac_handle_t hal, uint8_t session_id, uint16_t he_mcs) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct csr_roam_session *csr_session; |
| uint16_t mcs_val = 0; |
| uint16_t mcs_map = HE_MCS_ALL_DISABLED; |
| uint32_t wni_cfg_tx_param = 0; |
| uint32_t wni_cfg_rx_param = 0; |
| |
| csr_session = CSR_GET_SESSION(mac_ctx, session_id); |
| if (!csr_session) { |
| sme_err("No session for id %d", session_id); |
| return -EINVAL; |
| } |
| if ((he_mcs & 0x3) == HE_MCS_DISABLE) { |
| sme_err("Invalid HE MCS 0x%0x, can't disable 0-7 for 1ss", |
| he_mcs); |
| return -EINVAL; |
| } |
| mcs_val = he_mcs & 0x3; |
| switch (he_mcs) { |
| case HE_80_MCS0_7: |
| case HE_80_MCS0_9: |
| case HE_80_MCS0_11: |
| if (mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable2x2) { |
| mcs_map = HE_SET_MCS_4_NSS(mcs_map, mcs_val, 1); |
| mcs_map = HE_SET_MCS_4_NSS(mcs_map, mcs_val, 2); |
| } else { |
| mcs_map = HE_SET_MCS_4_NSS(mcs_map, mcs_val, 1); |
| } |
| wni_cfg_tx_param = WNI_CFG_HE_TX_MCS_MAP_LT_80; |
| wni_cfg_rx_param = WNI_CFG_HE_RX_MCS_MAP_LT_80; |
| break; |
| |
| case HE_160_MCS0_7: |
| case HE_160_MCS0_9: |
| case HE_160_MCS0_11: |
| mcs_map = HE_SET_MCS_4_NSS(mcs_map, mcs_val, 1); |
| wni_cfg_tx_param = WNI_CFG_HE_TX_MCS_MAP_160; |
| wni_cfg_rx_param = WNI_CFG_HE_RX_MCS_MAP_160; |
| break; |
| |
| case HE_80p80_MCS0_7: |
| case HE_80p80_MCS0_9: |
| case HE_80p80_MCS0_11: |
| mcs_map = HE_SET_MCS_4_NSS(mcs_map, mcs_val, 1); |
| wni_cfg_tx_param = WNI_CFG_HE_TX_MCS_MAP_80_80; |
| wni_cfg_rx_param = WNI_CFG_HE_RX_MCS_MAP_80_80; |
| break; |
| |
| default: |
| sme_err("Invalid HE MCS 0x%0x", he_mcs); |
| return -EINVAL; |
| } |
| sme_info("new HE MCS 0x%0x", mcs_map); |
| sme_cfg_set_int(hal, wni_cfg_tx_param, mcs_map); |
| sme_cfg_set_int(hal, wni_cfg_rx_param, mcs_map); |
| csr_update_session_he_cap(mac_ctx, csr_session); |
| |
| return 0; |
| } |
| |
| static int sme_update_he_cap(mac_handle_t hal, uint8_t session_id, |
| uint16_t he_cap, int value) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct csr_roam_session *session; |
| |
| session = CSR_GET_SESSION(mac_ctx, session_id); |
| if (!session) { |
| sme_err("No session for id %d", session_id); |
| return -EINVAL; |
| } |
| sme_cfg_set_int(hal, he_cap, value); |
| csr_update_session_he_cap(mac_ctx, session); |
| |
| return 0; |
| } |
| |
| void sme_set_usr_cfg_mu_edca(mac_handle_t hal, bool val) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| mac_ctx->usr_cfg_mu_edca_params = val; |
| } |
| |
| int sme_update_mu_edca_params(mac_handle_t hal, uint8_t session_id) |
| { |
| struct scheduler_msg msg = {0}; |
| QDF_STATUS status; |
| |
| qdf_mem_zero(&msg, sizeof(msg)); |
| msg.type = WNI_SME_UPDATE_MU_EDCA_PARAMS; |
| msg.reserved = 0; |
| msg.bodyval = session_id; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_PE, |
| QDF_MODULE_ID_PE, &msg); |
| if (status != QDF_STATUS_SUCCESS) { |
| sme_err("Not able to post update edca profile"); |
| return -EIO; |
| } |
| |
| return 0; |
| } |
| void sme_set_he_mu_edca_def_cfg(mac_handle_t hal) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| uint8_t i; |
| |
| sme_debug("Set MU EDCA params to default"); |
| for (i = 0; i < MAX_NUM_AC; i++) { |
| mac_ctx->usr_mu_edca_params[i].aci.aifsn = MU_EDCA_DEF_AIFSN; |
| mac_ctx->usr_mu_edca_params[i].aci.aci = i; |
| mac_ctx->usr_mu_edca_params[i].cw.max = MU_EDCA_DEF_CW_MAX; |
| mac_ctx->usr_mu_edca_params[i].cw.min = MU_EDCA_DEF_CW_MIN; |
| mac_ctx->usr_mu_edca_params[i].mu_edca_timer = |
| MU_EDCA_DEF_TIMER; |
| } |
| } |
| |
| int sme_update_he_tx_bfee_supp(mac_handle_t hal, uint8_t session_id, |
| uint8_t cfg_val) |
| { |
| return sme_update_he_cap(hal, session_id, WNI_CFG_HE_SU_BEAMFORMEE, |
| cfg_val); |
| } |
| |
| int sme_update_he_trigger_frm_mac_pad(mac_handle_t hal, uint8_t session_id, |
| uint8_t cfg_val) |
| { |
| return sme_update_he_cap(hal, session_id, WNI_CFG_HE_TRIG_PAD, |
| cfg_val); |
| } |
| |
| int sme_update_he_om_ctrl_supp(mac_handle_t hal, uint8_t session_id, |
| uint8_t cfg_val) |
| { |
| return sme_update_he_cap(hal, session_id, WNI_CFG_HE_OMI, |
| cfg_val); |
| } |
| |
| int sme_send_he_om_ctrl_bw_update(mac_handle_t hal, uint8_t session_id, |
| uint8_t cfg_val) |
| { |
| uint32_t om_ctrl_cmd[NUM_OM_CTRL_UPDATE_CFG_PARAMS] = {0}; |
| QDF_STATUS status; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, session_id); |
| |
| if (!session) { |
| sme_err("Session does not exist, Session_id: %d", session_id); |
| return -EINVAL; |
| } |
| if (!csr_is_conn_state_connected_infra(mac_ctx, session_id)) { |
| sme_info("STA is not connected, Session_id: %d", session_id); |
| return -EINVAL; |
| } |
| if (cfg_val > session->connectedProfile.vht_channel_width) { |
| sme_info("OM ctrl BW %d is greater than connected BW %d", |
| cfg_val, session->connectedProfile.vht_channel_width); |
| return -EINVAL; |
| } |
| mac_ctx->he_om_ctrl_cfg_bw_set = true; |
| mac_ctx->he_om_ctrl_cfg_bw = cfg_val; |
| om_ctrl_cmd[0] = 1; |
| qdf_mem_copy((void *)&om_ctrl_cmd[OM_CTRL_CMD_MAC_BITS31], |
| (void *)session->connectedProfile.bssid.bytes, |
| sizeof(uint32_t)); |
| qdf_mem_copy((void *)&om_ctrl_cmd[OM_CTRL_CMD_MAC_BITS47], |
| (void *)&session->connectedProfile.bssid.bytes[4], |
| sizeof(uint16_t)); |
| if (mac_ctx->he_om_ctrl_cfg_nss_set) { |
| om_ctrl_cmd[OM_CTRL_CMD_RX_NSS] = |
| mac_ctx->he_om_ctrl_cfg_nss - 1; |
| om_ctrl_cmd[OM_CTRL_CMD_TX_NSS] = |
| mac_ctx->he_om_ctrl_cfg_nss - 1; |
| } else { |
| om_ctrl_cmd[OM_CTRL_CMD_RX_NSS] = session->nss - 1; |
| om_ctrl_cmd[OM_CTRL_CMD_TX_NSS] = session->nss - 1; |
| } |
| om_ctrl_cmd[OM_CTRL_CMD_BW] = cfg_val; |
| om_ctrl_cmd[OM_CTRL_CMD_ULMU] = 1; |
| status = wma_form_unit_test_cmd_and_send(session_id, 13, 7, |
| om_ctrl_cmd); |
| if (QDF_STATUS_SUCCESS != status) { |
| sme_err("send_unit_test_cmd returned %d", status); |
| return -EIO; |
| } |
| |
| return 0; |
| } |
| |
| int sme_send_he_om_ctrl_nss_update(mac_handle_t hal, uint8_t session_id, |
| uint8_t cfg_val) |
| { |
| uint32_t om_ctrl_cmd[NUM_OM_CTRL_UPDATE_CFG_PARAMS] = {0}; |
| QDF_STATUS status; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, session_id); |
| |
| if (!session) { |
| sme_err("Session does not exist, Session_id: %d", session_id); |
| return -EINVAL; |
| } |
| if (!csr_is_conn_state_connected_infra(mac_ctx, session_id)) { |
| sme_info("STA not in connected state Session_id: %d", |
| session_id); |
| return -EINVAL; |
| } |
| if (cfg_val > session->nss) { |
| sme_info("OM ctrl Nss %d is greater than connected Nss %d", |
| cfg_val, session->nss); |
| return -EINVAL; |
| } |
| mac_ctx->he_om_ctrl_cfg_nss_set = true; |
| mac_ctx->he_om_ctrl_cfg_nss = cfg_val; |
| om_ctrl_cmd[0] = 1; |
| qdf_mem_copy((void *)&om_ctrl_cmd[OM_CTRL_CMD_MAC_BITS31], |
| (void *)session->connectedProfile.bssid.bytes, |
| sizeof(uint32_t)); |
| qdf_mem_copy((void *)&om_ctrl_cmd[OM_CTRL_CMD_MAC_BITS47], |
| (void *)&session->connectedProfile.bssid.bytes[4], |
| sizeof(uint16_t)); |
| |
| if (mac_ctx->he_om_ctrl_cfg_bw_set) |
| om_ctrl_cmd[OM_CTRL_CMD_BW] = mac_ctx->he_om_ctrl_cfg_bw; |
| else |
| om_ctrl_cmd[OM_CTRL_CMD_BW] = |
| session->connectedProfile.vht_channel_width; |
| |
| om_ctrl_cmd[OM_CTRL_CMD_RX_NSS] = cfg_val - 1; |
| om_ctrl_cmd[OM_CTRL_CMD_TX_NSS] = cfg_val - 1; |
| om_ctrl_cmd[OM_CTRL_CMD_ULMU] = 1; |
| status = wma_form_unit_test_cmd_and_send(session_id, 13, 7, |
| om_ctrl_cmd); |
| if (QDF_STATUS_SUCCESS != status) { |
| sme_err("send_unit_test_cmd returned %d", status); |
| return -EIO; |
| } |
| |
| return 0; |
| } |
| |
| void sme_reset_he_om_ctrl(mac_handle_t hal) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| mac_ctx->he_om_ctrl_cfg_bw_set = false; |
| mac_ctx->he_om_ctrl_cfg_nss_set = false; |
| mac_ctx->he_om_ctrl_cfg_bw = 0; |
| mac_ctx->he_om_ctrl_cfg_nss = 0; |
| } |
| |
| int sme_update_he_tx_bfee_nsts(mac_handle_t hal, uint8_t session_id, |
| uint8_t cfg_val) |
| { |
| return sme_update_he_cap(hal, session_id, WNI_CFG_HE_BFEE_STS_LT80, |
| cfg_val); |
| } |
| |
| void sme_set_he_tx_bf_cbf_rates(uint8_t session_id) |
| { |
| uint32_t tx_bf_cbf_rates_5g[] = {91, 1, 0, 3, 2, 4, 0}; |
| uint32_t tx_bf_cbf_rates_2g[] = {91, 1, 1, 3, 1, 3, 0}; |
| QDF_STATUS status; |
| |
| status = wma_form_unit_test_cmd_and_send(session_id, 0x48, 7, |
| tx_bf_cbf_rates_5g); |
| if (QDF_STATUS_SUCCESS != status) |
| sme_err("send_unit_test_cmd returned %d", status); |
| |
| status = wma_form_unit_test_cmd_and_send(session_id, 0x48, 7, |
| tx_bf_cbf_rates_2g); |
| if (QDF_STATUS_SUCCESS != status) |
| sme_err("send_unit_test_cmd returned %d", status); |
| } |
| |
| void sme_config_su_ppdu_queue(uint8_t session_id, bool enable) |
| { |
| uint32_t su_ppdu_enable[] = {69, 1, 1, 1}; |
| uint32_t su_ppdu_disable[] = {69, 1, 1, 0}; |
| QDF_STATUS status; |
| |
| if (enable) { |
| sme_debug("Send Tx SU PPDU queue ENABLE cmd to FW"); |
| status = wma_form_unit_test_cmd_and_send(session_id, 0x48, 4, |
| su_ppdu_enable); |
| } else { |
| sme_debug("Send Tx SU PPDU queue DISABLE cmd to FW"); |
| status = wma_form_unit_test_cmd_and_send(session_id, 0x48, 4, |
| su_ppdu_disable); |
| } |
| if (QDF_STATUS_SUCCESS != status) |
| sme_err("send_unit_test_cmd returned %d", status); |
| } |
| |
| int sme_update_he_tx_stbc_cap(mac_handle_t hal, uint8_t session_id, int value) |
| { |
| int ret; |
| uint32_t he_cap_val = 0; |
| |
| he_cap_val = value ? 1 : 0; |
| |
| ret = sme_update_he_cap(hal, session_id, |
| WNI_CFG_HE_TX_STBC_LT80, he_cap_val); |
| if (ret) |
| return ret; |
| |
| return sme_update_he_cap(hal, session_id, |
| WNI_CFG_HE_TX_STBC_GT80, he_cap_val); |
| } |
| |
| int sme_update_he_rx_stbc_cap(mac_handle_t hal, uint8_t session_id, int value) |
| { |
| int ret; |
| uint32_t he_cap_val = 0; |
| |
| he_cap_val = value ? 1 : 0; |
| |
| ret = sme_update_he_cap(hal, session_id, |
| WNI_CFG_HE_RX_STBC_LT80, he_cap_val); |
| if (ret) |
| return ret; |
| |
| return sme_update_he_cap(hal, session_id, |
| WNI_CFG_HE_RX_STBC_GT80, he_cap_val); |
| } |
| |
| int sme_update_he_frag_supp(mac_handle_t hal, uint8_t session_id, |
| uint16_t he_frag) |
| { |
| return sme_update_he_cap(hal, session_id, |
| WNI_CFG_HE_FRAGMENTATION, he_frag); |
| } |
| |
| int sme_update_he_ldpc_supp(mac_handle_t hal, uint8_t session_id, |
| uint16_t he_ldpc) |
| { |
| return sme_update_he_cap(hal, session_id, WNI_CFG_HE_LDPC, he_ldpc); |
| } |
| #endif |
| |
| /** |
| * sme_set_nud_debug_stats_cb() - set nud debug stats callback |
| * @hal: global hal handle |
| * @cb: callback function pointer |
| * @context: callback context |
| * |
| * This function stores nud debug stats callback function. |
| * |
| * Return: QDF_STATUS enumeration. |
| */ |
| QDF_STATUS sme_set_nud_debug_stats_cb(mac_handle_t hal, |
| void (*cb)(void *, struct rsp_stats *, void *), |
| void *context) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac; |
| |
| if (!hal) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("hal is not valid")); |
| return QDF_STATUS_E_INVAL; |
| } |
| mac = PMAC_STRUCT(hal); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("sme_acquire_global_lock failed!(status=%d)"), |
| status); |
| return status; |
| } |
| |
| mac->sme.get_arp_stats_cb = cb; |
| mac->sme.get_arp_stats_context = context; |
| sme_release_global_lock(&mac->sme); |
| return status; |
| } |
| |
| /** |
| * sme_is_any_session_in_connected_state() - SME wrapper API to |
| * check if any session is in connected state or not. |
| * |
| * @hal: Handle returned by mac open |
| * |
| * This function is used to check if any valid sme session is in |
| * connected state or not. |
| * |
| * Return: true if any session is connected, else false. |
| * |
| */ |
| bool sme_is_any_session_in_connected_state(mac_handle_t mac_handle) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status; |
| bool ret = false; |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| ret = csr_is_any_session_in_connect_state(mac_ctx); |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| return ret; |
| } |
| |
| QDF_STATUS sme_set_chip_pwr_save_fail_cb(mac_handle_t mac_handle, |
| pwr_save_fail_cb cb) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (status != QDF_STATUS_SUCCESS) { |
| sme_err("sme_AcquireGlobalLock failed!(status=%d)", status); |
| return status; |
| } |
| mac->sme.chip_power_save_fail_cb = cb; |
| sme_release_global_lock(&mac->sme); |
| return status; |
| } |
| |
| #ifdef FEATURE_RSSI_MONITOR |
| /** |
| * sme_set_rssi_monitoring() - set rssi monitoring |
| * @hal: global hal handle |
| * @input: request message |
| * |
| * This function constructs the vos message and fill in message type, |
| * bodyptr with @input and posts it to WDA queue. |
| * |
| * Return: QDF_STATUS enumeration |
| */ |
| QDF_STATUS sme_set_rssi_monitoring(mac_handle_t hal, |
| struct rssi_monitor_req *input) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| struct scheduler_msg message = {0}; |
| struct rssi_monitor_req *req_msg; |
| |
| SME_ENTER(); |
| req_msg = qdf_mem_malloc(sizeof(*req_msg)); |
| if (!req_msg) |
| return QDF_STATUS_E_NOMEM; |
| |
| *req_msg = *input; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("sme_acquire_global_lock failed!(status=%d)", status); |
| qdf_mem_free(req_msg); |
| return status; |
| } |
| |
| /* Serialize the req through MC thread */ |
| message.bodyptr = req_msg; |
| message.type = WMA_SET_RSSI_MONITOR_REQ; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("scheduler_post_msg failed!(err=%d)", status); |
| qdf_mem_free(req_msg); |
| } |
| sme_release_global_lock(&mac->sme); |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_set_rssi_threshold_breached_cb(mac_handle_t mac_handle, |
| rssi_threshold_breached_cb cb) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac; |
| |
| mac = MAC_CONTEXT(mac_handle); |
| if (!mac) { |
| sme_err("Invalid mac context"); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("sme_acquire_global_lock failed!(status=%d)", |
| status); |
| return status; |
| } |
| |
| mac->sme.rssi_threshold_breached_cb = cb; |
| sme_release_global_lock(&mac->sme); |
| return status; |
| } |
| #endif /* FEATURE_RSSI_MONITOR */ |
| |
| QDF_STATUS sme_reset_rssi_threshold_breached_cb(mac_handle_t mac_handle) |
| { |
| return sme_set_rssi_threshold_breached_cb(mac_handle, NULL); |
| } |
| |
| static enum band_info sme_get_connected_roaming_vdev_band(void) |
| { |
| enum band_info band = BAND_ALL; |
| tpAniSirGlobal mac = sme_get_mac_context(); |
| struct csr_roam_session *session; |
| uint8_t session_id, channel; |
| |
| if (!mac) { |
| sme_debug("MAC Context is NULL"); |
| return band; |
| } |
| session_id = csr_get_roam_enabled_sta_sessionid(mac); |
| if (session_id != CSR_SESSION_ID_INVALID) { |
| session = CSR_GET_SESSION(mac, session_id); |
| channel = session->connectedProfile.operationChannel; |
| band = csr_get_rf_band(channel); |
| return band; |
| } |
| |
| return band; |
| } |
| |
| /* |
| * sme_pdev_set_pcl() - Send WMI_PDEV_SET_PCL_CMDID to the WMA |
| * @hal: Handle returned by macOpen |
| * @msg: PCL channel list and length structure |
| * |
| * Sends the command to WMA to send WMI_PDEV_SET_PCL_CMDID to FW |
| * Return: QDF_STATUS_SUCCESS on successful posting |
| */ |
| QDF_STATUS sme_pdev_set_pcl(struct policy_mgr_pcl_list *msg) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = sme_get_mac_context(); |
| struct scheduler_msg message = {0}; |
| struct set_pcl_req *req_msg; |
| uint32_t i; |
| |
| if (!mac) { |
| sme_err("mac is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| if (!msg) { |
| sme_err("msg is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| req_msg = qdf_mem_malloc(sizeof(*req_msg)); |
| if (!req_msg) |
| return QDF_STATUS_E_NOMEM; |
| |
| req_msg->band = BAND_ALL; |
| if (CSR_IS_ROAM_INTRA_BAND_ENABLED(mac)) { |
| req_msg->band = sme_get_connected_roaming_vdev_band(); |
| sme_debug("Connected STA band %d", req_msg->band); |
| } |
| for (i = 0; i < msg->pcl_len; i++) { |
| req_msg->chan_weights.pcl_list[i] = msg->pcl_list[i]; |
| req_msg->chan_weights.weight_list[i] = msg->weight_list[i]; |
| } |
| |
| req_msg->chan_weights.pcl_len = msg->pcl_len; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (status != QDF_STATUS_SUCCESS) { |
| sme_err("sme_acquire_global_lock failed!(status=%d)", status); |
| qdf_mem_free(req_msg); |
| return status; |
| } |
| |
| /* Serialize the req through MC thread */ |
| message.bodyptr = req_msg; |
| message.type = SIR_HAL_PDEV_SET_PCL_TO_FW; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("scheduler_post_msg failed!(err=%d)", status); |
| qdf_mem_free(req_msg); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&mac->sme); |
| |
| return status; |
| } |
| |
| /* |
| * sme_pdev_set_hw_mode() - Send WMI_PDEV_SET_HW_MODE_CMDID to the WMA |
| * @hal: Handle returned by macOpen |
| * @msg: HW mode structure containing hw mode and callback details |
| * |
| * Sends the command to CSR to send WMI_PDEV_SET_HW_MODE_CMDID to FW |
| * Return: QDF_STATUS_SUCCESS on successful posting |
| */ |
| QDF_STATUS sme_pdev_set_hw_mode(struct policy_mgr_hw_mode msg) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = sme_get_mac_context(); |
| tSmeCmd *cmd = NULL; |
| |
| if (!mac) { |
| sme_err("mac is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| status = sme_acquire_global_lock(&mac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("Failed to acquire lock"); |
| return QDF_STATUS_E_RESOURCES; |
| } |
| |
| cmd = csr_get_command_buffer(mac); |
| if (!cmd) { |
| sme_err("Get command buffer failed"); |
| sme_release_global_lock(&mac->sme); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| cmd->command = e_sme_command_set_hw_mode; |
| cmd->sessionId = msg.session_id; |
| cmd->u.set_hw_mode_cmd.hw_mode_index = msg.hw_mode_index; |
| cmd->u.set_hw_mode_cmd.set_hw_mode_cb = msg.set_hw_mode_cb; |
| cmd->u.set_hw_mode_cmd.reason = msg.reason; |
| cmd->u.set_hw_mode_cmd.session_id = msg.session_id; |
| cmd->u.set_hw_mode_cmd.next_action = msg.next_action; |
| cmd->u.set_hw_mode_cmd.context = msg.context; |
| |
| sme_debug("Queuing set hw mode to CSR, session: %d reason: %d", |
| cmd->u.set_hw_mode_cmd.session_id, |
| cmd->u.set_hw_mode_cmd.reason); |
| csr_queue_sme_command(mac, cmd, false); |
| |
| sme_release_global_lock(&mac->sme); |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_register_hw_mode_trans_cb() - HW mode transition callback registration |
| * @hal: Handle returned by macOpen |
| * @callback: HDD callback to be registered |
| * |
| * Registers the HDD callback with SME. This callback will be invoked when |
| * HW mode transition event is received from the FW |
| * |
| * Return: None |
| */ |
| void sme_register_hw_mode_trans_cb(mac_handle_t hal, |
| hw_mode_transition_cb callback) |
| { |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| |
| mac->sme.sme_hw_mode_trans_cb = callback; |
| } |
| |
| /** |
| * sme_nss_update_request() - Send beacon templete update to FW with new |
| * nss value |
| * @hal: Handle returned by macOpen |
| * @vdev_id: the session id |
| * @new_nss: the new nss value |
| * @cback: hdd callback |
| * @next_action: next action to happen at policy mgr after beacon update |
| * @original_vdev_id: original request hwmode change vdev id |
| * |
| * Sends the command to CSR to send to PE |
| * Return: QDF_STATUS_SUCCESS on successful posting |
| */ |
| QDF_STATUS sme_nss_update_request(uint32_t vdev_id, |
| uint8_t new_nss, policy_mgr_nss_update_cback cback, |
| uint8_t next_action, struct wlan_objmgr_psoc *psoc, |
| enum policy_mgr_conn_update_reason reason, |
| uint32_t original_vdev_id) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal mac = sme_get_mac_context(); |
| tSmeCmd *cmd = NULL; |
| |
| if (!mac) { |
| sme_err("mac is null"); |
| return status; |
| } |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| cmd = csr_get_command_buffer(mac); |
| if (!cmd) { |
| sme_err("Get command buffer failed"); |
| sme_release_global_lock(&mac->sme); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| cmd->command = e_sme_command_nss_update; |
| /* Sessionized modules may require this info */ |
| cmd->sessionId = vdev_id; |
| cmd->u.nss_update_cmd.new_nss = new_nss; |
| cmd->u.nss_update_cmd.session_id = vdev_id; |
| cmd->u.nss_update_cmd.nss_update_cb = cback; |
| cmd->u.nss_update_cmd.context = psoc; |
| cmd->u.nss_update_cmd.next_action = next_action; |
| cmd->u.nss_update_cmd.reason = reason; |
| cmd->u.nss_update_cmd.original_vdev_id = original_vdev_id; |
| |
| sme_debug("Queuing e_sme_command_nss_update to CSR:vdev (%d %d) ss %d r %d", |
| vdev_id, original_vdev_id, new_nss, reason); |
| csr_queue_sme_command(mac, cmd, false); |
| sme_release_global_lock(&mac->sme); |
| } |
| return status; |
| } |
| |
| /** |
| * sme_soc_set_dual_mac_config() - Set dual mac configurations |
| * @hal: Handle returned by macOpen |
| * @msg: Structure containing the dual mac config parameters |
| * |
| * Queues configuration information to CSR to configure |
| * WLAN firmware for the dual MAC features |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_soc_set_dual_mac_config(struct policy_mgr_dual_mac_config msg) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = sme_get_mac_context(); |
| tSmeCmd *cmd; |
| |
| if (!mac) { |
| sme_err("mac is null"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| status = sme_acquire_global_lock(&mac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("Failed to acquire lock"); |
| return QDF_STATUS_E_RESOURCES; |
| } |
| |
| cmd = csr_get_command_buffer(mac); |
| if (!cmd) { |
| sme_err("Get command buffer failed"); |
| sme_release_global_lock(&mac->sme); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| cmd->command = e_sme_command_set_dual_mac_config; |
| cmd->u.set_dual_mac_cmd.scan_config = msg.scan_config; |
| cmd->u.set_dual_mac_cmd.fw_mode_config = msg.fw_mode_config; |
| cmd->u.set_dual_mac_cmd.set_dual_mac_cb = msg.set_dual_mac_cb; |
| |
| sme_debug("set_dual_mac_config scan_config: %x fw_mode_config: %x", |
| cmd->u.set_dual_mac_cmd.scan_config, |
| cmd->u.set_dual_mac_cmd.fw_mode_config); |
| csr_queue_sme_command(mac, cmd, false); |
| |
| sme_release_global_lock(&mac->sme); |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| #ifdef FEATURE_LFR_SUBNET_DETECTION |
| /** |
| * sme_gateway_param_update() - to update gateway parameters with WMA |
| * @Hal: hal handle |
| * @gw_params: request parameters from HDD |
| * |
| * Return: QDF_STATUS |
| * |
| * This routine will update gateway parameters to WMA |
| */ |
| QDF_STATUS sme_gateway_param_update(mac_handle_t Hal, |
| struct gateway_param_update_req *gw_params) |
| { |
| QDF_STATUS qdf_status; |
| struct scheduler_msg message = {0}; |
| struct gateway_param_update_req *request_buf; |
| |
| request_buf = qdf_mem_malloc(sizeof(*request_buf)); |
| if (!request_buf) |
| return QDF_STATUS_E_NOMEM; |
| |
| *request_buf = *gw_params; |
| |
| message.type = WMA_GW_PARAM_UPDATE_REQ; |
| message.reserved = 0; |
| message.bodyptr = request_buf; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "Not able to post WMA_GW_PARAM_UPDATE_REQ message to HAL"); |
| qdf_mem_free(request_buf); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| #endif /* FEATURE_LFR_SUBNET_DETECTION */ |
| |
| /** |
| * sme_soc_set_antenna_mode() - set antenna mode |
| * @hal: Handle returned by macOpen |
| * @msg: Structure containing the antenna mode parameters |
| * |
| * Send the command to CSR to send |
| * WMI_SOC_SET_ANTENNA_MODE_CMDID to FW |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_soc_set_antenna_mode(mac_handle_t hal, |
| struct sir_antenna_mode_param *msg) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| tSmeCmd *cmd; |
| |
| if (NULL == msg) { |
| sme_err("antenna mode mesg is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("Failed to acquire lock"); |
| return QDF_STATUS_E_RESOURCES; |
| } |
| |
| cmd = csr_get_command_buffer(mac); |
| if (!cmd) { |
| sme_release_global_lock(&mac->sme); |
| sme_err("Get command buffer failed"); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| cmd->command = e_sme_command_set_antenna_mode; |
| cmd->u.set_antenna_mode_cmd = *msg; |
| |
| sme_debug("Antenna mode rx_chains: %d tx_chains: %d", |
| cmd->u.set_antenna_mode_cmd.num_rx_chains, |
| cmd->u.set_antenna_mode_cmd.num_tx_chains); |
| |
| csr_queue_sme_command(mac, cmd, false); |
| sme_release_global_lock(&mac->sme); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_set_peer_authorized() - call peer authorized callback |
| * @peer_addr: peer mac address |
| * @auth_cb: auth callback |
| * @vdev_id: vdev id |
| * |
| * Return: QDF Status |
| */ |
| QDF_STATUS sme_set_peer_authorized(uint8_t *peer_addr, |
| sme_peer_authorized_fp auth_cb, |
| uint32_t vdev_id) |
| { |
| void *wma_handle; |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "wma handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| wma_set_peer_authorized_cb(wma_handle, auth_cb); |
| return wma_set_peer_param(wma_handle, peer_addr, WMI_PEER_AUTHORIZE, |
| 1, vdev_id); |
| } |
| |
| /* |
| * sme_handle_set_fcc_channel() - set spec. tx power for non-fcc channel |
| * @hal: HAL pointer |
| * @fcc_constraint: flag to enable/disable the constraint |
| * @scan_pending: whether there is pending scan |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_handle_set_fcc_channel(mac_handle_t hal, bool fcc_constraint, |
| bool scan_pending) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac_ptr = PMAC_STRUCT(hal); |
| |
| status = sme_acquire_global_lock(&mac_ptr->sme); |
| |
| if (QDF_STATUS_SUCCESS == status) { |
| |
| if (fcc_constraint != mac_ptr->scan.fcc_constraint) { |
| mac_ptr->scan.fcc_constraint = fcc_constraint; |
| if (scan_pending) |
| mac_ptr->scan.defer_update_channel_list = true; |
| else |
| status = csr_update_channel_list(mac_ptr); |
| } |
| |
| sme_release_global_lock(&mac_ptr->sme); |
| } |
| |
| return status; |
| } |
| /** |
| * sme_setdef_dot11mode() - Updates pMac with default dot11mode |
| * @hal: Global MAC pointer |
| * |
| * Return: NULL. |
| */ |
| void sme_setdef_dot11mode(mac_handle_t hal) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| csr_set_default_dot11_mode(mac_ctx); |
| } |
| |
| /** |
| * sme_update_roam_scan_hi_rssi_scan_params() - update high rssi scan |
| * params |
| * @mac_handle - The handle returned by macOpen. |
| * @session_id - Session Identifier |
| * @notify_id - Identifies 1 of the 4 parameters to be modified |
| * @val New value of the parameter |
| * |
| * Return: QDF_STATUS - SME update config successful. |
| * Other status means SME failed to update |
| */ |
| |
| QDF_STATUS sme_update_roam_scan_hi_rssi_scan_params(mac_handle_t mac_handle, |
| uint8_t session_id, |
| uint32_t notify_id, |
| int32_t val) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| struct csr_neighbor_roamconfig *nr_config = NULL; |
| tpCsrNeighborRoamControlInfo nr_info = NULL; |
| uint32_t reason = 0; |
| |
| if (session_id >= CSR_ROAM_SESSION_MAX) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid sme session id: %d"), session_id); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| nr_config = &mac_ctx->roam.configParam.neighborRoamConfig; |
| nr_info = &mac_ctx->roam.neighborRoamInfo[session_id]; |
| switch (notify_id) { |
| case eCSR_HI_RSSI_SCAN_MAXCOUNT_ID: |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| "%s: gRoamScanHirssiMaxCount %d => %d", |
| __func__, nr_config->nhi_rssi_scan_max_count, |
| val); |
| nr_config->nhi_rssi_scan_max_count = val; |
| nr_info->cfgParams.hi_rssi_scan_max_count = val; |
| reason = REASON_ROAM_SCAN_HI_RSSI_MAXCOUNT_CHANGED; |
| break; |
| |
| case eCSR_HI_RSSI_SCAN_RSSI_DELTA_ID: |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| FL("gRoamScanHiRssiDelta %d => %d"), |
| nr_config->nhi_rssi_scan_rssi_delta, |
| val); |
| nr_config->nhi_rssi_scan_rssi_delta = val; |
| nr_info->cfgParams.hi_rssi_scan_rssi_delta = val; |
| reason = REASON_ROAM_SCAN_HI_RSSI_DELTA_CHANGED; |
| break; |
| |
| case eCSR_HI_RSSI_SCAN_DELAY_ID: |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| FL("gRoamScanHiRssiDelay %d => %d"), |
| nr_config->nhi_rssi_scan_delay, |
| val); |
| nr_config->nhi_rssi_scan_delay = val; |
| nr_info->cfgParams.hi_rssi_scan_delay = val; |
| reason = REASON_ROAM_SCAN_HI_RSSI_DELAY_CHANGED; |
| break; |
| |
| case eCSR_HI_RSSI_SCAN_RSSI_UB_ID: |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| FL("gRoamScanHiRssiUpperBound %d => %d"), |
| nr_config->nhi_rssi_scan_rssi_ub, |
| val); |
| nr_config->nhi_rssi_scan_rssi_ub = val; |
| nr_info->cfgParams.hi_rssi_scan_rssi_ub = val; |
| reason = REASON_ROAM_SCAN_HI_RSSI_UB_CHANGED; |
| break; |
| |
| default: |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| FL("invalid parameter notify_id %d"), |
| notify_id); |
| status = QDF_STATUS_E_INVAL; |
| break; |
| } |
| |
| if (mac_ctx->roam.configParam.isRoamOffloadScanEnabled && |
| status == QDF_STATUS_SUCCESS) { |
| csr_roam_offload_scan(mac_ctx, session_id, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, reason); |
| } |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| |
| return status; |
| } |
| |
| /** |
| * sme_update_tgt_services() - update the target services config. |
| * @hal: HAL pointer. |
| * @cfg: wma_tgt_services parameters. |
| * |
| * update the target services config. |
| * |
| * Return: None. |
| */ |
| void sme_update_tgt_services(mac_handle_t hal, struct wma_tgt_services *cfg) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| mac_ctx->obss_scan_offload = cfg->obss_scan_offload; |
| sme_debug("obss_scan_offload: %d", mac_ctx->obss_scan_offload); |
| mac_ctx->lteCoexAntShare = cfg->lte_coex_ant_share; |
| mac_ctx->beacon_offload = cfg->beacon_offload; |
| mac_ctx->pmf_offload = cfg->pmf_offload; |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, |
| FL("mac_ctx->pmf_offload: %d"), mac_ctx->pmf_offload); |
| mac_ctx->is_fils_roaming_supported = |
| cfg->is_fils_roaming_supported; |
| mac_ctx->is_11k_offload_supported = |
| cfg->is_11k_offload_supported; |
| sme_debug("pmf_offload: %d fils_roam support %d 11k_offload %d", |
| mac_ctx->pmf_offload, mac_ctx->is_fils_roaming_supported, |
| mac_ctx->is_11k_offload_supported); |
| } |
| |
| /** |
| * sme_is_session_id_valid() - Check if the session id is valid |
| * @hal: Pointer to HAL |
| * @session_id: Session id |
| * |
| * Checks if the session id is valid or not |
| * |
| * Return: True is the session id is valid, false otherwise |
| */ |
| bool sme_is_session_id_valid(mac_handle_t hal, uint32_t session_id) |
| { |
| tpAniSirGlobal mac; |
| |
| if (NULL != hal) { |
| mac = PMAC_STRUCT(hal); |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: null mac pointer", __func__); |
| return false; |
| } |
| |
| if (CSR_IS_SESSION_VALID(mac, session_id)) |
| return true; |
| |
| return false; |
| } |
| |
| #ifdef FEATURE_WLAN_TDLS |
| |
| /** |
| * sme_get_opclass() - determine operating class |
| * @hal: Pointer to HAL |
| * @channel: channel id |
| * @bw_offset: bandwidth offset |
| * @opclass: pointer to operating class |
| * |
| * Function will determine operating class from regdm_get_opclass_from_channel |
| * |
| * Return: none |
| */ |
| void sme_get_opclass(mac_handle_t hal, uint8_t channel, uint8_t bw_offset, |
| uint8_t *opclass) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| /* redgm opclass table contains opclass for 40MHz low primary, |
| * 40MHz high primary and 20MHz. No support for 80MHz yet. So |
| * first we will check if bit for 40MHz is set and if so find |
| * matching opclass either with low primary or high primary |
| * (a channel would never be in both) and then search for opclass |
| * matching 20MHz, else for any BW. |
| */ |
| if (bw_offset & (1 << BW_40_OFFSET_BIT)) { |
| *opclass = wlan_reg_dmn_get_opclass_from_channel( |
| mac_ctx->scan.countryCodeCurrent, |
| channel, BW40_LOW_PRIMARY); |
| if (!(*opclass)) { |
| *opclass = wlan_reg_dmn_get_opclass_from_channel( |
| mac_ctx->scan.countryCodeCurrent, |
| channel, BW40_HIGH_PRIMARY); |
| } |
| } else if (bw_offset & (1 << BW_20_OFFSET_BIT)) { |
| *opclass = wlan_reg_dmn_get_opclass_from_channel( |
| mac_ctx->scan.countryCodeCurrent, |
| channel, BW20); |
| } else { |
| *opclass = wlan_reg_dmn_get_opclass_from_channel( |
| mac_ctx->scan.countryCodeCurrent, |
| channel, BWALL); |
| } |
| } |
| #endif |
| |
| /** |
| * sme_set_fw_test() - set fw test |
| * @fw_test: fw test param |
| * |
| * Return: Return QDF_STATUS, otherwise appropriate failure code |
| */ |
| QDF_STATUS sme_set_fw_test(struct set_fwtest_params *fw_test) |
| { |
| void *wma_handle; |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "wma handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| wma_process_fw_test_cmd(wma_handle, fw_test); |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_ht40_stop_obss_scan() - ht40 obss stop scan |
| * @hal: mac handel |
| * @vdev_id: vdev identifier |
| * |
| * Return: Return QDF_STATUS, otherwise appropriate failure code |
| */ |
| QDF_STATUS sme_ht40_stop_obss_scan(mac_handle_t hal, uint32_t vdev_id) |
| { |
| void *wma_handle; |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "wma handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| wma_ht40_stop_obss_scan(wma_handle, vdev_id); |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_update_mimo_power_save() - Update MIMO power save |
| * configuration |
| * @hal: The handle returned by macOpen |
| * @is_ht_smps_enabled: enable/disable ht smps |
| * @ht_smps_mode: smps mode disabled/static/dynamic |
| * @send_smps_action: flag to send smps force mode command |
| * to FW |
| * |
| * Return: QDF_STATUS if SME update mimo power save |
| * configuration success else failure status |
| */ |
| QDF_STATUS sme_update_mimo_power_save(mac_handle_t hal, |
| uint8_t is_ht_smps_enabled, |
| uint8_t ht_smps_mode, |
| bool send_smps_action) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| sme_debug("SMPS enable: %d mode: %d send action: %d", |
| is_ht_smps_enabled, ht_smps_mode, |
| send_smps_action); |
| mac_ctx->mlme_cfg->ht_caps.enable_smps = |
| is_ht_smps_enabled; |
| mac_ctx->mlme_cfg->ht_caps.smps = ht_smps_mode; |
| mac_ctx->roam.configParam.send_smps_action = |
| send_smps_action; |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_is_sta_smps_allowed() - check if the supported nss for |
| * the session is greater than 1x1 to enable sta SMPS |
| * @hal: The handle returned by macOpen |
| * @session_id: session id |
| * |
| * Return: bool returns true if supported nss is greater than |
| * 1x1 else false |
| */ |
| bool sme_is_sta_smps_allowed(mac_handle_t hal, uint8_t session_id) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct csr_roam_session *csr_session; |
| |
| csr_session = CSR_GET_SESSION(mac_ctx, session_id); |
| if (NULL == csr_session) { |
| sme_err("SME session not valid: %d", session_id); |
| return false; |
| } |
| |
| if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) { |
| sme_err("CSR session not valid: %d", session_id); |
| return false; |
| } |
| |
| return (csr_session->supported_nss_1x1 == true) ? false : true; |
| } |
| |
| /** |
| * sme_add_beacon_filter() - set the beacon filter configuration |
| * @hal: The handle returned by macOpen |
| * @session_id: session id |
| * @ie_map: bitwise array of IEs |
| * |
| * Return: Return QDF_STATUS, otherwise appropriate failure code |
| */ |
| QDF_STATUS sme_add_beacon_filter(mac_handle_t hal, |
| uint32_t session_id, |
| uint32_t *ie_map) |
| { |
| struct scheduler_msg message = {0}; |
| QDF_STATUS qdf_status; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct beacon_filter_param *filter_param; |
| |
| if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) { |
| sme_err("CSR session not valid: %d", session_id); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| filter_param = qdf_mem_malloc(sizeof(*filter_param)); |
| if (!filter_param) |
| return QDF_STATUS_E_FAILURE; |
| |
| filter_param->vdev_id = session_id; |
| |
| qdf_mem_copy(filter_param->ie_map, ie_map, |
| BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(uint32_t)); |
| |
| message.type = WMA_ADD_BCN_FILTER_CMDID; |
| message.bodyptr = filter_param; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post msg to WDA!", |
| __func__); |
| |
| qdf_mem_free(filter_param); |
| } |
| return qdf_status; |
| } |
| |
| /** |
| * sme_remove_beacon_filter() - set the beacon filter configuration |
| * @hal: The handle returned by macOpen |
| * @session_id: session id |
| * |
| * Return: Return QDF_STATUS, otherwise appropriate failure code |
| */ |
| QDF_STATUS sme_remove_beacon_filter(mac_handle_t hal, uint32_t session_id) |
| { |
| struct scheduler_msg message = {0}; |
| QDF_STATUS qdf_status; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct beacon_filter_param *filter_param; |
| |
| if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) { |
| sme_err("CSR session not valid: %d", session_id); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| filter_param = qdf_mem_malloc(sizeof(*filter_param)); |
| if (!filter_param) |
| return QDF_STATUS_E_FAILURE; |
| |
| filter_param->vdev_id = session_id; |
| |
| message.type = WMA_REMOVE_BCN_FILTER_CMDID; |
| message.bodyptr = filter_param; |
| qdf_status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post msg to WDA!", |
| __func__); |
| |
| qdf_mem_free(filter_param); |
| } |
| return qdf_status; |
| } |
| |
| /** |
| * sme_send_disassoc_req_frame - send disassoc req |
| * @hal: handler to hal |
| * @session_id: session id |
| * @peer_mac: peer mac address |
| * @reason: reason for disassociation |
| * wait_for_ack: wait for acknowledgment |
| * |
| * function to send disassoc request to lim |
| * |
| * return: none |
| */ |
| void sme_send_disassoc_req_frame(mac_handle_t hal, uint8_t session_id, |
| uint8_t *peer_mac, uint16_t reason, uint8_t wait_for_ack) |
| { |
| struct sme_send_disassoc_frm_req *msg; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| A_UINT8 *buf; |
| A_UINT16 tmp; |
| |
| msg = qdf_mem_malloc(sizeof(struct sme_send_disassoc_frm_req)); |
| if (!msg) |
| return; |
| |
| msg->msg_type = (uint16_t) eWNI_SME_SEND_DISASSOC_FRAME; |
| |
| msg->length = (uint16_t) sizeof(struct sme_send_disassoc_frm_req); |
| |
| buf = &msg->session_id; |
| |
| /* session id */ |
| *buf = (A_UINT8) session_id; |
| buf += sizeof(A_UINT8); |
| |
| /* transaction id */ |
| *buf = 0; |
| *(buf + 1) = 0; |
| buf += sizeof(A_UINT16); |
| |
| /* Set the peer MAC address before sending the message to LIM */ |
| qdf_mem_copy(buf, peer_mac, QDF_MAC_ADDR_SIZE); |
| |
| buf += QDF_MAC_ADDR_SIZE; |
| |
| /* reasoncode */ |
| tmp = (uint16_t) reason; |
| qdf_mem_copy(buf, &tmp, sizeof(uint16_t)); |
| buf += sizeof(uint16_t); |
| |
| *buf = wait_for_ack; |
| buf += sizeof(uint8_t); |
| |
| qdf_status = umac_send_mb_message_to_mac(msg); |
| |
| if (qdf_status != QDF_STATUS_SUCCESS) |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("cds_send_mb_message Failed")); |
| } |
| |
| #ifdef FEATURE_WLAN_APF |
| QDF_STATUS sme_get_apf_capabilities(mac_handle_t hal, |
| apf_get_offload_cb callback, |
| void *context) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct scheduler_msg cds_msg = {0}; |
| |
| SME_ENTER(); |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| /* Serialize the req through MC thread */ |
| mac_ctx->sme.apf_get_offload_cb = callback; |
| mac_ctx->sme.apf_get_offload_context = context; |
| cds_msg.bodyptr = NULL; |
| cds_msg.type = WDA_APF_GET_CAPABILITIES_REQ; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &cds_msg); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Post apf get offload msg fail")); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| sme_release_global_lock(&mac_ctx->sme); |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("sme_acquire_global_lock error")); |
| } |
| SME_EXIT(); |
| return status; |
| } |
| |
| QDF_STATUS sme_set_apf_instructions(mac_handle_t hal, |
| struct sir_apf_set_offload *req) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct scheduler_msg cds_msg = {0}; |
| struct sir_apf_set_offload *set_offload; |
| |
| set_offload = qdf_mem_malloc(sizeof(*set_offload) + |
| req->current_length); |
| if (!set_offload) |
| return QDF_STATUS_E_NOMEM; |
| |
| set_offload->session_id = req->session_id; |
| set_offload->filter_id = req->filter_id; |
| set_offload->current_offset = req->current_offset; |
| set_offload->total_length = req->total_length; |
| set_offload->current_length = req->current_length; |
| if (set_offload->total_length) { |
| set_offload->program = ((uint8_t *)set_offload) + |
| sizeof(*set_offload); |
| qdf_mem_copy(set_offload->program, req->program, |
| set_offload->current_length); |
| } |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| /* Serialize the req through MC thread */ |
| cds_msg.bodyptr = set_offload; |
| cds_msg.type = WDA_APF_SET_INSTRUCTIONS_REQ; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &cds_msg); |
| |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Post APF set offload msg fail")); |
| status = QDF_STATUS_E_FAILURE; |
| qdf_mem_free(set_offload); |
| } |
| sme_release_global_lock(&mac_ctx->sme); |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("sme_acquire_global_lock failed")); |
| qdf_mem_free(set_offload); |
| } |
| return status; |
| } |
| |
| QDF_STATUS sme_set_apf_enable_disable(mac_handle_t hal, uint8_t vdev_id, |
| bool apf_enable) |
| { |
| void *wma_handle; |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "wma handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return wma_send_apf_enable_cmd(wma_handle, vdev_id, apf_enable); |
| } |
| |
| QDF_STATUS |
| sme_apf_write_work_memory(mac_handle_t hal, |
| struct wmi_apf_write_memory_params *write_params) |
| { |
| void *wma_handle; |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "wma handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return wma_send_apf_write_work_memory_cmd(wma_handle, write_params); |
| } |
| |
| QDF_STATUS |
| sme_apf_read_work_memory(mac_handle_t hal, |
| struct wmi_apf_read_memory_params *read_params, |
| apf_read_mem_cb callback) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| void *wma_handle; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| mac->sme.apf_read_mem_cb = callback; |
| sme_release_global_lock(&mac->sme); |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("sme_acquire_global_lock failed")); |
| } |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "wma handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return wma_send_apf_read_work_memory_cmd(wma_handle, read_params); |
| } |
| #endif /* FEATURE_WLAN_APF */ |
| |
| /** |
| * sme_get_wni_dot11_mode() - return configured wni dot11mode |
| * @hal: hal pointer |
| * |
| * Return: wni dot11 mode. |
| */ |
| uint32_t sme_get_wni_dot11_mode(mac_handle_t hal) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| return csr_translate_to_wni_cfg_dot11_mode(mac_ctx, |
| mac_ctx->roam.configParam.uCfgDot11Mode); |
| } |
| |
| /** |
| * sme_create_mon_session() - post message to create PE session for monitormode |
| * operation |
| * @mac_handle: Handle to the HAL |
| * @bssid: pointer to bssid |
| * @vdev_id: sme session id |
| * |
| * Return: QDF_STATUS_SUCCESS on success, non-zero error code on failure. |
| */ |
| QDF_STATUS sme_create_mon_session(mac_handle_t mac_handle, tSirMacAddr bss_id, |
| uint8_t vdev_id) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| struct sir_create_session *msg; |
| |
| msg = qdf_mem_malloc(sizeof(*msg)); |
| if (msg) { |
| msg->type = eWNI_SME_MON_INIT_SESSION; |
| msg->vdev_id = vdev_id; |
| msg->msg_len = sizeof(*msg); |
| qdf_mem_copy(msg->bss_id.bytes, bss_id, QDF_MAC_ADDR_SIZE); |
| status = umac_send_mb_message_to_mac(msg); |
| } |
| return status; |
| } |
| |
| void sme_set_chan_info_callback(mac_handle_t mac_handle, |
| void (*callback)(struct scan_chan_info *chan_info)) |
| { |
| tpAniSirGlobal mac; |
| |
| if (mac_handle == NULL) { |
| QDF_ASSERT(0); |
| return; |
| } |
| mac = PMAC_STRUCT(mac_handle); |
| mac->chan_info_cb = callback; |
| } |
| |
| /** |
| * sme_set_adaptive_dwelltime_config() - Update Adaptive dwelltime configuration |
| * @hal: The handle returned by macOpen |
| * @params: adaptive_dwelltime_params config |
| * |
| * Return: QDF_STATUS if adaptive dwell time update |
| * configuration success else failure status |
| */ |
| QDF_STATUS sme_set_adaptive_dwelltime_config(mac_handle_t hal, |
| struct adaptive_dwelltime_params *params) |
| { |
| struct scheduler_msg message = {0}; |
| QDF_STATUS status; |
| struct adaptive_dwelltime_params *dwelltime_params; |
| |
| dwelltime_params = qdf_mem_malloc(sizeof(*dwelltime_params)); |
| if (!dwelltime_params) |
| return QDF_STATUS_E_NOMEM; |
| |
| dwelltime_params->is_enabled = params->is_enabled; |
| dwelltime_params->dwelltime_mode = params->dwelltime_mode; |
| dwelltime_params->lpf_weight = params->lpf_weight; |
| dwelltime_params->passive_mon_intval = params->passive_mon_intval; |
| dwelltime_params->wifi_act_threshold = params->wifi_act_threshold; |
| |
| message.type = WMA_SET_ADAPT_DWELLTIME_CONF_PARAMS; |
| message.bodyptr = dwelltime_params; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post msg to WMA!", __func__); |
| |
| qdf_mem_free(dwelltime_params); |
| } |
| return status; |
| } |
| |
| /** |
| * sme_set_vdev_ies_per_band() - sends the per band IEs to vdev |
| * @hal: Pointer to HAL |
| * @vdev_id: vdev_id for which IE is targeted |
| * |
| * Return: None |
| */ |
| void sme_set_vdev_ies_per_band(mac_handle_t hal, uint8_t vdev_id) |
| { |
| struct sir_set_vdev_ies_per_band *p_msg; |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| |
| p_msg = qdf_mem_malloc(sizeof(*p_msg)); |
| if (!p_msg) |
| return; |
| |
| p_msg->vdev_id = vdev_id; |
| p_msg->msg_type = eWNI_SME_SET_VDEV_IES_PER_BAND; |
| p_msg->len = sizeof(*p_msg); |
| sme_debug("sending eWNI_SME_SET_VDEV_IES_PER_BAND: vdev_id: %d", |
| vdev_id); |
| status = umac_send_mb_message_to_mac(p_msg); |
| if (QDF_STATUS_SUCCESS != status) |
| sme_err("Send eWNI_SME_SET_VDEV_IES_PER_BAND fail"); |
| } |
| |
| /** |
| * sme_set_pdev_ht_vht_ies() - sends the set pdev IE req |
| * @hal: Pointer to HAL |
| * @enable2x2: 1x1 or 2x2 mode. |
| * |
| * Sends the set pdev IE req with Nss value. |
| * |
| * Return: None |
| */ |
| void sme_set_pdev_ht_vht_ies(mac_handle_t hal, bool enable2x2) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct sir_set_ht_vht_cfg *ht_vht_cfg; |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| |
| if (!((mac_ctx->roam.configParam.uCfgDot11Mode == |
| eCSR_CFG_DOT11_MODE_AUTO) || |
| (mac_ctx->roam.configParam.uCfgDot11Mode == |
| eCSR_CFG_DOT11_MODE_11N) || |
| (mac_ctx->roam.configParam.uCfgDot11Mode == |
| eCSR_CFG_DOT11_MODE_11N_ONLY) || |
| (mac_ctx->roam.configParam.uCfgDot11Mode == |
| eCSR_CFG_DOT11_MODE_11AC) || |
| (mac_ctx->roam.configParam.uCfgDot11Mode == |
| eCSR_CFG_DOT11_MODE_11AC_ONLY))) |
| return; |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| ht_vht_cfg = qdf_mem_malloc(sizeof(*ht_vht_cfg)); |
| if (!ht_vht_cfg) { |
| sme_release_global_lock(&mac_ctx->sme); |
| return; |
| } |
| |
| ht_vht_cfg->pdev_id = 0; |
| if (enable2x2) |
| ht_vht_cfg->nss = 2; |
| else |
| ht_vht_cfg->nss = 1; |
| ht_vht_cfg->dot11mode = |
| (uint8_t)csr_translate_to_wni_cfg_dot11_mode(mac_ctx, |
| mac_ctx->roam.configParam.uCfgDot11Mode); |
| |
| ht_vht_cfg->msg_type = eWNI_SME_PDEV_SET_HT_VHT_IE; |
| ht_vht_cfg->len = sizeof(*ht_vht_cfg); |
| sme_debug("SET_HT_VHT_IE with nss: %d, dot11mode: %d", |
| ht_vht_cfg->nss, |
| ht_vht_cfg->dot11mode); |
| status = umac_send_mb_message_to_mac(ht_vht_cfg); |
| if (QDF_STATUS_SUCCESS != status) |
| sme_err("Send SME_PDEV_SET_HT_VHT_IE fail"); |
| |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| } |
| |
| /** |
| * sme_update_vdev_type_nss() - sets the nss per vdev type |
| * @hal: Pointer to HAL |
| * @max_supp_nss: max_supported Nss |
| * @band: 5G or 2.4G band |
| * |
| * Sets the per band Nss for each vdev type based on INI and configured |
| * chain mask value. |
| * |
| * Return: None |
| */ |
| void sme_update_vdev_type_nss(mac_handle_t hal, uint8_t max_supp_nss, |
| uint32_t vdev_type_nss, enum band_info band) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct vdev_type_nss *vdev_nss; |
| |
| if (BAND_5G == band) |
| vdev_nss = &mac_ctx->vdev_type_nss_5g; |
| else |
| vdev_nss = &mac_ctx->vdev_type_nss_2g; |
| |
| vdev_nss->sta = QDF_MIN(max_supp_nss, CFG_STA_NSS(vdev_type_nss)); |
| vdev_nss->sap = QDF_MIN(max_supp_nss, CFG_SAP_NSS(vdev_type_nss)); |
| vdev_nss->p2p_go = QDF_MIN(max_supp_nss, |
| CFG_P2P_GO_NSS(vdev_type_nss)); |
| vdev_nss->p2p_cli = QDF_MIN(max_supp_nss, |
| CFG_P2P_CLI_NSS(vdev_type_nss)); |
| vdev_nss->p2p_dev = QDF_MIN(max_supp_nss, |
| CFG_P2P_DEV_NSS(vdev_type_nss)); |
| vdev_nss->ibss = QDF_MIN(max_supp_nss, CFG_IBSS_NSS(vdev_type_nss)); |
| vdev_nss->tdls = QDF_MIN(max_supp_nss, CFG_TDLS_NSS(vdev_type_nss)); |
| vdev_nss->ocb = QDF_MIN(max_supp_nss, CFG_OCB_NSS(vdev_type_nss)); |
| |
| sme_debug("band %d NSS:sta %d sap %d cli %d go %d dev %d ibss %d tdls %d ocb %d", |
| band, vdev_nss->sta, vdev_nss->sap, vdev_nss->p2p_cli, |
| vdev_nss->p2p_go, vdev_nss->p2p_dev, vdev_nss->ibss, |
| 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(mac_handle_t 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) |
| 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 |
| * @hw_dbs_capable: HW DBS capability |
| * |
| * Sets HW DBS capability based on INI and fw capability. |
| * |
| * Return: None |
| */ |
| void sme_update_hw_dbs_capable(mac_handle_t hal, uint8_t hw_dbs_capable) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| mac_ctx->hw_dbs_capable = hw_dbs_capable; |
| } |
| |
| #ifdef FEATURE_P2P_LISTEN_OFFLOAD |
| /** |
| * sme_register_p2p_lo_event() - Register for the p2p lo event |
| * @mac_handle: reference to the HAL |
| * @context: the context of the call |
| * @callback: the callback to hdd |
| * |
| * This function registers the callback function for P2P listen |
| * offload stop event. |
| * |
| * Return: none |
| */ |
| void sme_register_p2p_lo_event(mac_handle_t mac_handle, void *context, |
| p2p_lo_callback callback) |
| { |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| pMac->sme.p2p_lo_event_callback = callback; |
| pMac->sme.p2p_lo_event_context = context; |
| sme_release_global_lock(&pMac->sme); |
| } |
| #endif |
| |
| /** |
| * sme_process_mac_pwr_dbg_cmd() - enable mac pwr debugging |
| * @hal: The handle returned by macOpen |
| * @session_id: session id |
| * @dbg_args: args for mac pwr debug command |
| * Return: Return QDF_STATUS, otherwise appropriate failure code |
| */ |
| QDF_STATUS sme_process_mac_pwr_dbg_cmd(mac_handle_t hal, uint32_t session_id, |
| struct sir_mac_pwr_dbg_cmd* |
| dbg_args) |
| { |
| struct scheduler_msg message = {0}; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct sir_mac_pwr_dbg_cmd *req; |
| int i; |
| |
| if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) { |
| sme_err("CSR session not valid: %d", session_id); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| req = qdf_mem_malloc(sizeof(*req)); |
| if (!req) |
| return QDF_STATUS_E_FAILURE; |
| |
| req->module_id = dbg_args->module_id; |
| req->pdev_id = dbg_args->pdev_id; |
| req->num_args = dbg_args->num_args; |
| for (i = 0; i < req->num_args; i++) |
| req->args[i] = dbg_args->args[i]; |
| |
| message.type = SIR_HAL_POWER_DBG_CMD; |
| message.bodyptr = req; |
| |
| if (!QDF_IS_STATUS_SUCCESS(scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message))) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post msg to WDA!", |
| __func__); |
| qdf_mem_free(req); |
| } |
| return QDF_STATUS_SUCCESS; |
| } |
| /** |
| * sme_get_vdev_type_nss() - gets the nss per vdev type |
| * @dev_mode: connection type. |
| * @nss2g: Pointer to the 2G Nss parameter. |
| * @nss5g: Pointer to the 5G Nss parameter. |
| * |
| * Fills the 2G and 5G Nss values based on connection type. |
| * |
| * Return: None |
| */ |
| void sme_get_vdev_type_nss(enum QDF_OPMODE dev_mode, |
| uint8_t *nss_2g, uint8_t *nss_5g) |
| { |
| tpAniSirGlobal mac_ctx = sme_get_mac_context(); |
| |
| if (NULL == mac_ctx) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Invalid MAC context")); |
| return; |
| } |
| csr_get_vdev_type_nss(mac_ctx, dev_mode, nss_2g, nss_5g); |
| } |
| |
| /** |
| * sme_update_sta_roam_policy() - update sta roam policy for |
| * unsafe and DFS channels. |
| * @mac_handle: hal handle for getting global mac struct |
| * @dfs_mode: dfs mode which tell if dfs channel needs to be |
| * skipped or not |
| * @skip_unsafe_channels: Param to tell if driver needs to |
| * skip unsafe channels or not. |
| * @param session_id: sme_session_id |
| * @sap_operating_band: Band on which SAP is operating |
| * |
| * sme_update_sta_roam_policy update sta rome policies to csr |
| * this function will call csrUpdateChannelList as well |
| * to include/exclude DFS channels and unsafe channels. |
| * |
| * Return: eHAL_STATUS_SUCCESS or non-zero on failure. |
| */ |
| QDF_STATUS sme_update_sta_roam_policy(mac_handle_t mac_handle, |
| enum sta_roam_policy_dfs_mode dfs_mode, |
| bool skip_unsafe_channels, |
| uint8_t session_id, uint8_t sap_operating_band) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tSmeConfigParams *sme_config; |
| |
| if (!mac_ctx) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL, |
| "%s: mac_ctx is null", __func__); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| sme_config = qdf_mem_malloc(sizeof(*sme_config)); |
| if (!sme_config) |
| return QDF_STATUS_E_FAILURE; |
| |
| qdf_mem_zero(sme_config, sizeof(*sme_config)); |
| sme_get_config_param(mac_handle, sme_config); |
| |
| sme_config->csrConfig.sta_roam_policy_params.dfs_mode = |
| dfs_mode; |
| sme_config->csrConfig.sta_roam_policy_params.skip_unsafe_channels = |
| skip_unsafe_channels; |
| sme_config->csrConfig.sta_roam_policy_params.sap_operating_band = |
| sap_operating_band; |
| |
| sme_update_config(mac_handle, sme_config); |
| |
| status = csr_update_channel_list(mac_ctx); |
| if (QDF_STATUS_SUCCESS != status) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("failed to update the supported channel list")); |
| } |
| |
| if (mac_ctx->roam.configParam.isRoamOffloadScanEnabled) { |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| csr_roam_offload_scan(mac_ctx, session_id, |
| ROAM_SCAN_OFFLOAD_UPDATE_CFG, |
| REASON_ROAM_SCAN_STA_ROAM_POLICY_CHANGED); |
| sme_release_global_lock(&mac_ctx->sme); |
| } else { |
| sme_err("Failed to acquire SME lock"); |
| } |
| } |
| qdf_mem_free(sme_config); |
| return status; |
| } |
| |
| /** |
| * sme_enable_disable_chanavoidind_event - configure ca event ind |
| * @hal: handler to hal |
| * @set_value: enable/disable |
| * |
| * function to enable/disable chan avoidance indication |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_enable_disable_chanavoidind_event(mac_handle_t hal, |
| uint8_t set_value) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct scheduler_msg msg = {0}; |
| |
| if (!mac_ctx->mlme_cfg->gen.optimize_ca_event) { |
| sme_err("optimize_ca_event not enabled in ini"); |
| return QDF_STATUS_E_NOSUPPORT; |
| } |
| |
| sme_debug("set_value: %d", set_value); |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_STATUS_SUCCESS == status) { |
| qdf_mem_zero(&msg, sizeof(struct scheduler_msg)); |
| msg.type = WMA_SEND_FREQ_RANGE_CONTROL_IND; |
| msg.bodyval = set_value; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| sme_release_global_lock(&mac_ctx->sme); |
| return status; |
| } |
| return status; |
| } |
| |
| /* |
| * sme_set_default_scan_ie() - API to send default scan IE to LIM |
| * @hal: reference to the HAL |
| * @session_id: current session ID |
| * @ie_data: Pointer to Scan IE data |
| * @ie_len: Length of @ie_data |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_set_default_scan_ie(mac_handle_t hal, uint16_t session_id, |
| uint8_t *ie_data, uint16_t ie_len) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct hdd_default_scan_ie *set_ie_params; |
| |
| if (!ie_data) |
| return QDF_STATUS_E_INVAL; |
| |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| set_ie_params = qdf_mem_malloc(sizeof(*set_ie_params)); |
| if (!set_ie_params) |
| status = QDF_STATUS_E_NOMEM; |
| else { |
| set_ie_params->message_type = eWNI_SME_DEFAULT_SCAN_IE; |
| set_ie_params->length = sizeof(*set_ie_params); |
| set_ie_params->session_id = session_id; |
| set_ie_params->ie_len = ie_len; |
| qdf_mem_copy(set_ie_params->ie_data, ie_data, ie_len); |
| status = umac_send_mb_message_to_mac(set_ie_params); |
| } |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| return status; |
| } |
| |
| QDF_STATUS sme_get_sar_power_limits(mac_handle_t hal, |
| wma_sar_cb callback, void *context) |
| { |
| void *wma_handle; |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "wma handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return wma_get_sar_limit(wma_handle, callback, context); |
| } |
| |
| QDF_STATUS sme_set_sar_power_limits(mac_handle_t hal, |
| struct sar_limit_cmd_params *sar_limit_cmd) |
| { |
| void *wma_handle; |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "wma handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return wma_set_sar_limit(wma_handle, sar_limit_cmd); |
| } |
| |
| QDF_STATUS sme_send_coex_config_cmd(struct coex_config_params *coex_cfg_params) |
| { |
| void *wma_handle; |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| sme_err("wma handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| return wma_send_coex_config_cmd(wma_handle, coex_cfg_params); |
| } |
| |
| #ifdef WLAN_FEATURE_FIPS |
| QDF_STATUS sme_fips_request(mac_handle_t hal, struct fips_params *param, |
| wma_fips_cb callback, void *context) |
| { |
| void *wma_handle; |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| sme_err("wma handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return wma_fips_request(wma_handle, param, callback, context); |
| } |
| #endif |
| |
| QDF_STATUS sme_set_cts2self_for_p2p_go(mac_handle_t mac_handle) |
| { |
| void *wma_handle; |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "wma_handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| if (QDF_STATUS_SUCCESS != |
| wma_set_cts2self_for_p2p_go(wma_handle, true)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Failed to set cts2self for p2p GO to firmware", |
| __func__); |
| return QDF_STATUS_E_FAILURE; |
| } |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_update_tx_fail_cnt_threshold() - update tx fail count Threshold |
| * @mac_handle: Handle returned by mac_open |
| * @session_id: Session ID on which tx fail count needs to be updated to FW |
| * @tx_fail_count: Count for tx fail threshold after which FW will disconnect |
| * |
| * This function is used to set tx fail count threshold to firmware. |
| * firmware will issue disocnnect with peer device once this threshold is |
| * reached. |
| * |
| * Return: Return QDF_STATUS, otherwise appropriate failure code |
| */ |
| QDF_STATUS sme_update_tx_fail_cnt_threshold(mac_handle_t mac_handle, |
| uint8_t session_id, uint32_t tx_fail_count) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| struct sme_tx_fail_cnt_threshold *tx_fail_cnt; |
| struct scheduler_msg msg = {0}; |
| |
| tx_fail_cnt = qdf_mem_malloc(sizeof(*tx_fail_cnt)); |
| if (!tx_fail_cnt) |
| return QDF_STATUS_E_FAILURE; |
| |
| sme_debug("session_id: %d tx_fail_count: %d", |
| session_id, tx_fail_count); |
| tx_fail_cnt->session_id = session_id; |
| tx_fail_cnt->tx_fail_cnt_threshold = tx_fail_count; |
| |
| qdf_mem_zero(&msg, sizeof(struct scheduler_msg)); |
| msg.type = SIR_HAL_UPDATE_TX_FAIL_CNT_TH; |
| msg.reserved = 0; |
| msg.bodyptr = tx_fail_cnt; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("Not able to post Tx fail count message to WDA")); |
| qdf_mem_free(tx_fail_cnt); |
| } |
| return status; |
| } |
| |
| QDF_STATUS sme_set_lost_link_info_cb(mac_handle_t mac_handle, |
| lost_link_info_cb cb) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| mac->sme.lost_link_info_cb = cb; |
| sme_release_global_lock(&mac->sme); |
| } else { |
| sme_err("sme_acquire_global_lock error status: %d", status); |
| } |
| |
| return status; |
| } |
| |
| #ifdef FEATURE_WLAN_ESE |
| bool sme_roam_is_ese_assoc(struct csr_roam_info *roam_info) |
| { |
| return roam_info->isESEAssoc; |
| } |
| #endif |
| |
| bool sme_neighbor_roam_is11r_assoc(mac_handle_t hal_ctx, uint8_t session_id) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); |
| |
| return csr_neighbor_roam_is11r_assoc(mac_ctx, session_id); |
| } |
| |
| #ifdef WLAN_FEATURE_WOW_PULSE |
| /** |
| * sme_set_wow_pulse() - set wow pulse info |
| * @wow_pulse_set_info: wow_pulse_mode structure pointer |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_set_wow_pulse(struct wow_pulse_mode *wow_pulse_set_info) |
| { |
| struct scheduler_msg message = {0}; |
| QDF_STATUS status; |
| struct wow_pulse_mode *wow_pulse_set_cmd; |
| |
| if (!wow_pulse_set_info) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: invalid wow_pulse_set_info pointer", __func__); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| wow_pulse_set_cmd = qdf_mem_malloc(sizeof(*wow_pulse_set_cmd)); |
| if (!wow_pulse_set_cmd) |
| return QDF_STATUS_E_NOMEM; |
| |
| *wow_pulse_set_cmd = *wow_pulse_set_info; |
| |
| message.type = WMA_SET_WOW_PULSE_CMD; |
| message.bodyptr = wow_pulse_set_cmd; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &message); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Not able to post msg to WDA!", |
| __func__); |
| qdf_mem_free(wow_pulse_set_cmd); |
| status = QDF_STATUS_E_FAILURE; |
| } |
| |
| return status; |
| } |
| #endif |
| |
| /** |
| * sme_prepare_beacon_from_bss_descp() - prepares beacon frame by populating |
| * different fields and IEs from bss descriptor. |
| * @frame_buf: frame buffer to populate |
| * @bss_descp: bss descriptor |
| * @bssid: bssid of the beacon frame to populate |
| * @ie_len: length of IE fields |
| * |
| * Return: None |
| */ |
| static void sme_prepare_beacon_from_bss_descp(uint8_t *frame_buf, |
| tSirBssDescription *bss_descp, |
| const tSirMacAddr bssid, |
| uint32_t ie_len) |
| { |
| tDot11fBeacon1 *bcn_fixed; |
| tpSirMacMgmtHdr mac_hdr = (tpSirMacMgmtHdr)frame_buf; |
| |
| /* populate mac header first to indicate beacon */ |
| mac_hdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION; |
| mac_hdr->fc.type = SIR_MAC_MGMT_FRAME; |
| mac_hdr->fc.subType = SIR_MAC_MGMT_BEACON; |
| qdf_mem_copy((uint8_t *) mac_hdr->da, |
| (uint8_t *) "\xFF\xFF\xFF\xFF\xFF\xFF", |
| sizeof(struct qdf_mac_addr)); |
| qdf_mem_copy((uint8_t *) mac_hdr->sa, bssid, |
| sizeof(struct qdf_mac_addr)); |
| qdf_mem_copy((uint8_t *) mac_hdr->bssId, bssid, |
| sizeof(struct qdf_mac_addr)); |
| |
| /* now populate fixed params */ |
| bcn_fixed = (tDot11fBeacon1 *)(frame_buf + SIR_MAC_HDR_LEN_3A); |
| /* populate timestamp */ |
| qdf_mem_copy(&bcn_fixed->TimeStamp.timestamp, &bss_descp->timeStamp, |
| sizeof(bss_descp->timeStamp)); |
| /* populate beacon interval */ |
| bcn_fixed->BeaconInterval.interval = bss_descp->beaconInterval; |
| /* populate capability */ |
| qdf_mem_copy(&bcn_fixed->Capabilities, &bss_descp->capabilityInfo, |
| sizeof(bss_descp->capabilityInfo)); |
| |
| /* copy IEs now */ |
| qdf_mem_copy(frame_buf + SIR_MAC_HDR_LEN_3A |
| + SIR_MAC_B_PR_SSID_OFFSET, |
| &bss_descp->ieFields, ie_len); |
| } |
| |
| QDF_STATUS sme_get_rssi_snr_by_bssid(mac_handle_t hal, |
| struct csr_roam_profile *profile, |
| const uint8_t *bssid, |
| int8_t *rssi, int8_t *snr) |
| { |
| tSirBssDescription *bss_descp; |
| tCsrScanResultFilter *scan_filter; |
| struct scan_result_list *bss_list; |
| tScanResultHandle result_handle = NULL; |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| scan_filter = qdf_mem_malloc(sizeof(tCsrScanResultFilter)); |
| if (!scan_filter) { |
| status = QDF_STATUS_E_NOMEM; |
| goto free_scan_flter; |
| } |
| |
| status = csr_roam_prepare_filter_from_profile(mac_ctx, |
| profile, scan_filter); |
| if (QDF_STATUS_SUCCESS != status) { |
| sme_err("prepare_filter failed"); |
| goto free_scan_flter; |
| } |
| |
| /* update filter to get scan result with just target BSSID */ |
| if (NULL == scan_filter->BSSIDs.bssid) { |
| scan_filter->BSSIDs.bssid = |
| qdf_mem_malloc(sizeof(struct qdf_mac_addr)); |
| if (!scan_filter->BSSIDs.bssid) { |
| status = QDF_STATUS_E_NOMEM; |
| goto free_scan_flter; |
| } |
| } |
| |
| scan_filter->BSSIDs.numOfBSSIDs = 1; |
| qdf_mem_copy(scan_filter->BSSIDs.bssid[0].bytes, |
| bssid, sizeof(struct qdf_mac_addr)); |
| |
| status = csr_scan_get_result(mac_ctx, scan_filter, &result_handle); |
| if (QDF_STATUS_SUCCESS != status) { |
| sme_err("parse_scan_result failed"); |
| goto free_scan_flter; |
| } |
| |
| bss_list = (struct scan_result_list *)result_handle; |
| bss_descp = csr_get_fst_bssdescr_ptr(bss_list); |
| if (!bss_descp) { |
| sme_err("unable to fetch bss descriptor"); |
| status = QDF_STATUS_E_FAULT; |
| goto free_scan_flter; |
| } |
| |
| sme_debug("snr: %d, rssi: %d, raw_rssi: %d", |
| bss_descp->sinr, bss_descp->rssi, bss_descp->rssi_raw); |
| |
| if (rssi) |
| *rssi = bss_descp->rssi; |
| if (snr) |
| *snr = bss_descp->sinr; |
| |
| free_scan_flter: |
| /* free scan filter and exit */ |
| if (scan_filter) { |
| csr_free_scan_filter(mac_ctx, scan_filter); |
| qdf_mem_free(scan_filter); |
| } |
| |
| if (result_handle) |
| csr_scan_result_purge(mac_ctx, result_handle); |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_get_beacon_frm(mac_handle_t hal, |
| struct csr_roam_profile *profile, |
| const tSirMacAddr bssid, |
| uint8_t **frame_buf, uint32_t *frame_len, |
| int *channel) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tScanResultHandle result_handle = NULL; |
| tCsrScanResultFilter *scan_filter; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| tSirBssDescription *bss_descp; |
| struct scan_result_list *bss_list; |
| uint32_t ie_len; |
| |
| scan_filter = qdf_mem_malloc(sizeof(tCsrScanResultFilter)); |
| if (!scan_filter) { |
| status = QDF_STATUS_E_NOMEM; |
| goto free_scan_flter; |
| } |
| status = csr_roam_prepare_filter_from_profile(mac_ctx, |
| profile, scan_filter); |
| if (QDF_IS_STATUS_ERROR(status)) { |
| sme_err("prepare_filter failed"); |
| status = QDF_STATUS_E_FAULT; |
| goto free_scan_flter; |
| } |
| |
| /* update filter to get scan result with just target BSSID */ |
| if (NULL == scan_filter->BSSIDs.bssid) { |
| scan_filter->BSSIDs.bssid = |
| qdf_mem_malloc(sizeof(struct qdf_mac_addr)); |
| if (!scan_filter->BSSIDs.bssid) { |
| status = QDF_STATUS_E_NOMEM; |
| goto free_scan_flter; |
| } |
| } |
| scan_filter->BSSIDs.numOfBSSIDs = 1; |
| qdf_mem_copy(scan_filter->BSSIDs.bssid[0].bytes, |
| bssid, sizeof(struct qdf_mac_addr)); |
| |
| status = csr_scan_get_result(mac_ctx, scan_filter, &result_handle); |
| if (QDF_STATUS_SUCCESS != status) { |
| sme_err("parse_scan_result failed"); |
| status = QDF_STATUS_E_FAULT; |
| goto free_scan_flter; |
| } |
| |
| bss_list = (struct scan_result_list *)result_handle; |
| bss_descp = csr_get_fst_bssdescr_ptr(bss_list); |
| if (!bss_descp) { |
| sme_err("unable to fetch bss descriptor"); |
| status = QDF_STATUS_E_FAULT; |
| goto free_scan_flter; |
| } |
| |
| /** |
| * Length of BSS descriptor is without length of |
| * length itself and length of pointer that holds ieFields. |
| * |
| * tSirBssDescription |
| * +--------+---------------------------------+---------------+ |
| * | length | other fields | pointer to IEs| |
| * +--------+---------------------------------+---------------+ |
| * ^ |
| * ieFields |
| */ |
| ie_len = bss_descp->length + sizeof(bss_descp->length) |
| - (uint16_t)(offsetof(tSirBssDescription, ieFields[0])); |
| sme_debug("found bss_descriptor ie_len: %d channel %d", |
| ie_len, bss_descp->channelId); |
| |
| /* include mac header and fixed params along with IEs in frame */ |
| *frame_len = SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET + ie_len; |
| *frame_buf = qdf_mem_malloc(*frame_len); |
| if (!*frame_buf) { |
| status = QDF_STATUS_E_NOMEM; |
| goto free_scan_flter; |
| } |
| |
| sme_prepare_beacon_from_bss_descp(*frame_buf, bss_descp, bssid, ie_len); |
| |
| if (!*channel) |
| *channel = bss_descp->channelId; |
| free_scan_flter: |
| /* free scan filter and exit */ |
| if (scan_filter) { |
| csr_free_scan_filter(mac_ctx, scan_filter); |
| qdf_mem_free(scan_filter); |
| } |
| if (result_handle) |
| csr_scan_result_purge(mac_ctx, result_handle); |
| |
| return status; |
| } |
| |
| #ifdef WLAN_FEATURE_ROAM_OFFLOAD |
| QDF_STATUS sme_fast_reassoc(mac_handle_t hal, struct csr_roam_profile *profile, |
| const tSirMacAddr bssid, int channel, |
| uint8_t vdev_id, const tSirMacAddr connected_bssid) |
| { |
| QDF_STATUS status; |
| struct wma_roam_invoke_cmd *fastreassoc; |
| struct scheduler_msg msg = {0}; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct csr_roam_session *session; |
| struct csr_roam_profile *roam_profile; |
| |
| session = CSR_GET_SESSION(mac_ctx, vdev_id); |
| if (!session || !session->pCurRoamProfile) { |
| sme_err("session %d not found", vdev_id); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| roam_profile = session->pCurRoamProfile; |
| if (roam_profile->supplicant_disabled_roaming || |
| roam_profile->driver_disabled_roaming) { |
| sme_debug("roaming status in Supplicant %d and in driver %d", |
| roam_profile->supplicant_disabled_roaming, |
| roam_profile->driver_disabled_roaming); |
| return QDF_STATUS_E_FAILURE; |
| } |
| fastreassoc = qdf_mem_malloc(sizeof(*fastreassoc)); |
| if (!fastreassoc) |
| return QDF_STATUS_E_NOMEM; |
| |
| /* if both are same then set the flag */ |
| if (!qdf_mem_cmp(connected_bssid, bssid, ETH_ALEN)) { |
| fastreassoc->is_same_bssid = true; |
| sme_debug("bssid same, bssid[%pM]", bssid); |
| } |
| fastreassoc->vdev_id = vdev_id; |
| fastreassoc->bssid[0] = bssid[0]; |
| fastreassoc->bssid[1] = bssid[1]; |
| fastreassoc->bssid[2] = bssid[2]; |
| fastreassoc->bssid[3] = bssid[3]; |
| fastreassoc->bssid[4] = bssid[4]; |
| fastreassoc->bssid[5] = bssid[5]; |
| |
| status = sme_get_beacon_frm(hal, profile, bssid, |
| &fastreassoc->frame_buf, |
| &fastreassoc->frame_len, |
| &channel); |
| |
| if (!channel) { |
| sme_err("channel retrieval from BSS desc fails!"); |
| qdf_mem_free(fastreassoc); |
| return QDF_STATUS_E_FAULT; |
| } |
| |
| fastreassoc->channel = channel; |
| if (QDF_STATUS_SUCCESS != status) { |
| sme_warn("sme_get_beacon_frm failed"); |
| fastreassoc->frame_buf = NULL; |
| fastreassoc->frame_len = 0; |
| } |
| |
| if (csr_is_auth_type_ese(mac_ctx->roam.roamSession[vdev_id]. |
| connectedProfile.AuthType)) { |
| sme_debug("Beacon is not required for ESE"); |
| if (fastreassoc->frame_len) { |
| qdf_mem_free(fastreassoc->frame_buf); |
| fastreassoc->frame_buf = NULL; |
| fastreassoc->frame_len = 0; |
| } |
| } |
| |
| msg.type = eWNI_SME_ROAM_INVOKE; |
| msg.reserved = 0; |
| msg.bodyptr = fastreassoc; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_PE, |
| QDF_MODULE_ID_PE, &msg); |
| if (QDF_STATUS_SUCCESS != status) { |
| sme_err("Not able to post ROAM_INVOKE_CMD message to PE"); |
| qdf_mem_free(fastreassoc); |
| } |
| |
| return status; |
| } |
| #endif |
| |
| QDF_STATUS sme_set_del_pmkid_cache(mac_handle_t hal, uint8_t session_id, |
| tPmkidCacheInfo *pmk_cache_info, |
| bool is_add) |
| { |
| struct wmi_unified_pmk_cache *pmk_cache; |
| struct scheduler_msg msg; |
| |
| pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache)); |
| if (!pmk_cache) |
| return QDF_STATUS_E_NOMEM; |
| |
| qdf_mem_set(pmk_cache, sizeof(*pmk_cache), 0); |
| |
| pmk_cache->session_id = session_id; |
| |
| if (!pmk_cache_info) |
| goto send_flush_cmd; |
| |
| if (!pmk_cache_info->ssid_len) { |
| pmk_cache->cat_flag = WMI_PMK_CACHE_CAT_FLAG_BSSID; |
| WMI_CHAR_ARRAY_TO_MAC_ADDR(pmk_cache_info->BSSID.bytes, |
| &pmk_cache->bssid); |
| } else { |
| pmk_cache->cat_flag = WMI_PMK_CACHE_CAT_FLAG_SSID_CACHE_ID; |
| pmk_cache->ssid.length = pmk_cache_info->ssid_len; |
| qdf_mem_copy(pmk_cache->ssid.mac_ssid, |
| pmk_cache_info->ssid, |
| pmk_cache->ssid.length); |
| } |
| pmk_cache->cache_id = (uint32_t) (pmk_cache_info->cache_id[0] << 8 | |
| pmk_cache_info->cache_id[1]); |
| |
| if (is_add) |
| pmk_cache->action_flag = WMI_PMK_CACHE_ACTION_FLAG_ADD_ENTRY; |
| else |
| pmk_cache->action_flag = WMI_PMK_CACHE_ACTION_FLAG_DEL_ENTRY; |
| |
| pmk_cache->pmkid_len = CSR_RSN_PMKID_SIZE; |
| qdf_mem_copy(pmk_cache->pmkid, pmk_cache_info->PMKID, |
| CSR_RSN_PMKID_SIZE); |
| |
| pmk_cache->pmk_len = pmk_cache_info->pmk_len; |
| qdf_mem_copy(pmk_cache->pmk, pmk_cache_info->pmk, |
| pmk_cache->pmk_len); |
| |
| send_flush_cmd: |
| msg.type = SIR_HAL_SET_DEL_PMKID_CACHE; |
| msg.reserved = 0; |
| msg.bodyptr = pmk_cache; |
| if (QDF_STATUS_SUCCESS != |
| scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg)) { |
| sme_err("Not able to post message to WDA"); |
| qdf_mem_free(pmk_cache); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /* ARP DEBUG STATS */ |
| |
| /** |
| * sme_set_nud_debug_stats() - sme api to set nud debug stats |
| * @hal: handle to hal |
| * @set_stats_param: pointer to set stats param |
| * |
| * Return: Return QDF_STATUS. |
| */ |
| QDF_STATUS sme_set_nud_debug_stats(mac_handle_t hal, |
| struct set_arp_stats_params |
| *set_stats_param) |
| { |
| struct set_arp_stats_params *arp_set_param; |
| struct scheduler_msg msg; |
| |
| arp_set_param = qdf_mem_malloc(sizeof(*arp_set_param)); |
| if (!arp_set_param) |
| return QDF_STATUS_E_NOMEM; |
| |
| qdf_mem_copy(arp_set_param, set_stats_param, sizeof(*arp_set_param)); |
| |
| msg.type = WMA_SET_ARP_STATS_REQ; |
| msg.reserved = 0; |
| msg.bodyptr = arp_set_param; |
| |
| if (QDF_STATUS_SUCCESS != |
| scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg)) { |
| sme_err("Not able to post message to WDA"); |
| qdf_mem_free(arp_set_param); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * sme_get_nud_debug_stats() - sme api to get nud debug stats |
| * @hal: handle to hal |
| * @get_stats_param: pointer to set stats param |
| * |
| * Return: Return QDF_STATUS. |
| */ |
| QDF_STATUS sme_get_nud_debug_stats(mac_handle_t hal, |
| struct get_arp_stats_params |
| *get_stats_param) |
| { |
| struct get_arp_stats_params *arp_get_param; |
| struct scheduler_msg msg; |
| |
| arp_get_param = qdf_mem_malloc(sizeof(*arp_get_param)); |
| if (!arp_get_param) |
| return QDF_STATUS_E_NOMEM; |
| |
| qdf_mem_copy(arp_get_param, get_stats_param, sizeof(*arp_get_param)); |
| |
| msg.type = WMA_GET_ARP_STATS_REQ; |
| msg.reserved = 0; |
| msg.bodyptr = arp_get_param; |
| |
| if (QDF_STATUS_SUCCESS != |
| scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg)) { |
| sme_err("Not able to post message to WDA"); |
| qdf_mem_free(arp_get_param); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| QDF_STATUS sme_set_peer_param(uint8_t *peer_addr, uint32_t param_id, |
| uint32_t param_value, uint32_t vdev_id) |
| { |
| void *wma_handle; |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| sme_err("wma handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return wma_set_peer_param(wma_handle, peer_addr, param_id, |
| param_value, vdev_id); |
| } |
| |
| QDF_STATUS sme_register_set_connection_info_cb(mac_handle_t mac_handle, |
| bool (*set_connection_info_cb)(bool), |
| bool (*get_connection_info_cb)(uint8_t *session_id, |
| enum scan_reject_states *reason)) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal pMac = PMAC_STRUCT(mac_handle); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| pMac->sme.set_connection_info_cb = set_connection_info_cb; |
| pMac->sme.get_connection_info_cb = get_connection_info_cb; |
| sme_release_global_lock(&pMac->sme); |
| } |
| return status; |
| } |
| |
| QDF_STATUS sme_rso_cmd_status_cb(mac_handle_t mac_handle, |
| rso_cmd_status_cb cb) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| |
| mac->sme.rso_cmd_status_cb = cb; |
| sme_debug("Registered RSO command status callback"); |
| return status; |
| } |
| |
| QDF_STATUS sme_set_dbs_scan_selection_config(mac_handle_t hal, |
| struct wmi_dbs_scan_sel_params *params) |
| { |
| struct scheduler_msg message = {0}; |
| QDF_STATUS status; |
| struct wmi_dbs_scan_sel_params *dbs_scan_params; |
| uint32_t i; |
| |
| if (0 == params->num_clients) { |
| sme_err("Num of clients is 0"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| dbs_scan_params = qdf_mem_malloc(sizeof(*dbs_scan_params)); |
| if (!dbs_scan_params) |
| return QDF_STATUS_E_NOMEM; |
| |
| dbs_scan_params->num_clients = params->num_clients; |
| dbs_scan_params->pdev_id = params->pdev_id; |
| for (i = 0; i < params->num_clients; i++) { |
| dbs_scan_params->module_id[i] = params->module_id[i]; |
| dbs_scan_params->num_dbs_scans[i] = params->num_dbs_scans[i]; |
| dbs_scan_params->num_non_dbs_scans[i] = |
| params->num_non_dbs_scans[i]; |
| } |
| message.type = WMA_SET_DBS_SCAN_SEL_CONF_PARAMS; |
| message.bodyptr = dbs_scan_params; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &message); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("Not able to post msg to WMA!"); |
| qdf_mem_free(dbs_scan_params); |
| } |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_get_rcpi(mac_handle_t hal, struct sme_rcpi_req *rcpi) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal pMac = PMAC_STRUCT(hal); |
| struct scheduler_msg msg = {0}; |
| struct sme_rcpi_req *rcpi_req; |
| |
| rcpi_req = qdf_mem_malloc(sizeof(*rcpi_req)); |
| if (!rcpi_req) |
| return QDF_STATUS_E_NOMEM; |
| |
| qdf_mem_copy(rcpi_req, rcpi, sizeof(*rcpi_req)); |
| |
| status = sme_acquire_global_lock(&pMac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| msg.bodyptr = rcpi_req; |
| msg.type = WMA_GET_RCPI_REQ; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, &msg); |
| sme_release_global_lock(&pMac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("post get rcpi req failed")); |
| status = QDF_STATUS_E_FAILURE; |
| qdf_mem_free(rcpi_req); |
| } |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("sme_acquire_global_lock failed")); |
| qdf_mem_free(rcpi_req); |
| } |
| |
| return status; |
| } |
| |
| void sme_store_pdev(mac_handle_t hal, struct wlan_objmgr_pdev *pdev) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| void *wma_handle; |
| QDF_STATUS status; |
| |
| status = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_LEGACY_MAC_ID); |
| if (QDF_STATUS_SUCCESS != status) { |
| mac_ctx->pdev = NULL; |
| return; |
| } |
| mac_ctx->pdev = pdev; |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("wma handle is NULL")); |
| return; |
| } |
| wma_store_pdev(wma_handle, pdev); |
| } |
| |
| QDF_STATUS sme_congestion_register_callback(mac_handle_t hal, |
| congestion_cb congestion_cb) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| mac->sme.congestion_cb = congestion_cb; |
| sme_release_global_lock(&mac->sme); |
| sme_debug("congestion callback set"); |
| } else { |
| sme_err("Aquiring lock failed %d", status); |
| } |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_register_tx_queue_cb(mac_handle_t mac_handle, |
| tx_queue_cb tx_queue_cb) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| mac->sme.tx_queue_cb = tx_queue_cb; |
| sme_release_global_lock(&mac->sme); |
| sme_debug("Tx queue callback set"); |
| } else { |
| sme_err("Aquiring lock failed %d", status); |
| } |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_deregister_tx_queue_cb(mac_handle_t mac_handle) |
| { |
| return sme_register_tx_queue_cb(mac_handle, NULL); |
| } |
| |
| #ifdef WLAN_SUPPORT_TWT |
| QDF_STATUS sme_register_twt_enable_complete_cb(mac_handle_t mac_handle, |
| twt_enable_cb twt_enable_cb) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| mac->sme.twt_enable_cb = twt_enable_cb; |
| sme_release_global_lock(&mac->sme); |
| sme_debug("TWT: enable callback set"); |
| } else { |
| sme_err("Aquiring lock failed %d", status); |
| } |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_register_twt_disable_complete_cb(mac_handle_t mac_handle, |
| twt_disable_cb twt_disable_cb) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| mac->sme.twt_disable_cb = twt_disable_cb; |
| sme_release_global_lock(&mac->sme); |
| sme_debug("TWT: disable callback set"); |
| } else { |
| sme_err("Aquiring lock failed %d", status); |
| } |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_deregister_twt_enable_complete_cb(mac_handle_t mac_handle) |
| { |
| return sme_register_twt_enable_complete_cb(mac_handle, NULL); |
| } |
| |
| QDF_STATUS sme_deregister_twt_disable_complete_cb(mac_handle_t mac_handle) |
| { |
| return sme_register_twt_disable_complete_cb(mac_handle, NULL); |
| } |
| #endif |
| |
| QDF_STATUS sme_set_smps_cfg(uint32_t vdev_id, uint32_t param_id, |
| uint32_t param_val) |
| { |
| return wma_configure_smps_params(vdev_id, param_id, param_val); |
| } |
| |
| QDF_STATUS sme_ipa_uc_stat_request(mac_handle_t hal, uint32_t vdev_id, |
| uint32_t param_id, uint32_t param_val, uint32_t req_cat) |
| { |
| wma_cli_set_cmd_t *iwcmd; |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| iwcmd = qdf_mem_malloc(sizeof(*iwcmd)); |
| if (!iwcmd) |
| return QDF_STATUS_E_NOMEM; |
| |
| qdf_mem_zero(iwcmd, sizeof(*iwcmd)); |
| iwcmd->param_sec_value = 0; |
| iwcmd->param_vdev_id = vdev_id; |
| iwcmd->param_id = param_id; |
| iwcmd->param_vp_dev = req_cat; |
| iwcmd->param_value = param_val; |
| wma_ipa_uc_stat_request(iwcmd); |
| qdf_mem_free(iwcmd); |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_set_reorder_timeout(mac_handle_t hal, |
| struct sir_set_rx_reorder_timeout_val *req) |
| { |
| QDF_STATUS status; |
| tp_wma_handle wma_handle; |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| status = wma_set_rx_reorder_timeout_val(wma_handle, req); |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_set_rx_set_blocksize(mac_handle_t hal, |
| struct sir_peer_set_rx_blocksize *req) |
| { |
| QDF_STATUS status; |
| tp_wma_handle wma_handle; |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| status = wma_set_rx_blocksize(wma_handle, req); |
| |
| return status; |
| } |
| |
| int sme_cli_set_command(int vdev_id, int param_id, int sval, int vpdev) |
| { |
| return wma_cli_set_command(vdev_id, param_id, sval, vpdev); |
| } |
| |
| int sme_set_enable_mem_deep_sleep(mac_handle_t mac_handle, int vdev_id) |
| { |
| tpAniSirGlobal mac_ctx = MAC_CONTEXT(mac_handle); |
| |
| return wma_cli_set_command(vdev_id, WMI_PDEV_PARAM_HYST_EN, |
| mac_ctx->mlme_cfg->gen.memory_deep_sleep, |
| PDEV_CMD); |
| } |
| |
| int sme_set_cck_tx_fir_override(mac_handle_t mac_handle, int vdev_id) |
| { |
| tpAniSirGlobal mac_ctx = MAC_CONTEXT(mac_handle); |
| |
| return wma_cli_set_command(vdev_id, |
| WMI_PDEV_PARAM_ENABLE_CCK_TXFIR_OVERRIDE, |
| mac_ctx->mlme_cfg->gen.cck_tx_fir_override, |
| PDEV_CMD); |
| } |
| |
| QDF_STATUS sme_set_bt_activity_info_cb(mac_handle_t mac_handle, |
| bt_activity_info_cb cb) |
| { |
| QDF_STATUS status; |
| tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| mac->sme.bt_activity_info_cb = cb; |
| sme_release_global_lock(&mac->sme); |
| sme_debug("bt activity info callback set"); |
| } else { |
| sme_debug("sme_acquire_global_lock failed %d", status); |
| } |
| |
| return status; |
| } |
| |
| QDF_STATUS sme_get_chain_rssi(mac_handle_t hal, |
| struct get_chain_rssi_req_params *input, |
| get_chain_rssi_callback callback, |
| void *context) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| tp_wma_handle wma_handle; |
| |
| SME_ENTER(); |
| |
| if (NULL == input) { |
| sme_err("Invalid req params"); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| mac_ctx->sme.get_chain_rssi_cb = callback; |
| mac_ctx->sme.get_chain_rssi_context = context; |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| wma_get_chain_rssi(wma_handle, input); |
| |
| SME_EXIT(); |
| return status; |
| } |
| |
| QDF_STATUS sme_process_msg_callback(tpAniSirGlobal mac, |
| struct scheduler_msg *msg) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| |
| if (msg == NULL) { |
| sme_err("Empty message for SME Msg callback"); |
| return status; |
| } |
| status = sme_process_msg(mac, msg); |
| return status; |
| } |
| |
| void sme_display_disconnect_stats(mac_handle_t hal, uint8_t session_id) |
| { |
| struct csr_roam_session *session; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) { |
| sme_err("%s Invalid session id: %d", __func__, session_id); |
| return; |
| } |
| |
| session = CSR_GET_SESSION(mac_ctx, session_id); |
| if (!session) { |
| sme_err("%s Failed to get session for id: %d", |
| __func__, session_id); |
| return; |
| } |
| |
| sme_nofl_info("Total No. of Disconnections: %d", |
| session->disconnect_stats.disconnection_cnt); |
| |
| sme_nofl_info("No. of Diconnects Triggered by Application: %d", |
| session->disconnect_stats.disconnection_by_app); |
| |
| sme_nofl_info("No. of Disassoc Sent by Peer: %d", |
| session->disconnect_stats.disassoc_by_peer); |
| |
| sme_nofl_info("No. of Deauth Sent by Peer: %d", |
| session->disconnect_stats.deauth_by_peer); |
| |
| sme_nofl_info("No. of Disconnections due to Beacon Miss: %d", |
| session->disconnect_stats.bmiss); |
| |
| sme_nofl_info("No. of Disconnections due to Peer Kickout: %d", |
| session->disconnect_stats.peer_kickout); |
| } |
| |
| #ifdef FEATURE_WLAN_DYNAMIC_CVM |
| /** |
| * sme_set_vc_mode_config() - Set voltage corner config to FW |
| * @bitmap: Bitmap that referes to voltage corner config with |
| * different phymode and bw configuration |
| * |
| * Return: QDF_STATUS |
| */ |
| QDF_STATUS sme_set_vc_mode_config(uint32_t vc_bitmap) |
| { |
| void *wma_handle; |
| |
| wma_handle = cds_get_context(QDF_MODULE_ID_WMA); |
| if (!wma_handle) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "wma_handle is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| if (QDF_STATUS_SUCCESS != |
| wma_set_vc_mode_config(wma_handle, vc_bitmap)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| "%s: Failed to set Voltage Control config to FW", |
| __func__); |
| return QDF_STATUS_E_FAILURE; |
| } |
| return QDF_STATUS_SUCCESS; |
| } |
| #endif |
| |
| /** |
| * sme_set_bmiss_bcnt() - set bmiss config parameters |
| * @vdev_id: virtual device for the command |
| * @first_cnt: bmiss first value |
| * @final_cnt: bmiss final value |
| * |
| * Return: QDF_STATUS_SUCCESS or non-zero on failure |
| */ |
| QDF_STATUS sme_set_bmiss_bcnt(uint32_t vdev_id, uint32_t first_cnt, |
| uint32_t final_cnt) |
| { |
| return wma_config_bmiss_bcnt_params(vdev_id, first_cnt, final_cnt); |
| } |
| |
| QDF_STATUS sme_send_limit_off_channel_params(mac_handle_t hal, uint8_t vdev_id, |
| bool is_tos_active, uint32_t max_off_chan_time, |
| uint32_t rest_time, bool skip_dfs_chan) |
| { |
| struct sir_limit_off_chan *cmd; |
| struct scheduler_msg msg = {0}; |
| |
| cmd = qdf_mem_malloc(sizeof(*cmd)); |
| if (!cmd) |
| return QDF_STATUS_E_NOMEM; |
| |
| cmd->vdev_id = vdev_id; |
| cmd->is_tos_active = is_tos_active; |
| cmd->max_off_chan_time = max_off_chan_time; |
| cmd->rest_time = rest_time; |
| cmd->skip_dfs_chans = skip_dfs_chan; |
| |
| msg.type = WMA_SET_LIMIT_OFF_CHAN; |
| msg.reserved = 0; |
| msg.bodyptr = cmd; |
| |
| if (!QDF_IS_STATUS_SUCCESS(scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &msg))) { |
| sme_err("Not able to post WMA_SET_LIMIT_OFF_CHAN to WMA"); |
| qdf_mem_free(cmd); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| uint32_t sme_unpack_rsn_ie(mac_handle_t hal, uint8_t *buf, |
| uint8_t buf_len, tDot11fIERSN *rsn_ie, |
| bool append_ie) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| return dot11f_unpack_ie_rsn(mac_ctx, buf, buf_len, rsn_ie, append_ie); |
| } |
| |
| #ifdef FEATURE_BSS_TRANSITION |
| /** |
| * sme_get_status_for_candidate() - Get bss transition status for candidate |
| * @hal: Handle for HAL |
| * @conn_bss_desc: connected bss descriptor |
| * @bss_desc: candidate bss descriptor |
| * @info: candiadate bss information |
| * @trans_reason: transition reason code |
| * @is_bt_in_progress: bt activity indicator |
| * |
| * Return : true if candidate is rejected and reject reason is filled |
| * @info->status. Otherwise returns false. |
| */ |
| static bool sme_get_status_for_candidate(mac_handle_t hal, |
| tSirBssDescription *conn_bss_desc, |
| tSirBssDescription *bss_desc, |
| struct bss_candidate_info *info, |
| uint8_t trans_reason, |
| bool is_bt_in_progress) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct wlan_mlme_mbo *mbo_cfg; |
| int8_t current_rssi_mcc_thres; |
| |
| if (!(mac_ctx->mlme_cfg)) { |
| pe_err("mlme cfg is NULL"); |
| return false; |
| } |
| mbo_cfg = &mac_ctx->mlme_cfg->mbo_cfg; |
| |
| /* |
| * Low RSSI based rejection |
| * If candidate rssi is less than mbo_candidate_rssi_thres and connected |
| * bss rssi is greater than mbo_current_rssi_thres, then reject the |
| * candidate with MBO reason code 4. |
| */ |
| if ((bss_desc->rssi < mbo_cfg->mbo_candidate_rssi_thres) && |
| (conn_bss_desc->rssi > mbo_cfg->mbo_current_rssi_thres)) { |
| sme_err("Candidate BSS "MAC_ADDRESS_STR" has LOW RSSI(%d), hence reject", |
| MAC_ADDR_ARRAY(bss_desc->bssId), bss_desc->rssi); |
| info->status = QCA_STATUS_REJECT_LOW_RSSI; |
| return true; |
| } |
| |
| if (trans_reason == MBO_TRANSITION_REASON_LOAD_BALANCING || |
| trans_reason == MBO_TRANSITION_REASON_TRANSITIONING_TO_PREMIUM_AP) { |
| /* |
| * MCC rejection |
| * If moving to candidate's channel will result in MCC scenario |
| * and the rssi of connected bss is greater than |
| * mbo_current_rssi_mss_thres, then reject the candidate with |
| * MBO reason code 3. |
| */ |
| current_rssi_mcc_thres = mbo_cfg->mbo_current_rssi_mcc_thres; |
| if ((conn_bss_desc->rssi > current_rssi_mcc_thres) && |
| csr_is_mcc_channel(mac_ctx, bss_desc->channelId)) { |
| sme_err("Candidate BSS "MAC_ADDRESS_STR" causes MCC, hence reject", |
| MAC_ADDR_ARRAY(bss_desc->bssId)); |
| info->status = |
| QCA_STATUS_REJECT_INSUFFICIENT_QOS_CAPACITY; |
| return true; |
| } |
| |
| /* |
| * BT coex rejection |
| * If AP is trying to move the client from 5G to 2.4G and moving |
| * to 2.4G will result in BT coex and candidate channel rssi is |
| * less than mbo_candidate_rssi_btc_thres, then reject the |
| * candidate with MBO reason code 2. |
| */ |
| if (WLAN_REG_IS_5GHZ_CH(conn_bss_desc->channelId) && |
| WLAN_REG_IS_24GHZ_CH(bss_desc->channelId) && |
| is_bt_in_progress && |
| (bss_desc->rssi < mbo_cfg->mbo_candidate_rssi_btc_thres)) { |
| sme_err("Candidate BSS "MAC_ADDRESS_STR" causes BT coex, hence reject", |
| MAC_ADDR_ARRAY(bss_desc->bssId)); |
| info->status = |
| QCA_STATUS_REJECT_EXCESSIVE_DELAY_EXPECTED; |
| return true; |
| } |
| |
| /* |
| * LTE coex rejection |
| * If moving to candidate's channel can cause LTE coex, then |
| * reject the candidate with MBO reason code 5. |
| */ |
| if (policy_mgr_is_safe_channel(mac_ctx->psoc, |
| conn_bss_desc->channelId) && |
| !(policy_mgr_is_safe_channel(mac_ctx->psoc, |
| bss_desc->channelId))) { |
| sme_err("High interference expected if transitioned to BSS " |
| MAC_ADDRESS_STR" hence reject", |
| MAC_ADDR_ARRAY(bss_desc->bssId)); |
| info->status = |
| QCA_STATUS_REJECT_HIGH_INTERFERENCE; |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * wlan_hdd_get_bss_transition_status() - get bss transition status all cadidates |
| * @adapter : Pointer to adapter |
| * @transition_reason : Transition reason |
| * @info : bss candidate information |
| * @n_candidates : number of candidates |
| * |
| * Return : 0 on success otherwise errno |
| */ |
| int sme_get_bss_transition_status(mac_handle_t hal, |
| uint8_t transition_reason, |
| struct qdf_mac_addr *bssid, |
| struct bss_candidate_info *info, |
| uint16_t n_candidates, |
| bool is_bt_in_progress) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| tSirBssDescription *bss_desc, *conn_bss_desc; |
| tCsrScanResultInfo *res, *conn_res; |
| uint16_t i; |
| |
| if (!n_candidates || !info) { |
| sme_err("No candidate info available"); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| conn_res = qdf_mem_malloc(sizeof(tCsrScanResultInfo)); |
| if (!conn_res) |
| return QDF_STATUS_E_NOMEM; |
| |
| res = qdf_mem_malloc(sizeof(tCsrScanResultInfo)); |
| if (!res) { |
| status = QDF_STATUS_E_NOMEM; |
| goto free; |
| } |
| |
| /* Get the connected BSS descriptor */ |
| status = sme_scan_get_result_for_bssid(hal, bssid, conn_res); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("Failed to find connected BSS in scan list"); |
| goto free; |
| } |
| conn_bss_desc = &conn_res->BssDescriptor; |
| |
| for (i = 0; i < n_candidates; i++) { |
| /* Get candidate BSS descriptors */ |
| status = sme_scan_get_result_for_bssid(hal, &info[i].bssid, |
| res); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| sme_err("BSS "MAC_ADDRESS_STR" not present in scan list", |
| MAC_ADDR_ARRAY(info[i].bssid.bytes)); |
| info[i].status = QCA_STATUS_REJECT_UNKNOWN; |
| continue; |
| } |
| |
| bss_desc = &res->BssDescriptor; |
| if (!sme_get_status_for_candidate(hal, conn_bss_desc, bss_desc, |
| &info[i], transition_reason, is_bt_in_progress)) { |
| /* |
| * If status is not over written, it means it is a |
| * candidate for accept. |
| */ |
| info[i].status = QCA_STATUS_ACCEPT; |
| } |
| } |
| |
| /* success */ |
| status = QDF_STATUS_SUCCESS; |
| |
| free: |
| /* free allocated memory */ |
| if (conn_res) |
| qdf_mem_free(conn_res); |
| if (res) |
| qdf_mem_free(res); |
| |
| return status; |
| } |
| #endif /* FEATURE_BSS_TRANSITION */ |
| |
| bool sme_is_conn_state_connected(mac_handle_t hal, uint8_t session_id) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| return csr_is_conn_state_connected(mac_ctx, session_id); |
| } |
| |
| void sme_enable_roaming_on_connected_sta(mac_handle_t hal) |
| { |
| uint8_t session_id; |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| QDF_STATUS status; |
| |
| session_id = csr_get_roam_enabled_sta_sessionid(mac_ctx); |
| if (session_id != CSR_SESSION_ID_INVALID) |
| return; |
| |
| session_id = csr_get_connected_infra(mac_ctx); |
| if (session_id == CSR_SESSION_ID_INVALID) { |
| sme_debug("No STA in conencted state"); |
| return; |
| } |
| |
| sme_debug("Roaming not enabled on any STA, enable roaming on session %d", |
| session_id); |
| status = sme_acquire_global_lock(&mac_ctx->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| csr_roam_offload_scan(mac_ctx, session_id, |
| ROAM_SCAN_OFFLOAD_START, |
| REASON_CTX_INIT); |
| sme_release_global_lock(&mac_ctx->sme); |
| } |
| } |
| |
| int16_t sme_get_oper_chan_freq(struct wlan_objmgr_vdev *vdev) |
| { |
| uint8_t vdev_id, chan; |
| struct csr_roam_session *session; |
| tpAniSirGlobal mac_ctx; |
| mac_handle_t mac_handle; |
| int16_t freq = 0; |
| |
| if (vdev == NULL) { |
| sme_err("Invalid vdev id is passed"); |
| return 0; |
| } |
| |
| mac_handle = cds_get_context(QDF_MODULE_ID_SME); |
| if (!mac_handle) { |
| sme_err("mac_handle is null"); |
| return 0; |
| } |
| mac_ctx = PMAC_STRUCT(mac_handle); |
| vdev_id = wlan_vdev_get_id(vdev); |
| if (!CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) { |
| sme_err("Invalid vdev id is passed"); |
| return 0; |
| } |
| |
| session = CSR_GET_SESSION(mac_ctx, vdev_id); |
| chan = csr_get_infra_operation_channel(mac_ctx, vdev_id); |
| if (chan) |
| freq = cds_chan_to_freq(chan); |
| |
| return freq; |
| } |
| |
| enum phy_ch_width sme_get_oper_ch_width(struct wlan_objmgr_vdev *vdev) |
| { |
| uint8_t vdev_id; |
| struct csr_roam_session *session; |
| tpAniSirGlobal mac_ctx; |
| mac_handle_t mac_handle; |
| enum phy_ch_width ch_width = CH_WIDTH_20MHZ; |
| |
| if (vdev == NULL) { |
| sme_err("Invalid vdev id is passed"); |
| return CH_WIDTH_INVALID; |
| } |
| |
| mac_handle = cds_get_context(QDF_MODULE_ID_SME); |
| if (!mac_handle) { |
| sme_err("mac_handle is null"); |
| return CH_WIDTH_INVALID; |
| } |
| mac_ctx = PMAC_STRUCT(mac_handle); |
| vdev_id = wlan_vdev_get_id(vdev); |
| if (!CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) { |
| sme_err("Invalid vdev id is passed"); |
| return CH_WIDTH_INVALID; |
| } |
| |
| session = CSR_GET_SESSION(mac_ctx, vdev_id); |
| |
| if (csr_is_conn_state_connected(mac_ctx, vdev_id)) |
| ch_width = session->connectedProfile.vht_channel_width; |
| |
| return ch_width; |
| } |
| |
| int sme_get_sec20chan_freq_mhz(struct wlan_objmgr_vdev *vdev, |
| uint16_t *sec20chan_freq) |
| { |
| uint8_t vdev_id; |
| |
| vdev_id = wlan_vdev_get_id(vdev); |
| /* Need to extend */ |
| return 0; |
| } |
| |
| #ifdef WLAN_FEATURE_SAE |
| QDF_STATUS sme_handle_sae_msg(mac_handle_t hal, uint8_t session_id, |
| uint8_t sae_status) |
| { |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| struct sir_sae_msg *sae_msg; |
| struct scheduler_msg sch_msg = {0}; |
| |
| qdf_status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| sae_msg = qdf_mem_malloc(sizeof(*sae_msg)); |
| if (!sae_msg) { |
| qdf_status = QDF_STATUS_E_NOMEM; |
| } else { |
| sae_msg->message_type = eWNI_SME_SEND_SAE_MSG; |
| sae_msg->length = sizeof(*sae_msg); |
| sae_msg->session_id = session_id; |
| sae_msg->sae_status = sae_status; |
| sme_debug("SAE: sae_status %d session_id %d", |
| sae_msg->sae_status, |
| sae_msg->session_id); |
| |
| sch_msg.type = eWNI_SME_SEND_SAE_MSG; |
| sch_msg.bodyptr = sae_msg; |
| |
| qdf_status = |
| scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_PE, |
| QDF_MODULE_ID_PE, |
| &sch_msg); |
| } |
| sme_release_global_lock(&mac->sme); |
| } |
| |
| return qdf_status; |
| } |
| #endif |
| |
| bool sme_is_sta_key_exchange_in_progress(mac_handle_t hal, uint8_t session_id) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| |
| if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) { |
| sme_err("Invalid session id: %d", session_id); |
| return false; |
| } |
| |
| return CSR_IS_WAIT_FOR_KEY(mac_ctx, session_id); |
| } |
| |
| bool sme_validate_channel_list(mac_handle_t hal, |
| uint8_t *chan_list, |
| uint8_t num_channels) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| uint8_t i = 0; |
| uint8_t j; |
| bool found; |
| struct csr_channel *ch_lst_info = &mac_ctx->scan.base_channels; |
| |
| if (!chan_list || !num_channels) { |
| sme_err("Chan list empty %pK or num_channels is 0", chan_list); |
| return false; |
| } |
| |
| while (i < num_channels) { |
| found = false; |
| for (j = 0; j < ch_lst_info->numChannels; j++) { |
| if (ch_lst_info->channelList[j] == chan_list[i]) { |
| found = true; |
| break; |
| } |
| } |
| |
| if (!found) { |
| sme_debug("Invalid channel %d", chan_list[i]); |
| return false; |
| } |
| |
| i++; |
| } |
| |
| return true; |
| } |
| |
| void sme_set_amsdu(mac_handle_t hal, bool enable) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| mac_ctx->is_usr_cfg_amsdu_enabled = enable; |
| } |
| |
| uint8_t sme_get_mcs_idx(uint16_t max_rate, uint8_t rate_flags, |
| uint8_t *nss, uint8_t *mcs_rate_flags) |
| { |
| return wma_get_mcs_idx(max_rate, rate_flags, nss, mcs_rate_flags); |
| } |
| |
| bool sme_find_session_by_bssid(mac_handle_t hal, uint8_t *bssid) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| bool ret; |
| |
| ret = csr_find_session_by_bssid(mac_ctx, bssid); |
| |
| return ret; |
| } |
| |
| QDF_STATUS |
| sme_get_roam_scan_stats(mac_handle_t hal, roam_scan_stats_cb cb, void *context, |
| uint32_t vdev_id) |
| { |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| tpAniSirGlobal mac = PMAC_STRUCT(hal); |
| struct scheduler_msg msg = {0}; |
| struct sir_roam_scan_stats *req; |
| |
| req = qdf_mem_malloc(sizeof(*req)); |
| if (!req) |
| return QDF_STATUS_E_NOMEM; |
| |
| req->vdev_id = vdev_id; |
| req->cb = cb; |
| req->context = context; |
| |
| status = sme_acquire_global_lock(&mac->sme); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| msg.bodyptr = req; |
| msg.type = WMA_GET_ROAM_SCAN_STATS; |
| msg.reserved = 0; |
| status = scheduler_post_message(QDF_MODULE_ID_SME, |
| QDF_MODULE_ID_WMA, |
| QDF_MODULE_ID_WMA, |
| &msg); |
| sme_release_global_lock(&mac->sme); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, |
| FL("post roam scan stats req failed")); |
| status = QDF_STATUS_E_FAILURE; |
| qdf_mem_free(req); |
| } |
| } else { |
| sme_err("sme_acquire_global_lock failed"); |
| qdf_mem_free(req); |
| } |
| |
| return status; |
| } |
| |
| void sme_update_score_config(mac_handle_t hal, |
| struct scoring_config *score_config) |
| { |
| tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); |
| struct wlan_mlme_scoring_cfg *mlme_scoring_cfg; |
| |
| mlme_scoring_cfg = &mac_ctx->mlme_cfg->scoring; |
| |
| score_config->weight_cfg.rssi_weightage = |
| mlme_scoring_cfg->weight_cfg.rssi_weightage; |
| score_config->weight_cfg.ht_caps_weightage = |
| mlme_scoring_cfg->weight_cfg.ht_caps_weightage; |
| score_config->weight_cfg.vht_caps_weightage = |
| mlme_scoring_cfg->weight_cfg.vht_caps_weightage; |
| score_config->weight_cfg.he_caps_weightage = |
| mlme_scoring_cfg->weight_cfg.he_caps_weightage; |
| score_config->weight_cfg.chan_width_weightage = |
| mlme_scoring_cfg->weight_cfg.chan_width_weightage; |
| score_config->weight_cfg.chan_band_weightage = |
| mlme_scoring_cfg->weight_cfg.chan_band_weightage; |
| score_config->weight_cfg.nss_weightage = |
| mlme_scoring_cfg->weight_cfg.nss_weightage; |
| score_config->weight_cfg.beamforming_cap_weightage = |
| mlme_scoring_cfg->weight_cfg.beamforming_cap_weightage; |
| score_config->weight_cfg.pcl_weightage = |
| mlme_scoring_cfg->weight_cfg.pcl_weightage; |
| score_config->weight_cfg.channel_congestion_weightage = |
| mlme_scoring_cfg->weight_cfg.channel_congestion_weightage; |
| score_config->weight_cfg.oce_wan_weightage = |
| mlme_scoring_cfg->weight_cfg.oce_wan_weightage; |
| |
| score_config->bandwidth_weight_per_index = |
| mlme_scoring_cfg->bandwidth_weight_per_index; |
| score_config->nss_weight_per_index = |
| mlme_scoring_cfg->nss_weight_per_index; |
| score_config->band_weight_per_index = |
| mlme_scoring_cfg->band_weight_per_index; |
| |
| score_config->rssi_score.best_rssi_threshold = |
| mlme_scoring_cfg->rssi_score.best_rssi_threshold; |
| score_config->rssi_score.good_rssi_threshold = |
| mlme_scoring_cfg->rssi_score.good_rssi_threshold; |
| score_config->rssi_score.bad_rssi_threshold = |
| mlme_scoring_cfg->rssi_score.bad_rssi_threshold; |
| score_config->rssi_score.good_rssi_pcnt = |
| mlme_scoring_cfg->rssi_score.good_rssi_pcnt; |
| score_config->rssi_score.bad_rssi_pcnt = |
| mlme_scoring_cfg->rssi_score.bad_rssi_pcnt; |
| score_config->rssi_score.good_rssi_bucket_size = |
| mlme_scoring_cfg->rssi_score.good_rssi_bucket_size; |
| score_config->rssi_score.bad_rssi_bucket_size = |
| mlme_scoring_cfg->rssi_score.bad_rssi_bucket_size; |
| score_config->rssi_score.rssi_pref_5g_rssi_thresh = |
| mlme_scoring_cfg->rssi_score.rssi_pref_5g_rssi_thresh; |
| |
| score_config->esp_qbss_scoring.num_slot = |
| mlme_scoring_cfg->esp_qbss_scoring.num_slot; |
| score_config->esp_qbss_scoring.score_pcnt3_to_0 = |
| mlme_scoring_cfg->esp_qbss_scoring.score_pcnt3_to_0; |
| score_config->esp_qbss_scoring.score_pcnt7_to_4 = |
| mlme_scoring_cfg->esp_qbss_scoring.score_pcnt7_to_4; |
| score_config->esp_qbss_scoring.score_pcnt11_to_8 = |
| mlme_scoring_cfg->esp_qbss_scoring.score_pcnt11_to_8; |
| score_config->esp_qbss_scoring.score_pcnt15_to_12 = |
| mlme_scoring_cfg->esp_qbss_scoring.score_pcnt15_to_12; |
| |
| score_config->oce_wan_scoring.num_slot = |
| mlme_scoring_cfg->oce_wan_scoring.num_slot; |
| score_config->oce_wan_scoring.score_pcnt3_to_0 = |
| mlme_scoring_cfg->oce_wan_scoring.score_pcnt3_to_0; |
| score_config->oce_wan_scoring.score_pcnt7_to_4 = |
| mlme_scoring_cfg->oce_wan_scoring.score_pcnt7_to_4; |
| score_config->oce_wan_scoring.score_pcnt11_to_8 = |
| mlme_scoring_cfg->oce_wan_scoring.score_pcnt11_to_8; |
| score_config->oce_wan_scoring.score_pcnt15_to_12 = |
| mlme_scoring_cfg->oce_wan_scoring.score_pcnt15_to_12; |
| } |