| /* |
| * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. |
| * |
| * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| * |
| * |
| * 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. |
| */ |
| |
| /* |
| * This file was originally distributed by Qualcomm Atheros, Inc. |
| * under proprietary terms before Copyright ownership was assigned |
| * to the Linux Foundation. |
| */ |
| |
| /**========================================================================= |
| |
| \file vos_api.c |
| |
| \brief Stub file for all virtual Operating System Services (vOSS) APIs |
| |
| ========================================================================*/ |
| /*=========================================================================== |
| |
| EDIT HISTORY FOR FILE |
| |
| |
| This section contains comments describing changes made to the module. |
| Notice that changes are listed in reverse chronological order. |
| |
| |
| $Header:$ $DateTime: $ $Author: $ |
| |
| |
| when who what, where, why |
| -------- --- -------------------------------------------------------- |
| 03/29/09 kanand Created module. |
| ===========================================================================*/ |
| |
| /*-------------------------------------------------------------------------- |
| Include Files |
| ------------------------------------------------------------------------*/ |
| #include <vos_mq.h> |
| #include "vos_sched.h" |
| #include <vos_api.h> |
| #include "sirTypes.h" |
| #include "sirApi.h" |
| #include "sirMacProtDef.h" |
| #include "sme_Api.h" |
| #include "macInitApi.h" |
| #include "wlan_qct_sys.h" |
| #include "wlan_qct_tl.h" |
| #include "wlan_hdd_misc.h" |
| #include "i_vos_packet.h" |
| #include "vos_nvitem.h" |
| #include "wlan_qct_wda.h" |
| #include "wlan_hdd_main.h" |
| #include "wlan_hdd_tsf.h" |
| #include <linux/vmalloc.h> |
| #include "wlan_hdd_cfg80211.h" |
| #include "vos_cnss.h" |
| |
| #include "sapApi.h" |
| #include "vos_trace.h" |
| #include "adf_trace.h" |
| |
| |
| |
| #include "bmi.h" |
| #include "ol_fw.h" |
| #include "ol_if_athvar.h" |
| #if defined(HIF_PCI) |
| #include "if_pci.h" |
| #elif defined(HIF_USB) |
| #include "if_usb.h" |
| #elif defined(HIF_SDIO) |
| #include "if_ath_sdio.h" |
| #endif |
| #include "vos_utils.h" |
| #include "wlan_logging_sock_svc.h" |
| #include "wma.h" |
| |
| #include "vos_utils.h" |
| |
| /*--------------------------------------------------------------------------- |
| * Preprocessor Definitions and Constants |
| * ------------------------------------------------------------------------*/ |
| /* Approximate amount of time to wait for WDA to stop WDI */ |
| #define VOS_WDA_STOP_TIMEOUT WDA_STOP_TIMEOUT |
| |
| /* Approximate amount of time to wait for WDA to issue a DUMP req */ |
| #define VOS_WDA_RESP_TIMEOUT WDA_STOP_TIMEOUT |
| |
| /* Maximum number of vos message queue get wrapper failures to cause panic */ |
| #define VOS_WRAPPER_MAX_FAIL_COUNT (VOS_CORE_MAX_MESSAGES * 3) |
| |
| /*--------------------------------------------------------------------------- |
| * Data definitions |
| * ------------------------------------------------------------------------*/ |
| static VosContextType gVosContext; |
| static pVosContextType gpVosContext; |
| |
| /* Debug variable to detect MC thread stuck */ |
| static atomic_t vos_wrapper_empty_count; |
| |
| static uint8_t vos_multicast_logging; |
| /*--------------------------------------------------------------------------- |
| * Forward declaration |
| * ------------------------------------------------------------------------*/ |
| v_VOID_t vos_sys_probe_thread_cback ( v_VOID_t *pUserData ); |
| |
| v_VOID_t vos_core_return_msg(v_PVOID_t pVContext, pVosMsgWrapper pMsgWrapper); |
| |
| v_VOID_t vos_fetch_tl_cfg_parms ( WLANTL_ConfigInfoType *pTLConfig, |
| hdd_config_t * pConfig ); |
| |
| |
| /*--------------------------------------------------------------------------- |
| |
| \brief vos_preOpen() - PreOpen the vOSS Module |
| |
| The \a vos_preOpen() function allocates the Vos Context, but do not |
| initialize all the members. This overal initialization will happen |
| at vos_Open(). |
| The reason why we need vos_preOpen() is to get a minimum context |
| where to store BAL and SAL relative data, which happens before |
| vos_Open() is called. |
| |
| \param pVosContext: A pointer to where to store the VOS Context |
| |
| |
| \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and |
| is ready to be used. |
| |
| VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/ |
| |
| \sa vos_Open() |
| |
| ---------------------------------------------------------------------------*/ |
| VOS_STATUS vos_preOpen ( v_CONTEXT_t *pVosContext ) |
| { |
| if ( pVosContext == NULL) |
| return VOS_STATUS_E_FAILURE; |
| |
| /* Allocate the VOS Context */ |
| *pVosContext = NULL; |
| gpVosContext = &gVosContext; |
| |
| if (NULL == gpVosContext) |
| { |
| /* Critical Error ...Cannot proceed further */ |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to allocate VOS Context", __func__); |
| VOS_ASSERT(0); |
| return VOS_STATUS_E_RESOURCES; |
| } |
| |
| vos_mem_zero(gpVosContext, sizeof(VosContextType)); |
| |
| *pVosContext = gpVosContext; |
| |
| /* Initialize the spinlock */ |
| vos_trace_spin_lock_init(); |
| /* it is the right time to initialize MTRACE structures */ |
| #if defined(TRACE_RECORD) |
| vosTraceInit(); |
| #endif |
| vos_register_debugcb_init(); |
| |
| adf_dp_trace_init(); |
| return VOS_STATUS_SUCCESS; |
| |
| } /* vos_preOpen()*/ |
| |
| |
| /*--------------------------------------------------------------------------- |
| |
| \brief vos_preClose() - PreClose the vOSS Module |
| |
| The \a vos_preClose() function frees the Vos Context. |
| |
| \param pVosContext: A pointer to where the VOS Context was stored |
| |
| |
| \return VOS_STATUS_SUCCESS - Always successful |
| |
| |
| \sa vos_preClose() |
| \sa vos_close() |
| ---------------------------------------------------------------------------*/ |
| VOS_STATUS vos_preClose( v_CONTEXT_t *pVosContext ) |
| { |
| |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, |
| "%s: De-allocating the VOS Context", __func__); |
| |
| if (( pVosContext == NULL) || (*pVosContext == NULL)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: vOS Context is Null", __func__); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| if (gpVosContext != *pVosContext) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Context mismatch", __func__); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| *pVosContext = gpVosContext = NULL; |
| |
| return VOS_STATUS_SUCCESS; |
| |
| } /* vos_preClose()*/ |
| |
| #ifdef FEATURE_RUNTIME_PM |
| static inline void vos_runtime_pm_config(struct ol_softc *scn, |
| hdd_context_t *pHddCtx) |
| { |
| scn->enable_runtime_pm = pHddCtx->cfg_ini->runtime_pm; |
| scn->runtime_pm_delay = pHddCtx->cfg_ini->runtime_pm_delay; |
| } |
| #else |
| static inline void vos_runtime_pm_config(struct ol_softc *scn, |
| hdd_context_t *pHddCtx) { } |
| #endif |
| |
| #if defined (FEATURE_SECURE_FIRMWARE) && defined (FEATURE_FW_HASH_CHECK) |
| static inline void vos_fw_hash_check_config(struct ol_softc *scn, |
| hdd_context_t *pHddCtx) |
| { |
| scn->enable_fw_hash_check = pHddCtx->cfg_ini->enable_fw_hash_check; |
| } |
| #elif defined (FEATURE_SECURE_FIRMWARE) |
| static inline void vos_fw_hash_check_config(struct ol_softc *scn, |
| hdd_context_t *pHddCtx) |
| { |
| scn->enable_fw_hash_check = true; |
| } |
| #else |
| static inline void vos_fw_hash_check_config(struct ol_softc *scn, |
| hdd_context_t *pHddCtx) { } |
| #endif |
| |
| #ifdef WLAN_FEATURE_TSF_PLUS |
| /** |
| * vos_set_ptp_enable() - set ptp enable flag in mac open param |
| * @wma_handle: Pointer to mac open param |
| * @hdd_ctx: Pointer to hdd context |
| * |
| * Return: none |
| */ |
| static void vos_set_ptp_enable(tMacOpenParameters *param, |
| hdd_context_t *hdd_ctx) |
| { |
| param->is_ptp_enabled = |
| (hdd_ctx->cfg_ini->tsf_ptp_options != 0); |
| } |
| #else |
| static void vos_set_ptp_enable(tMacOpenParameters *param, |
| hdd_context_t *pHddCtx) |
| { |
| } |
| #endif |
| |
| #ifdef WLAN_FEATURE_NAN |
| /** |
| * vos_set_nan_enable() - set nan enable flag in mac open param |
| * @wma_handle: Pointer to mac open param |
| * @hdd_ctx: Pointer to hdd context |
| * |
| * Return: none |
| */ |
| static void vos_set_nan_enable(tMacOpenParameters *param, |
| hdd_context_t *hdd_ctx) |
| { |
| param->is_nan_enabled = hdd_ctx->cfg_ini->enable_nan_support; |
| } |
| #else |
| static void vos_set_nan_enable(tMacOpenParameters *param, |
| hdd_context_t *pHddCtx) |
| { |
| } |
| #endif |
| |
| #ifdef QCA_SUPPORT_TXRX_DRIVER_TCP_DEL_ACK |
| static void vos_set_del_ack_params(tMacOpenParameters *param, |
| hdd_context_t *hdd_ctx) |
| { |
| param->del_ack_enable = |
| hdd_ctx->cfg_ini->del_ack_enable; |
| param->del_ack_timer_value = hdd_ctx->cfg_ini->del_ack_timer_value; |
| param->del_ack_pkt_count = hdd_ctx->cfg_ini->del_ack_pkt_count; |
| } |
| #else |
| static void vos_set_del_ack_params(tMacOpenParameters *param, |
| hdd_context_t *hdd_ctx) |
| { |
| } |
| #endif |
| |
| #ifdef QCA_SUPPORT_TXRX_HL_BUNDLE |
| /** |
| * vos_set_bundle_params() - set bundle params in mac open param |
| * @wma_handle: Pointer to mac open param |
| * @hdd_ctx: Pointer to hdd context |
| * |
| * Return: none |
| */ |
| static void vos_set_bundle_params(tMacOpenParameters *param, |
| hdd_context_t *hdd_ctx) |
| { |
| param->pkt_bundle_timer_value = |
| hdd_ctx->cfg_ini->pkt_bundle_timer_value; |
| param->pkt_bundle_size = hdd_ctx->cfg_ini->pkt_bundle_size; |
| } |
| #else |
| static void vos_set_bundle_params(tMacOpenParameters *param, |
| hdd_context_t *hdd_ctx) |
| { |
| } |
| #endif |
| |
| /** |
| * vos_set_ac_specs_params() - set ac_specs params in mac open param |
| * @param: Pointer to mac open param |
| * @hdd_ctx: Pointer to hdd context |
| * |
| * Return: none |
| */ |
| static void vos_set_ac_specs_params(tMacOpenParameters *param, |
| hdd_context_t *hdd_ctx) |
| { |
| uint8_t num_entries = 0; |
| uint8_t tx_sched_wrr_param[TX_SCHED_WRR_PARAMS_NUM]; |
| uint8_t *tx_sched_wrr_ac; |
| int i; |
| |
| if (NULL == hdd_ctx) |
| return; |
| |
| if (NULL == param) |
| return; |
| |
| if (NULL == hdd_ctx->cfg_ini) { |
| /* Do nothing if hdd_ctx is invalid */ |
| VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, |
| "%s: Warning: hdd_ctx->cfg_ini is NULL", __func__); |
| return; |
| } |
| |
| for (i = 0; i < OL_TX_NUM_WMM_AC; i++) { |
| switch (i) { |
| case OL_TX_WMM_AC_BE: |
| tx_sched_wrr_ac = hdd_ctx->cfg_ini->tx_sched_wrr_be; |
| break; |
| case OL_TX_WMM_AC_BK: |
| tx_sched_wrr_ac = hdd_ctx->cfg_ini->tx_sched_wrr_bk; |
| break; |
| case OL_TX_WMM_AC_VI: |
| tx_sched_wrr_ac = hdd_ctx->cfg_ini->tx_sched_wrr_vi; |
| break; |
| case OL_TX_WMM_AC_VO: |
| tx_sched_wrr_ac = hdd_ctx->cfg_ini->tx_sched_wrr_vo; |
| break; |
| default: |
| tx_sched_wrr_ac = NULL; |
| } |
| |
| hdd_string_to_u8_array(tx_sched_wrr_ac, |
| tx_sched_wrr_param, |
| &num_entries, |
| sizeof(tx_sched_wrr_param)); |
| |
| if (num_entries == TX_SCHED_WRR_PARAMS_NUM) { |
| param->ac_specs[i].wrr_skip_weight = |
| tx_sched_wrr_param[0]; |
| param->ac_specs[i].credit_threshold = |
| tx_sched_wrr_param[1]; |
| param->ac_specs[i].send_limit = |
| tx_sched_wrr_param[2]; |
| param->ac_specs[i].credit_reserve = |
| tx_sched_wrr_param[3]; |
| param->ac_specs[i].discard_weight = |
| tx_sched_wrr_param[4]; |
| } |
| |
| num_entries = 0; |
| } |
| } |
| |
| |
| /*--------------------------------------------------------------------------- |
| |
| \brief vos_open() - Open the vOSS Module |
| |
| The \a vos_open() function opens the vOSS Scheduler |
| Upon successful initialization: |
| |
| - All VOS submodules should have been initialized |
| |
| - The VOS scheduler should have opened |
| |
| - All the WLAN SW components should have been opened. This includes |
| SYS, MAC, SME, WDA and TL. |
| |
| |
| \param hddContextSize: Size of the HDD context to allocate. |
| |
| |
| \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and |
| is ready to be used. |
| |
| VOS_STATUS_E_RESOURCES - System resources (other than memory) |
| are unavailable to initilize the scheduler |
| |
| |
| VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/ |
| |
| \sa vos_preOpen() |
| |
| ---------------------------------------------------------------------------*/ |
| VOS_STATUS vos_open( v_CONTEXT_t *pVosContext, v_SIZE_t hddContextSize ) |
| |
| { |
| VOS_STATUS vStatus = VOS_STATUS_SUCCESS; |
| int iter = 0; |
| tSirRetStatus sirStatus = eSIR_SUCCESS; |
| tMacOpenParameters macOpenParms; |
| WLANTL_ConfigInfoType TLConfig; |
| adf_os_device_t adf_ctx; |
| HTC_INIT_INFO htcInfo; |
| struct ol_softc *scn; |
| v_VOID_t *HTCHandle; |
| hdd_context_t *pHddCtx; |
| |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, |
| "%s: Opening VOSS", __func__); |
| |
| if (NULL == gpVosContext) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Trying to open VOSS without a PreOpen", __func__); |
| VOS_ASSERT(0); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| /* Initialize the timer module */ |
| vos_timer_module_init(); |
| |
| /* Initialize bug reporting structure */ |
| vos_init_log_completion(); |
| |
| /* Initialize the probe event */ |
| if (vos_event_init(&gpVosContext->ProbeEvent) != VOS_STATUS_SUCCESS) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Unable to init probeEvent", __func__); |
| VOS_ASSERT(0); |
| return VOS_STATUS_E_FAILURE; |
| } |
| if (vos_event_init( &(gpVosContext->wdaCompleteEvent) ) != VOS_STATUS_SUCCESS ) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Unable to init wdaCompleteEvent", __func__); |
| VOS_ASSERT(0); |
| |
| goto err_probe_event; |
| } |
| |
| /* Initialize the free message queue */ |
| vStatus = vos_mq_init(&gpVosContext->freeVosMq); |
| if (! VOS_IS_STATUS_SUCCESS(vStatus)) |
| { |
| |
| /* Critical Error ... Cannot proceed further */ |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to initialize VOS free message queue", __func__); |
| VOS_ASSERT(0); |
| goto err_wda_complete_event; |
| } |
| |
| for (iter = 0; iter < VOS_CORE_MAX_MESSAGES; iter++) |
| { |
| (gpVosContext->aMsgWrappers[iter]).pVosMsg = |
| &(gpVosContext->aMsgBuffers[iter]); |
| INIT_LIST_HEAD(&gpVosContext->aMsgWrappers[iter].msgNode); |
| vos_mq_put(&gpVosContext->freeVosMq, &(gpVosContext->aMsgWrappers[iter])); |
| } |
| |
| /* Now Open the VOS Scheduler */ |
| vStatus= vos_sched_open(gpVosContext, &gpVosContext->vosSched, |
| sizeof(VosSchedContext)); |
| |
| if (!VOS_IS_STATUS_SUCCESS(vStatus)) |
| { |
| /* Critical Error ... Cannot proceed further */ |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to open VOS Scheduler", __func__); |
| VOS_ASSERT(0); |
| goto err_msg_queue; |
| } |
| |
| pHddCtx = (hdd_context_t*)(gpVosContext->pHDDContext); |
| if((NULL == pHddCtx) || |
| (NULL == pHddCtx->cfg_ini)) |
| { |
| /* Critical Error ... Cannot proceed further */ |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Hdd Context is Null", __func__); |
| VOS_ASSERT(0); |
| goto err_sched_close; |
| } |
| |
| scn = vos_get_context(VOS_MODULE_ID_HIF, gpVosContext); |
| if (!scn) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: scn is null!", __func__); |
| goto err_sched_close; |
| } |
| scn->enableuartprint = pHddCtx->cfg_ini->enablefwprint; |
| scn->enablefwlog = pHddCtx->cfg_ini->enablefwlog; |
| scn->enableFwSelfRecovery = pHddCtx->cfg_ini->enableFwSelfRecovery; |
| scn->max_no_of_peers = pHddCtx->max_peers; |
| #ifdef WLAN_FEATURE_LPSS |
| scn->enablelpasssupport = pHddCtx->cfg_ini->enablelpasssupport; |
| #endif |
| scn->enableRamdumpCollection = pHddCtx->cfg_ini->is_ramdump_enabled; |
| scn->enable_self_recovery = pHddCtx->cfg_ini->enableSelfRecovery; |
| |
| vos_fw_hash_check_config(scn, pHddCtx); |
| vos_runtime_pm_config(scn, pHddCtx); |
| |
| /* Initialize BMI and Download firmware */ |
| if (bmi_download_firmware(scn)) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: BMI failed to download target", __func__); |
| goto err_bmi_close; |
| } |
| htcInfo.pContext = gpVosContext->pHIFContext; |
| htcInfo.TargetFailure = ol_target_failure; |
| htcInfo.TargetSendSuspendComplete = wma_target_suspend_acknowledge; |
| adf_ctx = vos_get_context(VOS_MODULE_ID_ADF, gpVosContext); |
| |
| /* Create HTC */ |
| gpVosContext->htc_ctx = HTCCreate(htcInfo.pContext, &htcInfo, adf_ctx); |
| if (!gpVosContext->htc_ctx) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to Create HTC", __func__); |
| goto err_bmi_close; |
| } |
| |
| if (bmi_done(scn)) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to complete BMI phase", __func__); |
| goto err_htc_close; |
| } |
| |
| /* |
| ** Need to open WDA first because it calls WDI_Init, which calls wpalOpen |
| ** The reason that is needed becasue vos_packet_open need to use PAL APIs |
| */ |
| |
| /*Open the WDA module */ |
| vos_mem_set(&macOpenParms, sizeof(macOpenParms), 0); |
| /* UMA is supported in hardware for performing the |
| ** frame translation 802.11 <-> 802.3 |
| */ |
| macOpenParms.frameTransRequired = 1; |
| macOpenParms.driverType = eDRIVER_TYPE_PRODUCTION; |
| macOpenParms.powersaveOffloadEnabled = |
| pHddCtx->cfg_ini->enablePowersaveOffload; |
| macOpenParms.staDynamicDtim = pHddCtx->cfg_ini->enableDynamicDTIM; |
| macOpenParms.staModDtim = pHddCtx->cfg_ini->enableModulatedDTIM; |
| macOpenParms.staMaxLIModDtim = pHddCtx->cfg_ini->fMaxLIModulatedDTIM; |
| macOpenParms.wowEnable = pHddCtx->cfg_ini->wowEnable; |
| macOpenParms.maxWoWFilters = pHddCtx->cfg_ini->maxWoWFilters; |
| /* Here olIniInfo is used to store ini status of arp offload |
| * ns offload and others. Currently 1st bit is used for arp |
| * off load and 2nd bit for ns offload currently, rest bits are unused |
| */ |
| if ( pHddCtx->cfg_ini->fhostArpOffload) |
| macOpenParms.olIniInfo = macOpenParms.olIniInfo | 0x1; |
| if ( pHddCtx->cfg_ini->fhostNSOffload) |
| macOpenParms.olIniInfo = macOpenParms.olIniInfo | 0x2; |
| /* |
| * Copy the DFS Phyerr Filtering Offload status. |
| * This parameter reflects the value of the |
| * dfsPhyerrFilterOffload flag as set in the ini. |
| */ |
| macOpenParms.dfsPhyerrFilterOffload = |
| pHddCtx->cfg_ini->fDfsPhyerrFilterOffload; |
| |
| macOpenParms.ssdp = pHddCtx->cfg_ini->ssdp; |
| macOpenParms.enable_bcst_ptrn = pHddCtx->cfg_ini->bcastptrn; |
| macOpenParms.enable_mc_list = pHddCtx->cfg_ini->fEnableMCAddrList; |
| |
| macOpenParms.bpf_packet_filter_enable = |
| pHddCtx->cfg_ini->bpf_packet_filter_enable; |
| #ifdef FEATURE_WLAN_RA_FILTERING |
| macOpenParms.RArateLimitInterval = pHddCtx->cfg_ini->RArateLimitInterval; |
| macOpenParms.IsRArateLimitEnabled = pHddCtx->cfg_ini->IsRArateLimitEnabled; |
| #endif |
| |
| macOpenParms.force_target_assert_enabled = |
| pHddCtx->cfg_ini->crash_inject_enabled; |
| macOpenParms.apMaxOffloadPeers = pHddCtx->cfg_ini->apMaxOffloadPeers; |
| |
| macOpenParms.apMaxOffloadReorderBuffs = |
| pHddCtx->cfg_ini->apMaxOffloadReorderBuffs; |
| |
| macOpenParms.apDisableIntraBssFwd = pHddCtx->cfg_ini->apDisableIntraBssFwd; |
| |
| macOpenParms.dfsRadarPriMultiplier = pHddCtx->cfg_ini->dfsRadarPriMultiplier; |
| macOpenParms.reorderOffload = pHddCtx->cfg_ini->reorderOffloadSupport; |
| |
| #ifdef IPA_UC_OFFLOAD |
| /* IPA micro controller data path offload resource config item */ |
| macOpenParms.ucOffloadEnabled = pHddCtx->cfg_ini->IpaUcOffloadEnabled; |
| |
| if (!is_power_of_2(pHddCtx->cfg_ini->IpaUcTxBufCount)) { |
| /* IpaUcTxBufCount should be power of 2 */ |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Round down IpaUcTxBufCount %d to nearest power of two", |
| __func__, pHddCtx->cfg_ini->IpaUcTxBufCount); |
| pHddCtx->cfg_ini->IpaUcTxBufCount = |
| vos_rounddown_pow_of_two(pHddCtx->cfg_ini->IpaUcTxBufCount); |
| if (!pHddCtx->cfg_ini->IpaUcTxBufCount) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to round down IpaUcTxBufCount", __func__); |
| goto err_htc_close; |
| } |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: IpaUcTxBufCount rounded down to %d", __func__, |
| pHddCtx->cfg_ini->IpaUcTxBufCount); |
| } |
| macOpenParms.ucTxBufCount = pHddCtx->cfg_ini->IpaUcTxBufCount; |
| macOpenParms.ucTxBufSize = pHddCtx->cfg_ini->IpaUcTxBufSize; |
| |
| if (!is_power_of_2(pHddCtx->cfg_ini->IpaUcRxIndRingCount)) { |
| /* IpaUcRxIndRingCount should be power of 2 */ |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Round down IpaUcRxIndRingCount %d to nearest power of two", |
| __func__, pHddCtx->cfg_ini->IpaUcRxIndRingCount); |
| pHddCtx->cfg_ini->IpaUcRxIndRingCount = |
| vos_rounddown_pow_of_two(pHddCtx->cfg_ini->IpaUcRxIndRingCount); |
| if (!pHddCtx->cfg_ini->IpaUcRxIndRingCount) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to round down IpaUcRxIndRingCount", __func__); |
| goto err_htc_close; |
| } |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: IpaUcRxIndRingCount rounded down to %d", __func__, |
| pHddCtx->cfg_ini->IpaUcRxIndRingCount); |
| } |
| macOpenParms.ucRxIndRingCount = pHddCtx->cfg_ini->IpaUcRxIndRingCount; |
| macOpenParms.ucTxPartitionBase = pHddCtx->cfg_ini->IpaUcTxPartitionBase; |
| #endif /* IPA_UC_OFFLOAD */ |
| |
| macOpenParms.tx_chain_mask_cck = pHddCtx->cfg_ini->tx_chain_mask_cck; |
| macOpenParms.self_gen_frm_pwr = pHddCtx->cfg_ini->self_gen_frm_pwr; |
| macOpenParms.max_mgmt_tx_fail_count = |
| pHddCtx->cfg_ini->max_mgmt_tx_fail_count; |
| |
| #ifdef WLAN_FEATURE_LPSS |
| macOpenParms.is_lpass_enabled = pHddCtx->cfg_ini->enablelpasssupport; |
| #endif |
| |
| vos_set_nan_enable(&macOpenParms, pHddCtx); |
| vos_set_bundle_params(&macOpenParms, pHddCtx); |
| vos_set_del_ack_params(&macOpenParms, pHddCtx); |
| vos_set_ac_specs_params(&macOpenParms, pHddCtx); |
| vos_set_ptp_enable(&macOpenParms, pHddCtx); |
| |
| vStatus = WDA_open( gpVosContext, gpVosContext->pHDDContext, |
| hdd_update_tgt_cfg, |
| hdd_dfs_indicate_radar, |
| hdd_update_dfs_cac_block_tx_flag, |
| &macOpenParms ); |
| |
| if (!VOS_IS_STATUS_SUCCESS(vStatus)) |
| { |
| /* Critical Error ... Cannot proceed further */ |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to open WDA module", __func__); |
| VOS_ASSERT(0); |
| goto err_htc_close; |
| } |
| |
| /* Number of peers limit differs in each chip version. If peer max |
| * limit configured in ini exceeds more than supported, WMA adjusts |
| * and keeps correct limit in macOpenParms.maxStation. So, make sure |
| * pHddCtx->max_peers has adjusted value |
| */ |
| pHddCtx->max_peers = macOpenParms.maxStation; |
| HTCHandle = vos_get_context(VOS_MODULE_ID_HTC, gpVosContext); |
| if (!HTCHandle) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: HTCHandle is null!", __func__); |
| goto err_wda_close; |
| } |
| if (HTCWaitTarget(HTCHandle)) { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to complete BMI phase", __func__); |
| goto err_wda_close; |
| } |
| |
| bmi_target_ready(scn, gpVosContext->cfg_ctx); |
| /* Open the SYS module */ |
| vStatus = sysOpen(gpVosContext); |
| |
| if (!VOS_IS_STATUS_SUCCESS(vStatus)) |
| { |
| /* Critical Error ... Cannot proceed further */ |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to open SYS module", __func__); |
| VOS_ASSERT(0); |
| goto err_packet_close; |
| } |
| |
| |
| /* If we arrive here, both threads dispacthing messages correctly */ |
| |
| /* Now proceed to open the MAC */ |
| |
| /* UMA is supported in hardware for performing the |
| frame translation 802.11 <-> 802.3 */ |
| macOpenParms.frameTransRequired = 1; |
| |
| sirStatus = macOpen(&(gpVosContext->pMACContext), gpVosContext->pHDDContext, |
| &macOpenParms); |
| |
| if (eSIR_SUCCESS != sirStatus) |
| { |
| /* Critical Error ... Cannot proceed further */ |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to open MAC", __func__); |
| VOS_ASSERT(0); |
| goto err_nv_close; |
| } |
| |
| /* Now proceed to open the SME */ |
| vStatus = sme_Open(gpVosContext->pMACContext); |
| if (!VOS_IS_STATUS_SUCCESS(vStatus)) |
| { |
| /* Critical Error ... Cannot proceed further */ |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to open SME", __func__); |
| VOS_ASSERT(0); |
| goto err_mac_close; |
| } |
| |
| /* Now proceed to open TL. Read TL config first */ |
| vos_fetch_tl_cfg_parms ( &TLConfig, |
| ((hdd_context_t*)(gpVosContext->pHDDContext))->cfg_ini); |
| |
| vStatus = WLANTL_Open(gpVosContext, &TLConfig); |
| if (!VOS_IS_STATUS_SUCCESS(vStatus)) |
| { |
| /* Critical Error ... Cannot proceed further */ |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to open TL", __func__); |
| VOS_ASSERT(0); |
| goto err_sme_close; |
| } |
| |
| #ifdef IPA_UC_OFFLOAD |
| WLANTL_GetIpaUcResource(gpVosContext, |
| &((hdd_context_t*)(gpVosContext->pHDDContext))->ce_sr_base_paddr, |
| &((hdd_context_t*)(gpVosContext->pHDDContext))->ce_sr_ring_size, |
| &((hdd_context_t*)(gpVosContext->pHDDContext))->ce_reg_paddr, |
| &((hdd_context_t*)(gpVosContext->pHDDContext))->tx_comp_ring_base_paddr, |
| &((hdd_context_t*)(gpVosContext->pHDDContext))->tx_comp_ring_size, |
| &((hdd_context_t*)(gpVosContext->pHDDContext))->tx_num_alloc_buffer, |
| &((hdd_context_t*)(gpVosContext->pHDDContext))->rx_rdy_ring_base_paddr, |
| &((hdd_context_t*)(gpVosContext->pHDDContext))->rx_rdy_ring_size, |
| &((hdd_context_t*)(gpVosContext->pHDDContext))->rx_proc_done_idx_paddr); |
| #endif /* IPA_UC_OFFLOAD */ |
| |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, |
| "%s: VOSS successfully Opened", __func__); |
| |
| *pVosContext = gpVosContext; |
| |
| return VOS_STATUS_SUCCESS; |
| |
| |
| err_sme_close: |
| sme_Close(gpVosContext->pMACContext); |
| |
| err_mac_close: |
| macClose(gpVosContext->pMACContext); |
| |
| err_nv_close: |
| |
| sysClose(gpVosContext); |
| |
| err_packet_close: |
| err_wda_close: |
| WDA_close(gpVosContext); |
| |
| wma_wmi_service_close(gpVosContext); |
| |
| err_htc_close: |
| if (gpVosContext->htc_ctx) { |
| HTCDestroy(gpVosContext->htc_ctx); |
| gpVosContext->htc_ctx = NULL; |
| } |
| |
| err_bmi_close: |
| BMICleanup(scn); |
| |
| err_sched_close: |
| vos_sched_close(gpVosContext); |
| |
| |
| err_msg_queue: |
| vos_mq_deinit(&gpVosContext->freeVosMq); |
| |
| err_wda_complete_event: |
| vos_event_destroy( &gpVosContext->wdaCompleteEvent ); |
| |
| err_probe_event: |
| vos_event_destroy(&gpVosContext->ProbeEvent); |
| |
| return VOS_STATUS_E_FAILURE; |
| |
| } /* vos_open() */ |
| |
| /*--------------------------------------------------------------------------- |
| |
| \brief vos_preStart() - |
| |
| The \a vos_preStart() function to download CFG. |
| including: |
| - ccmStart |
| |
| - WDA: triggers the CFG download |
| |
| |
| \param pVosContext: The VOS context |
| |
| |
| \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and |
| is ready to be used. |
| |
| VOS_STATUS_E_RESOURCES - System resources (other than memory) |
| are unavailable to initilize the scheduler |
| |
| |
| VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/ |
| |
| \sa vos_start |
| |
| ---------------------------------------------------------------------------*/ |
| VOS_STATUS vos_preStart( v_CONTEXT_t vosContext ) |
| { |
| VOS_STATUS vStatus = VOS_STATUS_SUCCESS; |
| pVosContextType pVosContext = (pVosContextType)vosContext; |
| v_VOID_t *scn; |
| VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO, |
| "vos prestart"); |
| |
| if (gpVosContext != pVosContext) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Context mismatch", __func__); |
| VOS_ASSERT(0); |
| return VOS_STATUS_E_INVAL; |
| } |
| |
| if (pVosContext->pMACContext == NULL) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: MAC NULL context", __func__); |
| VOS_ASSERT(0); |
| return VOS_STATUS_E_INVAL; |
| } |
| |
| if (pVosContext->pWDAContext == NULL) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: WDA NULL context", __func__); |
| VOS_ASSERT(0); |
| return VOS_STATUS_E_INVAL; |
| } |
| |
| scn = vos_get_context(VOS_MODULE_ID_HIF, gpVosContext); |
| if (!scn) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: scn is null!", __func__); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| /* call macPreStart */ |
| vStatus = macPreStart(gpVosContext->pMACContext); |
| if ( !VOS_IS_STATUS_SUCCESS(vStatus) ) |
| { |
| VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_FATAL, |
| "Failed at macPreStart "); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| /* call ccmStart */ |
| ccmStart(gpVosContext->pMACContext); |
| |
| /* Reset wda wait event */ |
| vos_event_reset(&gpVosContext->wdaCompleteEvent); |
| |
| |
| /*call WDA pre start*/ |
| vStatus = WDA_preStart(gpVosContext); |
| if (!VOS_IS_STATUS_SUCCESS(vStatus)) |
| { |
| VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_FATAL, |
| "Failed to WDA prestart"); |
| ccmStop(gpVosContext->pMACContext); |
| VOS_ASSERT(0); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| /* Need to update time out of complete */ |
| vStatus = vos_wait_single_event( &gpVosContext->wdaCompleteEvent, |
| VOS_WDA_TIMEOUT ); |
| if ( vStatus != VOS_STATUS_SUCCESS ) |
| { |
| if ( vStatus == VOS_STATUS_E_TIMEOUT ) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Timeout occurred before WDA complete", __func__); |
| } |
| else |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: WDA_preStart reporting other error", __func__); |
| } |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Test MC thread by posting a probe message to SYS", __func__); |
| wlan_sys_probe(); |
| |
| ccmStop(gpVosContext->pMACContext); |
| VOS_ASSERT( 0 ); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| vStatus = HTCStart(gpVosContext->htc_ctx); |
| if (!VOS_IS_STATUS_SUCCESS(vStatus)) |
| { |
| VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_FATAL, |
| "Failed to Start HTC"); |
| ccmStop(gpVosContext->pMACContext); |
| VOS_ASSERT( 0 ); |
| return VOS_STATUS_E_FAILURE; |
| } |
| vStatus = wma_wait_for_ready_event(gpVosContext->pWDAContext); |
| if (!VOS_IS_STATUS_SUCCESS(vStatus)) |
| { |
| VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_FATAL, |
| "Failed to get ready event from target firmware"); |
| HTCSetTargetToSleep(scn); |
| ccmStop(gpVosContext->pMACContext); |
| HTCStop(gpVosContext->htc_ctx); |
| VOS_ASSERT( 0 ); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| HTCSetTargetToSleep(scn); |
| |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| /*--------------------------------------------------------------------------- |
| |
| \brief vos_start() - Start the Libra SW Modules |
| |
| The \a vos_start() function starts all the components of the Libra SW |
| including: |
| - SAL/BAL, which in turn starts SSC |
| |
| - the MAC (HAL and PE) |
| |
| - SME |
| |
| - TL |
| |
| - SYS: triggers the CFG download |
| |
| |
| \param pVosContext: The VOS context |
| |
| |
| \return VOS_STATUS_SUCCESS - Scheduler was successfully initialized and |
| is ready to be used. |
| |
| VOS_STATUS_E_RESOURCES - System resources (other than memory) |
| are unavailable to initilize the scheduler |
| |
| |
| VOS_STATUS_E_FAILURE - Failure to initialize the scheduler/ |
| |
| \sa vos_preStart() |
| \sa vos_open() |
| |
| ---------------------------------------------------------------------------*/ |
| VOS_STATUS vos_start( v_CONTEXT_t vosContext ) |
| { |
| VOS_STATUS vStatus = VOS_STATUS_SUCCESS; |
| tSirRetStatus sirStatus = eSIR_SUCCESS; |
| pVosContextType pVosContext = (pVosContextType)vosContext; |
| tHalMacStartParameters halStartParams; |
| |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, |
| "%s: Starting Libra SW", __func__); |
| |
| /* We support only one instance for now ...*/ |
| if (gpVosContext != pVosContext) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: mismatch in context", __func__); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| if (( pVosContext->pWDAContext == NULL) || ( pVosContext->pMACContext == NULL) |
| || ( pVosContext->pTLContext == NULL)) |
| { |
| if (pVosContext->pWDAContext == NULL) |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: WDA NULL context", __func__); |
| else if (pVosContext->pMACContext == NULL) |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: MAC NULL context", __func__); |
| else |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: TL NULL context", __func__); |
| |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| |
| /* Start the WDA */ |
| vStatus = WDA_start(pVosContext); |
| if ( vStatus != VOS_STATUS_SUCCESS ) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to start WDA", __func__); |
| return VOS_STATUS_E_FAILURE; |
| } |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, |
| "%s: WDA correctly started", __func__); |
| |
| /* Start the MAC */ |
| vos_mem_zero((v_PVOID_t)&halStartParams, sizeof(tHalMacStartParameters)); |
| |
| /* Start the MAC */ |
| sirStatus = macStart(pVosContext->pMACContext,(v_PVOID_t)&halStartParams); |
| |
| if (eSIR_SUCCESS != sirStatus) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to start MAC", __func__); |
| goto err_wda_stop; |
| } |
| |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, |
| "%s: MAC correctly started", __func__); |
| |
| /* START SME */ |
| vStatus = sme_Start(pVosContext->pMACContext); |
| |
| if (!VOS_IS_STATUS_SUCCESS(vStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to start SME", __func__); |
| goto err_mac_stop; |
| } |
| |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, |
| "%s: SME correctly started", __func__); |
| |
| /** START TL */ |
| vStatus = WLANTL_Start(pVosContext); |
| if (!VOS_IS_STATUS_SUCCESS(vStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to start TL", __func__); |
| goto err_sme_stop; |
| } |
| |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, |
| "TL correctly started"); |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, |
| "%s: VOSS Start is successful!!", __func__); |
| |
| return VOS_STATUS_SUCCESS; |
| |
| |
| err_sme_stop: |
| sme_Stop(pVosContext->pMACContext, HAL_STOP_TYPE_SYS_RESET); |
| |
| err_mac_stop: |
| macStop( pVosContext->pMACContext, HAL_STOP_TYPE_SYS_RESET ); |
| |
| err_wda_stop: |
| vos_event_reset( &(gpVosContext->wdaCompleteEvent) ); |
| vStatus = WDA_stop( pVosContext, HAL_STOP_TYPE_RF_KILL); |
| if (!VOS_IS_STATUS_SUCCESS(vStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to stop WDA", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vStatus ) ); |
| WDA_setNeedShutdown(vosContext); |
| } |
| else |
| { |
| vStatus = vos_wait_single_event( &(gpVosContext->wdaCompleteEvent), |
| VOS_WDA_TIMEOUT ); |
| if( vStatus != VOS_STATUS_SUCCESS ) |
| { |
| if( vStatus == VOS_STATUS_E_TIMEOUT ) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Timeout occurred before WDA_stop complete", __func__); |
| |
| } |
| else |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: WDA_stop reporting other error", __func__); |
| } |
| VOS_ASSERT( 0 ); |
| WDA_setNeedShutdown(vosContext); |
| } |
| } |
| |
| return VOS_STATUS_E_FAILURE; |
| |
| } /* vos_start() */ |
| |
| |
| /* vos_stop function */ |
| VOS_STATUS vos_stop( v_CONTEXT_t vosContext ) |
| { |
| VOS_STATUS vosStatus; |
| |
| /* WDA_Stop is called before the SYS so that the processing of Riva |
| pending responces will not be handled during uninitialization of WLAN driver */ |
| vos_event_reset( &(gpVosContext->wdaCompleteEvent) ); |
| |
| vosStatus = WDA_stop( vosContext, HAL_STOP_TYPE_RF_KILL ); |
| |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to stop WDA", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| WDA_setNeedShutdown(vosContext); |
| } |
| |
| hif_disable_isr(((VosContextType*)vosContext)->pHIFContext); |
| hif_reset_soc(((VosContextType*)vosContext)->pHIFContext); |
| |
| /* SYS STOP will stop SME and MAC */ |
| vosStatus = sysStop( vosContext); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to stop SYS", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| |
| vosStatus = WLANTL_Stop( vosContext ); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to stop TL", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| |
| /* vos_close function */ |
| VOS_STATUS vos_close( v_CONTEXT_t vosContext ) |
| { |
| VOS_STATUS vosStatus; |
| |
| vosStatus = wma_wmi_work_close( vosContext ); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to close wma_wmi_work", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| |
| if (gpVosContext->htc_ctx) |
| { |
| HTCStop(gpVosContext->htc_ctx); |
| HTCDestroy(gpVosContext->htc_ctx); |
| gpVosContext->htc_ctx = NULL; |
| } |
| |
| vosStatus = WLANTL_Close(vosContext); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to close TL", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| |
| vosStatus = sme_Close( ((pVosContextType)vosContext)->pMACContext); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to close SME", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| |
| vosStatus = macClose( ((pVosContextType)vosContext)->pMACContext); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to close MAC", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| |
| ((pVosContextType)vosContext)->pMACContext = NULL; |
| |
| vosStatus = sysClose( vosContext ); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to close SYS", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| |
| if ( TRUE == WDA_needShutdown(vosContext )) |
| { |
| /* if WDA stop failed, call WDA shutdown to cleanup WDA/WDI */ |
| vosStatus = WDA_shutdown( vosContext, VOS_TRUE ); |
| if (VOS_IS_STATUS_SUCCESS( vosStatus ) ) |
| { |
| hdd_set_ssr_required( HDD_SSR_REQUIRED ); |
| } |
| else |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Failed to shutdown WDA", __func__ ); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| } |
| else |
| { |
| vosStatus = WDA_close( vosContext ); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to close WDA", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| } |
| |
| vosStatus = wma_wmi_service_close( vosContext ); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to close wma_wmi_service", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| |
| |
| vos_mq_deinit(&((pVosContextType)vosContext)->freeVosMq); |
| |
| vosStatus = vos_event_destroy(&gpVosContext->wdaCompleteEvent); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: failed to destroy wdaCompleteEvent", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| |
| vosStatus = vos_event_destroy(&gpVosContext->ProbeEvent); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: failed to destroy ProbeEvent", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| |
| vos_deinit_log_completion(); |
| |
| vos_wdthread_flush_timer_work(); |
| |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| |
| /**--------------------------------------------------------------------------- |
| |
| \brief vos_get_context() - get context data area |
| |
| Each module in the system has a context / data area that is allocated |
| and maanged by voss. This API allows any user to get a pointer to its |
| allocated context data area from the VOSS global context. |
| |
| \param vosContext - the VOSS Global Context. |
| |
| \param moduleId - the module ID, who's context data are is being retrived. |
| |
| \return - pointer to the context data area. |
| |
| - NULL if the context data is not allocated for the module ID |
| specified |
| |
| --------------------------------------------------------------------------*/ |
| v_VOID_t* vos_get_context( VOS_MODULE_ID moduleId, |
| v_CONTEXT_t pVosContext ) |
| { |
| v_PVOID_t pModContext = NULL; |
| |
| if (pVosContext == NULL) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: vos context pointer is null", __func__); |
| return NULL; |
| } |
| |
| if (gpVosContext != pVosContext) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: pVosContext != gpVosContext", __func__); |
| return NULL; |
| } |
| |
| switch(moduleId) |
| { |
| case VOS_MODULE_ID_TL: |
| { |
| pModContext = gpVosContext->pTLContext; |
| break; |
| } |
| |
| case VOS_MODULE_ID_HDD: |
| { |
| pModContext = gpVosContext->pHDDContext; |
| break; |
| } |
| |
| case VOS_MODULE_ID_SME: |
| case VOS_MODULE_ID_PE: |
| case VOS_MODULE_ID_PMC: |
| { |
| /* |
| ** In all these cases, we just return the MAC Context |
| */ |
| pModContext = gpVosContext->pMACContext; |
| break; |
| } |
| |
| case VOS_MODULE_ID_WDA: |
| { |
| /* For WDA module */ |
| pModContext = gpVosContext->pWDAContext; |
| break; |
| } |
| |
| case VOS_MODULE_ID_VOSS: |
| { |
| /* For SYS this is VOS itself*/ |
| pModContext = gpVosContext; |
| break; |
| } |
| |
| |
| case VOS_MODULE_ID_HIF: |
| { |
| pModContext = gpVosContext->pHIFContext; |
| break; |
| } |
| |
| case VOS_MODULE_ID_HTC: |
| { |
| pModContext = gpVosContext->htc_ctx; |
| break; |
| } |
| |
| case VOS_MODULE_ID_ADF: |
| { |
| pModContext = gpVosContext->adf_ctx; |
| break; |
| } |
| |
| case VOS_MODULE_ID_TXRX: |
| { |
| pModContext = gpVosContext->pdev_txrx_ctx; |
| break; |
| } |
| |
| case VOS_MODULE_ID_CFG: |
| { |
| pModContext = gpVosContext->cfg_ctx; |
| break; |
| } |
| |
| default: |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,"%s: Module ID %i " |
| "does not have its context maintained by VOSS", __func__, moduleId); |
| VOS_ASSERT(0); |
| return NULL; |
| } |
| } |
| |
| if (pModContext == NULL ) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,"%s: Module ID %i " |
| "context is Null", __func__, moduleId); |
| } |
| |
| return pModContext; |
| |
| } /* vos_get_context()*/ |
| |
| |
| /**--------------------------------------------------------------------------- |
| |
| \brief vos_get_global_context() - get VOSS global Context |
| |
| This API allows any user to get the VOS Global Context pointer from a |
| module context data area. |
| |
| \param moduleContext - the input module context pointer |
| |
| \param moduleId - the module ID who's context pointer is input in |
| moduleContext. |
| |
| \return - pointer to the VOSS global context |
| |
| - NULL if the function is unable to retreive the VOSS context. |
| |
| --------------------------------------------------------------------------*/ |
| v_CONTEXT_t vos_get_global_context( VOS_MODULE_ID moduleId, |
| v_VOID_t *moduleContext ) |
| { |
| if (gpVosContext == NULL) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: global voss context is NULL", __func__); |
| } |
| |
| return gpVosContext; |
| |
| } /* vos_get_global_context() */ |
| |
| |
| v_U8_t vos_is_logp_in_progress(VOS_MODULE_ID moduleId, v_VOID_t *moduleContext) |
| { |
| if (gpVosContext == NULL) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: global voss context is NULL", __func__); |
| return 1; |
| } |
| |
| return gpVosContext->isLogpInProgress; |
| } |
| |
| void vos_set_logp_in_progress(VOS_MODULE_ID moduleId, v_U8_t value) |
| { |
| hdd_context_t *pHddCtx = NULL; |
| |
| if (gpVosContext == NULL) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: global voss context is NULL", __func__); |
| return; |
| } |
| |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_DEBUG, |
| "%s:%pS setting value %d",__func__, (void *)_RET_IP_, value); |
| gpVosContext->isLogpInProgress = value; |
| |
| /* HDD uses it's own context variable to check if SSR in progress, |
| * instead of modifying all HDD APIs set the HDD context variable |
| * here */ |
| pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, gpVosContext); |
| if (!pHddCtx) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: HDD context is Null", __func__); |
| return; |
| } |
| pHddCtx->isLogpInProgress = value; |
| } |
| |
| v_U8_t vos_is_load_unload_in_progress(VOS_MODULE_ID moduleId, v_VOID_t *moduleContext) |
| { |
| if (gpVosContext == NULL) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: global voss context is NULL", __func__); |
| return 0; |
| } |
| |
| return gpVosContext->isLoadUnloadInProgress; |
| } |
| |
| void vos_set_load_unload_in_progress(VOS_MODULE_ID moduleId, v_U8_t value) |
| { |
| if (gpVosContext == NULL) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: global voss context is NULL", __func__); |
| return; |
| } |
| gpVosContext->isLoadUnloadInProgress = value; |
| |
| vos_set_driver_status(value); |
| } |
| |
| /** |
| * vos_is_unload_in_progress - check if driver unload is in progress |
| * |
| * Return: true - unload in progress |
| * false - unload not in progress |
| */ |
| v_U8_t vos_is_unload_in_progress(void) |
| { |
| if (gpVosContext == NULL) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: global voss context is NULL", __func__); |
| return 0; |
| } |
| |
| return gpVosContext->is_unload_in_progress; |
| } |
| |
| /** |
| * vos_is_load_in_progress - check if driver load is in progress |
| * |
| * @moduleId: the module ID who's context pointer is input in moduleContext |
| * @moduleContext: the input module context pointer |
| * |
| * Return: true - load in progress |
| * false - load not in progress |
| */ |
| v_U8_t vos_is_load_in_progress(VOS_MODULE_ID moduleId, v_VOID_t *moduleContext) |
| { |
| if (gpVosContext == NULL) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: global voss context is NULL", __func__); |
| return 0; |
| } |
| |
| return gpVosContext->is_load_in_progress; |
| } |
| |
| /** |
| * vos_set_unload_in_progress - set driver unload in progress status |
| * @value: true - driver unload starts |
| * false - driver unload completes |
| * |
| * Return: none |
| */ |
| void vos_set_unload_in_progress(v_U8_t value) |
| { |
| if (gpVosContext == NULL) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: global voss context is NULL", __func__); |
| return; |
| } |
| |
| gpVosContext->is_unload_in_progress = value; |
| } |
| |
| /** |
| * vos_set_load_in_progress - set driver load in progress status |
| * |
| * @moduleId: the module ID of the caller |
| * @value: true - driver load starts |
| * false - driver load completes |
| * Return: none |
| */ |
| void vos_set_load_in_progress(VOS_MODULE_ID moduleId, v_U8_t value) |
| { |
| if (gpVosContext == NULL) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: global voss context is NULL", __func__); |
| return; |
| } |
| |
| gpVosContext->is_load_in_progress = value; |
| } |
| |
| v_U8_t vos_is_reinit_in_progress(VOS_MODULE_ID moduleId, v_VOID_t *moduleContext) |
| { |
| if (gpVosContext == NULL) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: global voss context is NULL", __func__); |
| return 1; |
| } |
| |
| return gpVosContext->isReInitInProgress; |
| } |
| |
| void vos_set_reinit_in_progress(VOS_MODULE_ID moduleId, v_U8_t value) |
| { |
| if (gpVosContext == NULL) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: global voss context is NULL", __func__); |
| return; |
| } |
| |
| gpVosContext->isReInitInProgress = value; |
| } |
| |
| |
| /** |
| * vos_set_shutdown_in_progress - set SSR shutdown progress status |
| * |
| * @moduleId: the module ID of the caller |
| * @value: true - CNSS SSR shutdown start |
| * false - CNSS SSR shutdown completes |
| * Return: none |
| */ |
| |
| void vos_set_shutdown_in_progress(VOS_MODULE_ID moduleId, bool value) |
| { |
| if (gpVosContext == NULL) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: global voss context is NULL", __func__); |
| return; |
| } |
| gpVosContext->is_shutdown_in_progress = value; |
| } |
| |
| /** |
| * vos_is_shutdown_in_progress - check if SSR shutdown is in progress |
| * |
| * @moduleId: the module ID of the caller |
| * @moduleContext: the input module context pointer |
| * |
| * Return: true - shutdown in progress |
| * false - shutdown is not in progress |
| */ |
| |
| bool vos_is_shutdown_in_progress(VOS_MODULE_ID moduleId, |
| v_VOID_t *moduleContext) |
| { |
| if (gpVosContext == NULL) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: global voss context is NULL", __func__); |
| return 0; |
| } |
| return gpVosContext->is_shutdown_in_progress; |
| } |
| |
| /**--------------------------------------------------------------------------- |
| |
| \brief vos_alloc_context() - allocate a context within the VOSS global Context |
| |
| This API allows any user to allocate a user context area within the |
| VOS Global Context. |
| |
| \param pVosContext - pointer to the global Vos context |
| |
| \param moduleId - the module ID who's context area is being allocated. |
| |
| \param ppModuleContext - pointer to location where the pointer to the |
| allocated context is returned. Note this |
| output pointer is valid only if the API |
| returns VOS_STATUS_SUCCESS |
| |
| \param size - the size of the context area to be allocated. |
| |
| \return - VOS_STATUS_SUCCESS - the context for the module ID has been |
| allocated successfully. The pointer to the context area |
| can be found in *ppModuleContext. |
| \note This function returns VOS_STATUS_SUCCESS if the |
| module context was already allocated and the size |
| allocated matches the size on this call. |
| |
| VOS_STATUS_E_INVAL - the moduleId is not a valid or does |
| not identify a module that can have a context allocated. |
| |
| VOS_STATUS_E_EXISTS - vos could allocate the requested context |
| because a context for this module ID already exists and it is |
| a *different* size that specified on this call. |
| |
| VOS_STATUS_E_NOMEM - vos could not allocate memory for the |
| requested context area. |
| |
| \sa vos_get_context(), vos_free_context() |
| |
| --------------------------------------------------------------------------*/ |
| VOS_STATUS vos_alloc_context( v_VOID_t *pVosContext, VOS_MODULE_ID moduleID, |
| v_VOID_t **ppModuleContext, v_SIZE_t size ) |
| { |
| v_VOID_t ** pGpModContext = NULL; |
| |
| if ( pVosContext == NULL) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: vos context is null", __func__); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| if (( gpVosContext != pVosContext) || ( ppModuleContext == NULL)) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: context mismatch or null param passed", __func__); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| switch(moduleID) |
| { |
| case VOS_MODULE_ID_TL: |
| { |
| pGpModContext = &(gpVosContext->pTLContext); |
| break; |
| } |
| |
| case VOS_MODULE_ID_WDA: |
| { |
| pGpModContext = &(gpVosContext->pWDAContext); |
| break; |
| } |
| case VOS_MODULE_ID_SME: |
| case VOS_MODULE_ID_PE: |
| case VOS_MODULE_ID_PMC: |
| case VOS_MODULE_ID_HDD: |
| case VOS_MODULE_ID_HDD_SOFTAP: |
| default: |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: Module ID %i " |
| "does not have its context allocated by VOSS", __func__, moduleID); |
| VOS_ASSERT(0); |
| return VOS_STATUS_E_INVAL; |
| } |
| } |
| |
| if ( NULL != *pGpModContext) |
| { |
| /* |
| ** Context has already been allocated! |
| ** Prevent double allocation |
| */ |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Module ID %i context has already been allocated", |
| __func__, moduleID); |
| return VOS_STATUS_E_EXISTS; |
| } |
| |
| /* |
| ** Dynamically allocate the context for module |
| */ |
| |
| *ppModuleContext = vos_mem_malloc(size); |
| |
| |
| if ( *ppModuleContext == NULL) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,"%s: Failed to " |
| "allocate Context for module ID %i", __func__, moduleID); |
| VOS_ASSERT(0); |
| return VOS_STATUS_E_NOMEM; |
| } |
| |
| if (moduleID==VOS_MODULE_ID_TL) |
| { |
| vos_mem_zero(*ppModuleContext, size); |
| } |
| |
| *pGpModContext = *ppModuleContext; |
| |
| return VOS_STATUS_SUCCESS; |
| |
| } /* vos_alloc_context() */ |
| |
| |
| /**--------------------------------------------------------------------------- |
| |
| \brief vos_free_context() - free an allocated a context within the |
| VOSS global Context |
| |
| This API allows a user to free the user context area within the |
| VOS Global Context. |
| |
| \param pVosContext - pointer to the global Vos context |
| |
| \param moduleId - the module ID who's context area is being free |
| |
| \param pModuleContext - pointer to module context area to be free'd. |
| |
| \return - VOS_STATUS_SUCCESS - the context for the module ID has been |
| free'd. The pointer to the context area is not longer |
| available. |
| |
| VOS_STATUS_E_FAULT - pVosContext or pModuleContext are not |
| valid pointers. |
| |
| VOS_STATUS_E_INVAL - the moduleId is not a valid or does |
| not identify a module that can have a context free'd. |
| |
| VOS_STATUS_E_EXISTS - vos could not free the requested |
| context area because a context for this module ID does not |
| exist in the global vos context. |
| |
| \sa vos_get_context() |
| |
| --------------------------------------------------------------------------*/ |
| VOS_STATUS vos_free_context( v_VOID_t *pVosContext, VOS_MODULE_ID moduleID, |
| v_VOID_t *pModuleContext ) |
| { |
| v_VOID_t ** pGpModContext = NULL; |
| |
| if (( pVosContext == NULL) || ( gpVosContext != pVosContext) || |
| ( pModuleContext == NULL)) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Null params or context mismatch", __func__); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| |
| switch(moduleID) |
| { |
| case VOS_MODULE_ID_TL: |
| { |
| pGpModContext = &(gpVosContext->pTLContext); |
| break; |
| } |
| |
| case VOS_MODULE_ID_WDA: |
| { |
| pGpModContext = &(gpVosContext->pWDAContext); |
| break; |
| } |
| case VOS_MODULE_ID_HDD: |
| case VOS_MODULE_ID_SME: |
| case VOS_MODULE_ID_PE: |
| case VOS_MODULE_ID_PMC: |
| case VOS_MODULE_ID_HDD_SOFTAP: |
| default: |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: Module ID %i " |
| "does not have its context allocated by VOSS", __func__, moduleID); |
| VOS_ASSERT(0); |
| return VOS_STATUS_E_INVAL; |
| } |
| } |
| |
| if ( NULL == *pGpModContext) |
| { |
| /* |
| ** Context has not been allocated or freed already! |
| */ |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,"%s: Module ID %i " |
| "context has not been allocated or freed already", __func__,moduleID); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| if (*pGpModContext != pModuleContext) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: pGpModContext != pModuleContext", __func__); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| if(pModuleContext != NULL) |
| vos_mem_free(pModuleContext); |
| |
| *pGpModContext = NULL; |
| |
| return VOS_STATUS_SUCCESS; |
| |
| } /* vos_free_context() */ |
| |
| /** |
| * vos_mq_post_message_by_priority() - posts message using priority |
| * to message queue |
| * @msgQueueId: message queue id |
| * @pMsg: message to be posted |
| * @is_high_priority: wheather message is high priority |
| * |
| * This function is used to post high priority message to message queue |
| * |
| * Return: VOS_STATUS_SUCCESS on success |
| * VOS_STATUS_E_FAILURE on failure |
| * VOS_STATUS_E_RESOURCES on resource allocation failure |
| */ |
| VOS_STATUS vos_mq_post_message_by_priority(VOS_MQ_ID msgQueueId, |
| vos_msg_t *pMsg, |
| int is_high_priority) |
| { |
| pVosMqType pTargetMq = NULL; |
| pVosMsgWrapper pMsgWrapper = NULL; |
| uint32_t debug_count; |
| |
| if ((gpVosContext == NULL) || (pMsg == NULL)) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Null params or global vos context is null", __func__); |
| VOS_ASSERT(0); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| switch (msgQueueId) |
| { |
| /// Message Queue ID for messages bound for SME |
| case VOS_MQ_ID_SME: |
| { |
| pTargetMq = &(gpVosContext->vosSched.smeMcMq); |
| break; |
| } |
| |
| /// Message Queue ID for messages bound for PE |
| case VOS_MQ_ID_PE: |
| { |
| pTargetMq = &(gpVosContext->vosSched.peMcMq); |
| break; |
| } |
| |
| /// Message Queue ID for messages bound for WDA |
| case VOS_MQ_ID_WDA: |
| { |
| pTargetMq = &(gpVosContext->vosSched.wdaMcMq); |
| break; |
| } |
| |
| /// Message Queue ID for messages bound for TL |
| case VOS_MQ_ID_TL: |
| { |
| pTargetMq = &(gpVosContext->vosSched.tlMcMq); |
| break; |
| } |
| |
| /// Message Queue ID for messages bound for the SYS module |
| case VOS_MQ_ID_SYS: |
| { |
| pTargetMq = &(gpVosContext->vosSched.sysMcMq); |
| break; |
| } |
| |
| default: |
| |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| ("%s: Trying to queue msg into unknown MC Msg queue ID %d"), |
| __func__, msgQueueId); |
| |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| VOS_ASSERT(NULL !=pTargetMq); |
| if (pTargetMq == NULL) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: pTargetMq == NULL", __func__); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| /* |
| ** Try and get a free Msg wrapper |
| */ |
| pMsgWrapper = vos_mq_get(&gpVosContext->freeVosMq); |
| |
| if (NULL == pMsgWrapper) { |
| debug_count = atomic_inc_return(&vos_wrapper_empty_count); |
| if (1 == debug_count) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: VOS Core run out of message wrapper %d", |
| __func__, debug_count); |
| vos_flush_logs(WLAN_LOG_TYPE_FATAL, |
| WLAN_LOG_INDICATOR_HOST_ONLY, |
| WLAN_LOG_REASON_VOS_MSG_UNDER_RUN, |
| DUMP_VOS_TRACE); |
| } |
| if (VOS_WRAPPER_MAX_FAIL_COUNT == debug_count) { |
| vos_wlanRestart(); |
| } |
| return VOS_STATUS_E_RESOURCES; |
| } |
| |
| atomic_set(&vos_wrapper_empty_count, 0); |
| |
| /* |
| ** Copy the message now |
| */ |
| vos_mem_copy( (v_VOID_t*)pMsgWrapper->pVosMsg, |
| (v_VOID_t*)pMsg, sizeof(vos_msg_t)); |
| |
| if (is_high_priority) |
| vos_mq_put_front(pTargetMq, pMsgWrapper); |
| else |
| vos_mq_put(pTargetMq, pMsgWrapper); |
| |
| set_bit(MC_POST_EVENT, &gpVosContext->vosSched.mcEventFlag); |
| wake_up_interruptible(&gpVosContext->vosSched.mcWaitQueue); |
| |
| return VOS_STATUS_SUCCESS; |
| |
| } |
| |
| v_VOID_t |
| vos_sys_probe_thread_cback |
| ( |
| v_VOID_t *pUserData |
| ) |
| { |
| if (gpVosContext != pUserData) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: gpVosContext != pUserData", __func__); |
| return; |
| } |
| |
| if (vos_event_set(&gpVosContext->ProbeEvent)!= VOS_STATUS_SUCCESS) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: vos_event_set failed", __func__); |
| return; |
| } |
| |
| } /* vos_sys_probe_thread_cback() */ |
| |
| v_VOID_t vos_WDAComplete_cback |
| ( |
| v_VOID_t *pUserData |
| ) |
| { |
| |
| if (gpVosContext != pUserData) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: gpVosContext != pUserData", __func__); |
| return; |
| } |
| |
| if (vos_event_set(&gpVosContext->wdaCompleteEvent)!= VOS_STATUS_SUCCESS) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: vos_event_set failed", __func__); |
| return; |
| } |
| |
| } /* vos_WDAComplete_cback() */ |
| |
| v_VOID_t vos_core_return_msg |
| ( |
| v_PVOID_t pVContext, |
| pVosMsgWrapper pMsgWrapper |
| ) |
| { |
| pVosContextType pVosContext = (pVosContextType) pVContext; |
| |
| VOS_ASSERT( gpVosContext == pVosContext); |
| |
| if (gpVosContext != pVosContext) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: gpVosContext != pVosContext", __func__); |
| return; |
| } |
| |
| VOS_ASSERT( NULL !=pMsgWrapper ); |
| |
| if (pMsgWrapper == NULL) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: pMsgWrapper == NULL in function", __func__); |
| return; |
| } |
| |
| /* |
| ** Return the message on the free message queue |
| */ |
| INIT_LIST_HEAD(&pMsgWrapper->msgNode); |
| vos_mq_put(&pVosContext->freeVosMq, pMsgWrapper); |
| |
| } /* vos_core_return_msg() */ |
| |
| |
| /** |
| @brief vos_fetch_tl_cfg_parms() - this function will attempt to read the |
| TL config params from the registry |
| |
| @param pAdapter : [inout] pointer to TL config block |
| |
| @return |
| None |
| |
| */ |
| v_VOID_t |
| vos_fetch_tl_cfg_parms |
| ( |
| WLANTL_ConfigInfoType *pTLConfig, |
| hdd_config_t * pConfig |
| ) |
| { |
| if (pTLConfig == NULL) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s NULL ptr passed in!", __func__); |
| return; |
| } |
| |
| pTLConfig->uDelayedTriggerFrmInt = pConfig->DelayedTriggerFrmInt; |
| pTLConfig->uMinFramesProcThres = pConfig->MinFramesProcThres; |
| pTLConfig->ip_checksum_offload = pConfig->enableIPChecksumOffload; |
| pTLConfig->enable_rxthread = |
| (WLAN_HDD_RX_HANDLE_RX_THREAD == pConfig->rxhandle) ? 1 : 0; |
| } |
| |
| /*--------------------------------------------------------------------------- |
| |
| \brief vos_shutdown() - shutdown VOS |
| |
| - All VOS submodules are closed. |
| |
| - All the WLAN SW components should have been opened. This includes |
| SYS, MAC, SME and TL. |
| |
| |
| \param vosContext: Global vos context |
| |
| |
| \return VOS_STATUS_SUCCESS - Operation successfull & vos is shutdown |
| |
| VOS_STATUS_E_FAILURE - Failure to close |
| |
| ---------------------------------------------------------------------------*/ |
| VOS_STATUS vos_shutdown(v_CONTEXT_t vosContext) |
| { |
| VOS_STATUS vosStatus; |
| |
| vosStatus = wma_wmi_work_close(vosContext); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Fail to close wma_wmi_work!", __func__); |
| VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus)); |
| } |
| |
| if (gpVosContext->htc_ctx) |
| { |
| HTCStop(gpVosContext->htc_ctx); |
| HTCDestroy(gpVosContext->htc_ctx); |
| gpVosContext->htc_ctx = NULL; |
| } |
| |
| vosStatus = WLANTL_Close(vosContext); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to close TL", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| |
| vosStatus = sme_Close( ((pVosContextType)vosContext)->pMACContext); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to close SME", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| |
| vosStatus = macClose( ((pVosContextType)vosContext)->pMACContext); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to close MAC", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| |
| ((pVosContextType)vosContext)->pMACContext = NULL; |
| |
| vosStatus = sysClose( vosContext ); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to close SYS", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| |
| if (TRUE == WDA_needShutdown(vosContext)) |
| { |
| /* If WDA stop failed, call WDA shutdown to cleanup WDA/WDI. */ |
| vosStatus = WDA_shutdown(vosContext, VOS_TRUE); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to shutdown WDA!", __func__); |
| VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus)); |
| } |
| } |
| else |
| { |
| vosStatus = WDA_close(vosContext); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to close WDA!", __func__); |
| VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus)); |
| } |
| } |
| |
| vosStatus = wma_wmi_service_close(vosContext); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to close wma_wmi_service!", __func__); |
| VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus)); |
| } |
| |
| vos_mq_deinit(&((pVosContextType)vosContext)->freeVosMq); |
| |
| vosStatus = vos_event_destroy(&gpVosContext->wdaCompleteEvent); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: failed to destroy wdaCompleteEvent", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| |
| vosStatus = vos_event_destroy(&gpVosContext->ProbeEvent); |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: failed to destroy ProbeEvent", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| /*--------------------------------------------------------------------------- |
| |
| \brief vos_wda_shutdown() - VOS interface to wda shutdown |
| |
| - WDA/WDI shutdown |
| |
| \param vosContext: Global vos context |
| |
| |
| \return VOS_STATUS_SUCCESS - Operation successfull |
| |
| VOS_STATUS_E_FAILURE - Failure to close |
| |
| ---------------------------------------------------------------------------*/ |
| VOS_STATUS vos_wda_shutdown(v_CONTEXT_t vosContext) |
| { |
| VOS_STATUS vosStatus; |
| vosStatus = WDA_shutdown(vosContext, VOS_FALSE); |
| |
| if (!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: failed to shutdown WDA", __func__); |
| VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); |
| } |
| return vosStatus; |
| } |
| /** |
| @brief vos_wlanShutdown() - This API will shutdown WLAN driver |
| |
| This function is called when Riva subsystem crashes. There are two |
| methods (or operations) in WLAN driver to handle Riva crash, |
| 1. shutdown: Called when Riva goes down, this will shutdown WLAN |
| driver without handshaking with Riva. |
| 2. re-init: Next API |
| @param |
| NONE |
| @return |
| VOS_STATUS_SUCCESS - Operation completed successfully. |
| VOS_STATUS_E_FAILURE - Operation failed. |
| |
| */ |
| VOS_STATUS vos_wlanShutdown(void) |
| { |
| VOS_STATUS vstatus; |
| vstatus = vos_watchdog_wlan_shutdown(); |
| return vstatus; |
| } |
| /** |
| @brief vos_wlanReInit() - This API will re-init WLAN driver |
| |
| This function is called when Riva subsystem reboots. There are two |
| methods (or operations) in WLAN driver to handle Riva crash, |
| 1. shutdown: Previous API |
| 2. re-init: Called when Riva comes back after the crash. This will |
| re-initialize WLAN driver. In some cases re-open may be |
| referred instead of re-init. |
| @param |
| NONE |
| @return |
| VOS_STATUS_SUCCESS - Operation completed successfully. |
| VOS_STATUS_E_FAILURE - Operation failed. |
| |
| */ |
| VOS_STATUS vos_wlanReInit(void) |
| { |
| VOS_STATUS vstatus; |
| vstatus = vos_watchdog_wlan_re_init(); |
| return vstatus; |
| } |
| /** |
| @brief vos_wlanRestart() - This API will reload WLAN driver. |
| |
| This function is called if driver detects any fatal state which |
| can be recovered by a WLAN module reload ( Android framwork initiated ). |
| Note that this API will not initiate any RIVA subsystem restart. |
| |
| The function wlan_hdd_restart_driver protects against re-entrant calls. |
| |
| @param |
| NONE |
| @return |
| VOS_STATUS_SUCCESS - Operation completed successfully. |
| VOS_STATUS_E_FAILURE - Operation failed. |
| VOS_STATUS_E_EMPTY - No configured interface |
| VOS_STATUS_E_ALREADY - Request already in progress |
| |
| |
| */ |
| VOS_STATUS vos_wlanRestart(void) |
| { |
| VOS_STATUS vstatus; |
| hdd_context_t *pHddCtx = NULL; |
| v_CONTEXT_t pVosContext = NULL; |
| |
| /* Check whether driver load unload is in progress */ |
| if(vos_is_load_unload_in_progress( VOS_MODULE_ID_VOSS, NULL)) |
| { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Driver load/unload is in progress, retry later.", __func__); |
| return VOS_STATUS_E_AGAIN; |
| } |
| |
| /* Get the Global VOSS Context */ |
| pVosContext = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL); |
| if(!pVosContext) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Global VOS context is Null", __func__); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| /* Get the HDD context */ |
| pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext ); |
| if(!pHddCtx) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: HDD context is Null", __func__); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| /* Reload the driver */ |
| vstatus = wlan_hdd_restart_driver(pHddCtx); |
| return vstatus; |
| } |
| |
| |
| /** |
| @brief vos_fwDumpReq() |
| |
| This function is called to issue dump commands to Firmware |
| |
| @param |
| cmd - Command No. to execute |
| arg1 - argument 1 to cmd |
| arg2 - argument 2 to cmd |
| arg3 - argument 3 to cmd |
| arg4 - argument 4 to cmd |
| @return |
| NONE |
| */ |
| v_VOID_t vos_fwDumpReq(tANI_U32 cmd, tANI_U32 arg1, tANI_U32 arg2, |
| tANI_U32 arg3, tANI_U32 arg4) |
| { |
| WDA_HALDumpCmdReq(NULL, cmd, arg1, arg2, arg3, arg4, NULL); |
| } |
| |
| VOS_STATUS vos_get_vdev_types(tVOS_CON_MODE mode, tANI_U32 *type, |
| tANI_U32 *sub_type) |
| { |
| VOS_STATUS status = VOS_STATUS_SUCCESS; |
| *type = 0; |
| *sub_type = 0; |
| switch (mode) |
| { |
| case VOS_STA_MODE: |
| *type = WMI_VDEV_TYPE_STA; |
| break; |
| case VOS_STA_SAP_MODE: |
| *type = WMI_VDEV_TYPE_AP; |
| break; |
| case VOS_P2P_DEVICE_MODE: |
| *type = WMI_VDEV_TYPE_AP; |
| *sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE; |
| break; |
| case VOS_P2P_CLIENT_MODE: |
| *type = WMI_VDEV_TYPE_STA; |
| *sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT; |
| break; |
| case VOS_P2P_GO_MODE: |
| *type = WMI_VDEV_TYPE_AP; |
| *sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO; |
| break; |
| case VOS_OCB_MODE: |
| *type = WMI_VDEV_TYPE_OCB; |
| break; |
| case VOS_IBSS_MODE: |
| *type = WMI_VDEV_TYPE_IBSS; |
| break; |
| case VOS_NDI_MODE: |
| *type = WMI_VDEV_TYPE_NDI; |
| break; |
| default: |
| hddLog(VOS_TRACE_LEVEL_ERROR, "Invalid device mode %d", mode); |
| status = VOS_STATUS_E_INVAL; |
| break; |
| } |
| return status; |
| } |
| |
| v_BOOL_t vos_is_packet_log_enabled(void) |
| { |
| hdd_context_t *pHddCtx; |
| |
| pHddCtx = (hdd_context_t*)(gpVosContext->pHDDContext); |
| if((NULL == pHddCtx) || |
| (NULL == pHddCtx->cfg_ini)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Hdd Context is Null", __func__); |
| return FALSE; |
| } |
| |
| return pHddCtx->cfg_ini->enablePacketLog; |
| } |
| |
| v_BOOL_t vos_config_is_no_ack(void) |
| { |
| hdd_context_t *pHddCtx; |
| |
| pHddCtx = (hdd_context_t*)(gpVosContext->pHDDContext); |
| if((NULL == pHddCtx) || |
| (NULL == pHddCtx->cfg_ini)) |
| { |
| VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Hdd Context is Null", __func__); |
| return FALSE; |
| } |
| |
| return pHddCtx->cfg_ini->gEnableNoAck; |
| } |
| |
| #ifdef WLAN_FEATURE_TSF_PLUS |
| bool vos_is_ptp_rx_opt_enabled(void) |
| { |
| hdd_context_t *hdd_ctx; |
| |
| hdd_ctx = (hdd_context_t *)(gpVosContext->pHDDContext); |
| if ((NULL == hdd_ctx) || (NULL == hdd_ctx->cfg_ini)) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Hdd Context is Null", __func__); |
| return false; |
| } |
| |
| return HDD_TSF_IS_RX_SET(hdd_ctx); |
| } |
| |
| bool vos_is_ptp_tx_opt_enabled(void) |
| { |
| hdd_context_t *hdd_ctx; |
| |
| hdd_ctx = (hdd_context_t *)(gpVosContext->pHDDContext); |
| if ((NULL == hdd_ctx) || (NULL == hdd_ctx->cfg_ini)) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Hdd Context is Null", __func__); |
| return false; |
| } |
| |
| return HDD_TSF_IS_TX_SET(hdd_ctx); |
| } |
| #endif |
| |
| #ifdef WLAN_FEATURE_DSRC |
| bool vos_is_ocb_tx_per_pkt_stats_enabled(void) |
| { |
| hdd_context_t *hdd_ctx; |
| |
| hdd_ctx = (hdd_context_t *)(gpVosContext->pHDDContext); |
| |
| if ((NULL == hdd_ctx) || (NULL == hdd_ctx->cfg_ini)) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Hdd Context is Null", __func__); |
| return false; |
| } |
| |
| return hdd_ctx->cfg_ini->ocb_tx_per_pkt_stats_enabled; |
| } |
| #endif |
| |
| VOS_STATUS vos_config_silent_recovery(pVosContextType vos_context) |
| { |
| struct ol_softc *scn; |
| struct device *dev; |
| |
| if (vos_is_logp_in_progress(VOS_MODULE_ID_VOSS, NULL)) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| FL("LOGP is in progress, ignore!")); |
| return VOS_STATUS_E_FAILURE; |
| } |
| vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, TRUE); |
| scn = vos_get_context(VOS_MODULE_ID_HIF, vos_context); |
| if (scn && scn->hif_sc) { |
| dev = scn->hif_sc->dev; |
| if (dev) |
| vos_schedule_recovery_work(dev); |
| } |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| void vos_trigger_recovery(bool skip_crash_inject) |
| { |
| pVosContextType vos_context; |
| tp_wma_handle wma_handle; |
| VOS_STATUS status = VOS_STATUS_SUCCESS; |
| void *runtime_context = NULL; |
| |
| vos_context = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL); |
| if (!vos_context) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "VOS context is invald!"); |
| return; |
| } |
| |
| wma_handle = (tp_wma_handle)vos_get_context(VOS_MODULE_ID_WDA, |
| vos_context); |
| if (!wma_handle) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "WMA context is invald!"); |
| return; |
| } |
| |
| runtime_context = vos_runtime_pm_prevent_suspend_init("vos_recovery"); |
| vos_runtime_pm_prevent_suspend(runtime_context); |
| |
| if (!skip_crash_inject) { |
| wma_crash_inject(wma_handle, RECOVERY_SIM_SELF_RECOVERY, 0); |
| status = vos_wait_single_event(&wma_handle->recovery_event, |
| WMA_CRASH_INJECT_TIMEOUT); |
| |
| if (VOS_STATUS_SUCCESS != status) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "CRASH_INJECT command is timed out!"); |
| if (!vos_config_silent_recovery(vos_context)) |
| goto out; |
| } |
| } else { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| FL("trigger silent recovery!")); |
| if (!vos_config_silent_recovery(vos_context)) |
| goto out; |
| } |
| out: |
| vos_runtime_pm_allow_suspend(runtime_context); |
| vos_runtime_pm_prevent_suspend_deinit(runtime_context); |
| } |
| |
| /** |
| * @brief vos_get_monotonic_boottime() |
| * Get kernel boot time. |
| * @return Time in microseconds |
| */ |
| |
| v_U64_t vos_get_monotonic_boottime(void) |
| { |
| #ifdef CONFIG_CNSS |
| struct timespec ts; |
| |
| vos_get_monotonic_boottime_ts(&ts); |
| return (((v_U64_t)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000)); |
| #else |
| return ((v_U64_t)adf_os_ticks_to_msecs(adf_os_ticks()) * 1000); |
| #endif |
| } |
| |
| #ifdef FEATURE_WLAN_D0WOW |
| v_VOID_t vos_pm_control(v_BOOL_t vote) |
| { |
| vos_wlan_pm_control(vote); |
| } |
| #endif |
| |
| /** |
| * vos_set_wakelock_logging() - Logging of wakelock enabled/disabled |
| * @value: Boolean value |
| * |
| * This function is used to set the flag which will indicate whether |
| * logging of wakelock is enabled or not |
| * |
| * Return: None |
| */ |
| void vos_set_wakelock_logging(bool value) |
| { |
| VosContextType *vos_context; |
| |
| vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); |
| if (!vos_context) { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "vos context is Invald"); |
| return; |
| } |
| vos_context->is_wakelock_log_enabled = value; |
| } |
| |
| /** |
| * vos_is_wakelock_enabled() - Check if logging of wakelock is enabled/disabled |
| * @value: Boolean value |
| * |
| * This function is used to check whether logging of wakelock is enabled or not |
| * |
| * Return: true if logging of wakelock is enabled |
| */ |
| bool vos_is_wakelock_enabled(void) |
| { |
| VosContextType *vos_context; |
| |
| vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); |
| if (!vos_context) { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "vos context is Invald"); |
| return false; |
| } |
| return vos_context->is_wakelock_log_enabled; |
| } |
| |
| /** |
| * vos_set_ring_log_level() - Convert HLOS values to driver log levels |
| * @ring_id: ring_id |
| * @log_levelvalue: Log level specificed |
| * |
| * This function sets the log level of a particular ring |
| * |
| * Return: None |
| */ |
| void vos_set_ring_log_level(uint32_t ring_id, uint32_t log_level) |
| { |
| VosContextType *vos_context; |
| uint32_t log_val; |
| |
| vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); |
| if (!vos_context) { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "%s: vos context is Invald", __func__); |
| return; |
| } |
| |
| switch (log_level) { |
| case LOG_LEVEL_NO_COLLECTION: |
| log_val = WLAN_LOG_LEVEL_OFF; |
| break; |
| case LOG_LEVEL_NORMAL_COLLECT: |
| log_val = WLAN_LOG_LEVEL_NORMAL; |
| break; |
| case LOG_LEVEL_ISSUE_REPRO: |
| log_val = WLAN_LOG_LEVEL_REPRO; |
| break; |
| case LOG_LEVEL_ACTIVE: |
| default: |
| log_val = WLAN_LOG_LEVEL_ACTIVE; |
| break; |
| } |
| |
| if (ring_id == RING_ID_WAKELOCK) { |
| vos_context->wakelock_log_level = log_val; |
| return; |
| } else if (ring_id == RING_ID_CONNECTIVITY) { |
| vos_context->connectivity_log_level = log_val; |
| return; |
| } else if (ring_id == RING_ID_PER_PACKET_STATS) { |
| vos_context->packet_stats_log_level = log_val; |
| return; |
| } else if (ring_id == RING_ID_DRIVER_DEBUG) { |
| vos_context->driver_debug_log_level = log_val; |
| return; |
| } else if (ring_id == RING_ID_FIRMWARE_DEBUG) { |
| vos_context->fw_debug_log_level = log_val; |
| return; |
| } |
| } |
| |
| /** |
| * vos_get_ring_log_level() - Get the a ring id's log level |
| * @ring_id: Ring id |
| * |
| * Fetch and return the log level corresponding to a ring id |
| * |
| * Return: Log level corresponding to the ring ID |
| */ |
| enum wifi_driver_log_level vos_get_ring_log_level(uint32_t ring_id) |
| { |
| VosContextType *vos_context; |
| |
| vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); |
| if (!vos_context) { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "%s: vos context is Invald", __func__); |
| return WLAN_LOG_LEVEL_OFF; |
| } |
| |
| if (ring_id == RING_ID_WAKELOCK) |
| return vos_context->wakelock_log_level; |
| else if (ring_id == RING_ID_CONNECTIVITY) |
| return vos_context->connectivity_log_level; |
| else if (ring_id == RING_ID_PER_PACKET_STATS) |
| return vos_context->packet_stats_log_level; |
| else if (ring_id == RING_ID_DRIVER_DEBUG) |
| return vos_context->driver_debug_log_level; |
| else if (ring_id == RING_ID_FIRMWARE_DEBUG) |
| return vos_context->fw_debug_log_level; |
| |
| return WLAN_LOG_LEVEL_OFF; |
| } |
| |
| /** |
| * vos_set_multicast_logging() - Set mutlicast logging value |
| * @value: Value of multicast logging |
| * |
| * Set the multicast logging value which will indicate |
| * whether to multicast host and fw messages even |
| * without any registration by userspace entity |
| * |
| * Return: None |
| */ |
| void vos_set_multicast_logging(uint8_t value) |
| { |
| vos_multicast_logging = value; |
| } |
| |
| /** |
| * vos_is_multicast_logging() - Get multicast logging value |
| * |
| * Get the multicast logging value which will indicate |
| * whether to multicast host and fw messages even |
| * without any registration by userspace entity |
| * |
| * Return: 0 - Multicast logging disabled, 1 - Multicast logging enabled |
| */ |
| uint8_t vos_is_multicast_logging(void) |
| { |
| return vos_multicast_logging; |
| } |
| |
| /* |
| * vos_reset_log_completion() - Reset log param structure |
| *@vos_context: Pointer to global vos context |
| * |
| * This function is used to reset the logging related |
| * parameters to default. |
| * |
| * Return: None |
| */ |
| void vos_reset_log_completion(VosContextType *vos_context) |
| { |
| /* Vos Context is validated by the caller */ |
| vos_spin_lock_acquire(&vos_context->bug_report_lock); |
| vos_context->log_complete.indicator = WLAN_LOG_INDICATOR_UNUSED; |
| vos_context->log_complete.is_fatal = WLAN_LOG_TYPE_NON_FATAL; |
| vos_context->log_complete.is_report_in_progress = false; |
| vos_context->log_complete.reason_code = WLAN_LOG_REASON_CODE_UNUSED; |
| vos_spin_lock_release(&vos_context->bug_report_lock); |
| } |
| |
| /* |
| * vos_init_log_completion() - Initialize log param structure |
| * |
| * This function is used to initialize the logging related |
| * parameters |
| * |
| * Return: None |
| */ |
| void vos_init_log_completion(void) |
| { |
| VosContextType *vos_context; |
| |
| vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); |
| if (!vos_context) { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "%s: vos context is Invalid", __func__); |
| return; |
| } |
| |
| vos_context->log_complete.is_fatal = WLAN_LOG_TYPE_NON_FATAL; |
| vos_context->log_complete.indicator = WLAN_LOG_INDICATOR_UNUSED; |
| vos_context->log_complete.reason_code = WLAN_LOG_REASON_CODE_UNUSED; |
| vos_context->log_complete.is_report_in_progress = false; |
| |
| vos_spin_lock_init(&vos_context->bug_report_lock); |
| } |
| |
| /** |
| * vos_deinit_log_completion() - Deinitialize log param structure |
| * |
| * This function is used to deinitialize the logging related |
| * parameters |
| * |
| * Return: None |
| */ |
| void vos_deinit_log_completion(void) |
| { |
| VosContextType *vos_context; |
| |
| vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); |
| if (!vos_context) { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "%s: vos context is Invalid", __func__); |
| return; |
| } |
| |
| vos_spin_lock_destroy(&vos_context->bug_report_lock); |
| } |
| |
| /** |
| * vos_set_log_completion() - Store the logging params |
| * @is_fatal: Indicates if the event triggering bug report is fatal or not |
| * @indicator: Source which trigerred the bug report |
| * @reason_code: Reason for triggering bug report |
| * |
| * This function is used to set the logging parameters based on the |
| * caller |
| * |
| * Return: 0 if setting of params is successful |
| */ |
| VOS_STATUS vos_set_log_completion(uint32_t is_fatal, |
| uint32_t indicator, |
| uint32_t reason_code) |
| { |
| VosContextType *vos_context; |
| |
| vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); |
| if (!vos_context) { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "%s: vos context is Invalid", __func__); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| vos_spin_lock_acquire(&vos_context->bug_report_lock); |
| vos_context->log_complete.is_fatal = is_fatal; |
| vos_context->log_complete.indicator = indicator; |
| vos_context->log_complete.reason_code = reason_code; |
| vos_context->log_complete.is_report_in_progress = true; |
| vos_spin_lock_release(&vos_context->bug_report_lock); |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| /** |
| * vos_get_log_and_reset_completion() - Get and reset the logging |
| * related params |
| * @is_fatal: Indicates if the event triggering bug report is fatal or not |
| * @indicator: Source which trigerred the bug report |
| * @reason_code: Reason for triggering bug report |
| * @ssr_needed: Indicates if SSR is required or not |
| * |
| * This function is used to get the logging related parameters |
| * |
| * Return: None |
| */ |
| void vos_get_log_and_reset_completion(uint32_t *is_fatal, |
| uint32_t *indicator, |
| uint32_t *reason_code, |
| uint32_t *is_ssr_needed) |
| { |
| VosContextType *vos_context; |
| |
| vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); |
| if (!vos_context) { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "%s: vos context is Invalid", __func__); |
| return; |
| } |
| |
| vos_spin_lock_acquire(&vos_context->bug_report_lock); |
| *is_fatal = vos_context->log_complete.is_fatal; |
| *indicator = vos_context->log_complete.indicator; |
| *reason_code = vos_context->log_complete.reason_code; |
| |
| if ((WLAN_LOG_INDICATOR_HOST_DRIVER == *indicator) && |
| ((WLAN_LOG_REASON_SME_OUT_OF_CMD_BUF == *reason_code) || |
| (WLAN_LOG_REASON_SME_COMMAND_STUCK == *reason_code) || |
| (WLAN_LOG_REASON_STALE_SESSION_FOUND == *reason_code) || |
| (WLAN_LOG_REASON_SCAN_NOT_ALLOWED == *reason_code))) |
| *is_ssr_needed = true; |
| else |
| *is_ssr_needed = false; |
| |
| vos_spin_lock_release(&vos_context->bug_report_lock); |
| |
| vos_reset_log_completion(vos_context); |
| } |
| |
| /** |
| * vos_is_log_report_in_progress() - Check if bug reporting is in progress |
| * |
| * This function is used to check if the bug reporting is already in progress |
| * |
| * Return: true if the bug reporting is in progress |
| */ |
| bool vos_is_log_report_in_progress(void) |
| { |
| VosContextType *vos_context; |
| |
| vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); |
| if (!vos_context) { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "%s: vos context is Invalid", __func__); |
| return true; |
| } |
| return vos_context->log_complete.is_report_in_progress; |
| } |
| /** |
| * vos_is_fatal_event_enabled() - Return if fatal event is enabled |
| * |
| * Return true if fatal event is enabled is in progress. |
| */ |
| bool vos_is_fatal_event_enabled(void) |
| { |
| VosContextType *vos_context = |
| vos_get_global_context(VOS_MODULE_ID_SYS, NULL); |
| |
| if (!vos_context) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: Global VOS context is Null", __func__); |
| return false; |
| } |
| |
| return vos_context->enable_fatal_event; |
| } |
| |
| /** |
| * vos_get_log_indicator() - Get the log flush indicator |
| * |
| * This function is used to get the log flush indicator |
| * |
| * Return: log indicator |
| */ |
| uint32_t vos_get_log_indicator(void) |
| { |
| VosContextType *vos_context; |
| uint32_t indicator; |
| |
| vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); |
| if (!vos_context) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| FL("vos context is Invalid")); |
| return WLAN_LOG_INDICATOR_UNUSED; |
| } |
| if (vos_context->isLoadUnloadInProgress || |
| vos_context->isLogpInProgress || |
| vos_context->isReInitInProgress) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, |
| FL("In LoadUnload: %u LogP: %u ReInit: %u"), |
| vos_context->isLoadUnloadInProgress, |
| vos_context->isLogpInProgress, |
| vos_context->isReInitInProgress); |
| return WLAN_LOG_INDICATOR_UNUSED; |
| } |
| |
| vos_spin_lock_acquire(&vos_context->bug_report_lock); |
| indicator = vos_context->log_complete.indicator; |
| vos_spin_lock_release(&vos_context->bug_report_lock); |
| return indicator; |
| } |
| |
| /** |
| * vos_wlan_flush_host_logs_for_fatal() - Wrapper to flush host logs |
| * |
| * This function is used to send signal to the logger thread to |
| * flush the host logs. |
| * |
| * Return: None |
| * |
| */ |
| void vos_wlan_flush_host_logs_for_fatal(void) |
| { |
| wlan_flush_host_logs_for_fatal(); |
| } |
| |
| /** |
| * vos_flush_logs() - Report fatal event to userspace |
| * @is_fatal: Indicates if the event triggering bug report is fatal or not |
| * @indicator: Source which trigerred the bug report |
| * @reason_code: Reason for triggering bug report |
| * @dump_vos_trace: If vos trace are needed in logs. |
| * @pkt_trace: flag to indicate when to report packet trace |
| * dump this info when connection related error occurs |
| * |
| * This function sets the log related params and send the WMI command to the |
| * FW to flush its logs. On receiving the flush completion event from the FW |
| * the same will be conveyed to userspace |
| * |
| * Return: 0 on success |
| */ |
| VOS_STATUS vos_flush_logs(uint32_t is_fatal, |
| uint32_t indicator, |
| uint32_t reason_code, |
| uint32_t dump_trace) |
| { |
| uint32_t ret; |
| VOS_STATUS status; |
| VosContextType *vos_context; |
| |
| vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); |
| if (!vos_context) { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "%s: vos context is Invalid", __func__); |
| return eHAL_STATUS_FAILURE; |
| } |
| |
| if (!vos_context->enable_fatal_event) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, |
| "%s: Fatal event not enabled", __func__); |
| return eHAL_STATUS_FAILURE; |
| } |
| if (vos_context->is_unload_in_progress || |
| vos_context->is_load_in_progress || |
| vos_context->isLogpInProgress) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: un/Load/SSR in progress", __func__); |
| return eHAL_STATUS_FAILURE; |
| } |
| |
| if (vos_is_log_report_in_progress() == true) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: Bug report already in progress - dropping! type:%d, indicator=%d reason_code=%d", |
| __func__, is_fatal, indicator, reason_code); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| status = vos_set_log_completion(is_fatal, indicator, reason_code); |
| if (VOS_STATUS_SUCCESS != status) { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to set log trigger params", __func__); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "%s: Triggering bug report: type:%d, indicator=%d reason_code=%d dump_trace=0x%x", |
| __func__, is_fatal, indicator, reason_code, dump_trace); |
| |
| if (dump_trace & DUMP_VOS_TRACE) |
| vosTraceDumpAll(vos_context->pMACContext, 0, 0, 500, 0); |
| |
| #ifdef QCA_PKT_PROTO_TRACE |
| if (dump_trace & DUMP_PACKET_TRACE) |
| vos_pkt_trace_buf_dump(); |
| #endif |
| if (WLAN_LOG_INDICATOR_HOST_ONLY == indicator) { |
| vos_wlan_flush_host_logs_for_fatal(); |
| return VOS_STATUS_SUCCESS; |
| } |
| ret = vos_send_flush_logs_cmd_to_fw(vos_context->pMACContext); |
| if (0 != ret) { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "%s: Failed to send flush FW log", __func__); |
| vos_reset_log_completion(vos_context); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| /** |
| * vos_logging_set_fw_flush_complete() - Wrapper for FW log flush completion |
| * |
| * This function is used to send signal to the logger thread to indicate |
| * that the flushing of FW logs is complete by the FW |
| * |
| * Return: None |
| * |
| */ |
| void vos_logging_set_fw_flush_complete(void) |
| { |
| wlan_logging_set_fw_flush_complete(); |
| } |
| |
| /** |
| * vos_set_fatal_event() - set fatal event status |
| * @value: pending statue to set |
| * |
| * Return: None |
| */ |
| void vos_set_fatal_event(bool value) |
| { |
| if (gpVosContext == NULL) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: global voss context is NULL", __func__); |
| return; |
| } |
| |
| gpVosContext->enable_fatal_event = value; |
| } |
| |
| /** |
| * vos_probe_threads() - VOS API to post messages |
| * to all the threads to detect if they are active or not |
| * |
| * Return: None |
| * |
| */ |
| void vos_probe_threads(void) |
| { |
| vos_msg_t msg; |
| |
| msg.callback = vos_wd_reset_thread_stuck_count; |
| /* Post Message to MC Thread */ |
| sysBuildMessageHeader(SYS_MSG_ID_MC_THR_PROBE, &msg); |
| if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_SYS, &msg)) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| FL("Unable to post SYS_MSG_ID_MC_THR_PROBE message to MC thread")); |
| } |
| } |
| /** |
| * vos_pkt_stats_to_logger_thread() - send pktstats to user |
| * @pl_hdr: Pointer to pl_hdr |
| * @pkt_dump: Pointer to pkt_dump data structure. |
| * @data: Pointer to data |
| * |
| * This function is used to send the pkt stats to SVC module. |
| * |
| * Return: None |
| */ |
| inline void vos_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump, |
| void *data) |
| { |
| if (vos_get_ring_log_level(RING_ID_PER_PACKET_STATS) != |
| WLAN_LOG_LEVEL_ACTIVE) |
| return; |
| |
| wlan_pkt_stats_to_logger_thread(pl_hdr, pkt_dump, data); |
| } |
| |
| /** |
| * vos_get_radio_index() - get radio index |
| * |
| * Return: radio index otherwise, -EINVAL |
| */ |
| int vos_get_radio_index(void) |
| { |
| if (gpVosContext == NULL) { |
| /* this should never change to use VOS_TRACE interface */ |
| pr_err("global voss context is NULL\n"); |
| return -EINVAL; |
| } |
| return gpVosContext->radio_index; |
| } |
| |
| /** |
| * vos_set_radio_index() - set radio index |
| * @radio_index: the radio index |
| * |
| * Return: 0 for success, otherwise -EINVAL |
| */ |
| int vos_set_radio_index(int radio_index) |
| { |
| if (gpVosContext == NULL) { |
| /* this should never change to use VOS_TRACE interface */ |
| pr_err("global voss context is NULL\n"); |
| return -EINVAL; |
| } |
| |
| gpVosContext->radio_index = radio_index; |
| return 0; |
| } |
| |
| /** |
| * vos_svc_fw_shutdown_ind() - API to send userspace about FW crash |
| * |
| * @data: Device Pointer |
| * |
| * Return: None |
| */ |
| void vos_svc_fw_shutdown_ind(struct device *dev) |
| { |
| hdd_svc_fw_shutdown_ind(dev); |
| } |
| |
| v_U64_t vos_get_monotonic_boottime_ns(void) |
| { |
| struct timespec ts; |
| |
| ktime_get_ts(&ts); |
| return timespec_to_ns(&ts); |
| } |
| |
| #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 10, 0)) |
| v_U64_t vos_get_bootbased_boottime_ns(void) |
| { |
| return ktime_get_boot_ns(); |
| } |
| |
| #else |
| v_U64_t vos_get_bootbased_boottime_ns(void) |
| { |
| return ktime_to_ns(ktime_get_boottime()); |
| } |
| #endif |
| |
| /** |
| * vos_do_div() - wrapper function for kernel macro(do_div). |
| * |
| * @dividend: Dividend value |
| * @divisor : Divisor value |
| * |
| * Return: Quotient |
| */ |
| uint64_t vos_do_div(uint64_t dividend, uint32_t divisor) |
| { |
| do_div(dividend, divisor); |
| /*do_div macro updates dividend with Quotient of dividend/divisor */ |
| return dividend; |
| } |
| |
| uint64_t vos_do_div64(uint64_t dividend, uint64_t divisor) |
| { |
| uint64_t n = dividend; |
| uint64_t base = divisor; |
| if ((base & 0xffffffff00000000ULL) != 0) { |
| n >>= 16; |
| base >>= 16; |
| |
| if ((base & 0xffff00000000ULL) != 0) { |
| n >>= 16; |
| base >>= 16; |
| } |
| return vos_do_div(n, (uint32_t)base); |
| } else { |
| return vos_do_div(n, base); |
| } |
| } |
| |
| /** |
| * vos_force_fw_dump() - force target to dump |
| * |
| *return |
| * VOS_STATUS_SUCCESS - Operation completed successfully. |
| * VOS_STATUS_E_FAILURE - Operation failed. |
| */ |
| VOS_STATUS vos_force_fw_dump(void) |
| { |
| struct ol_softc *scn; |
| |
| scn = vos_get_context(VOS_MODULE_ID_HIF, gpVosContext); |
| if (!scn) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: scn is null!", __func__); |
| return VOS_STATUS_E_FAILURE; |
| } |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s:enter!", __func__); |
| |
| ol_target_failure(scn, A_ERROR); |
| |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| /** |
| * vos_is_probe_rsp_offload_enabled - API to check if probe response offload |
| * feature is enabled from ini |
| * |
| * return - false: probe response offload is disabled/any-error |
| * true: probe response offload is enabled |
| */ |
| bool vos_is_probe_rsp_offload_enabled(void) |
| { |
| hdd_context_t *pHddCtx = NULL; |
| |
| if (gpVosContext == NULL) { |
| pr_err("global voss context is NULL\n"); |
| return false; |
| } |
| |
| pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, |
| gpVosContext); |
| if (!pHddCtx) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: HDD context is Null", __func__); |
| return false; |
| } |
| |
| return pHddCtx->cfg_ini->sap_probe_resp_offload; |
| } |
| |
| bool vos_is_mon_enable(void) |
| { |
| hdd_context_t *phdd_ctx = NULL; |
| |
| if (gpVosContext == NULL) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, |
| "%s: global voss context is NULL", __func__); |
| return false; |
| } |
| |
| phdd_ctx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, |
| gpVosContext); |
| if (!phdd_ctx) { |
| VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, |
| "%s: HDD context is Null", __func__); |
| return false; |
| } |
| |
| return phdd_ctx->is_mon_enable; |
| } |