/*---------------------------------------------------------------------------- @brief TM Level Change handler Received Tm Level changed notification @param dev : Device context changedTmLevel : Changed new TM level @return ----------------------------------------------------------------------------*/ void hddDevTmLevelChangedHandler(struct device *dev, int changedTmLevel) { hdd_context_t *pHddCtx = NULL; WLAN_TmLevelEnumType newTmLevel = changedTmLevel; hdd_adapter_t *staAdapater; pHddCtx = (hdd_context_t*)wcnss_wlan_get_drvdata(dev); if((pHddCtx->tmInfo.currentTmLevel == newTmLevel) || (!pHddCtx->cfg_ini->thermalMitigationEnable)) { VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_WARN, "%s: TM Not enabled %d or Level does not changed %d", __func__, pHddCtx->cfg_ini->thermalMitigationEnable, newTmLevel); /* TM Level does not changed, * Or feature does not enabled * do nothing */ return; } sme_SetTmLevel(pHddCtx->hHal, changedTmLevel, 0); if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock)) { VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR, "%s: Aquire lock fail", __func__); return; } pHddCtx->tmInfo.currentTmLevel = changedTmLevel; pHddCtx->tmInfo.txFrameCount = 0; vos_mem_copy(&pHddCtx->tmInfo.tmAction, &thermalMigrationAction[newTmLevel], sizeof(hdd_tmLevelAction_t)); if(pHddCtx->tmInfo.tmAction.enterImps) { staAdapater = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); if(staAdapater) { if(hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(staAdapater))) { sme_RoamDisconnect(pHddCtx->hHal, staAdapater->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED); } } } mutex_unlock(&pHddCtx->tmInfo.tmOperationLock); return; }
static ssize_t wcnss_patterngen_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { hdd_adapter_t *pAdapter = (hdd_adapter_t *)file->private_data; hdd_context_t *pHddCtx; tSirAddPeriodicTxPtrn *addPeriodicTxPtrnParams; tSirDelPeriodicTxPtrn *delPeriodicTxPtrnParams; char *cmd, *sptr, *token; v_U8_t pattern_idx = 0; v_U8_t pattern_duration = 0; char *pattern_buf; v_U16_t pattern_len = 0; v_U16_t i = 0; if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: Invalid adapter or adapter has invalid magic.", __func__); return -EINVAL; } pHddCtx = WLAN_HDD_GET_CTX(pAdapter); if (!sme_IsFeatureSupportedByFW(WLAN_PERIODIC_TX_PTRN)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Periodic Tx Pattern Offload feature is not supported " "in firmware!", __func__); return -EINVAL; } if (count < MAX_USER_COMMAND_SIZE_FRAME) cmd = vos_mem_malloc(count + 1); else { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Command length is larger than d% bytes.", __func__, MAX_USER_COMMAND_SIZE_FRAME); return -EINVAL; } if (!cmd) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Memory allocation for cmd failed!", __func__); return -EFAULT; } if (copy_from_user(cmd, buf, count)) { vos_mem_free(cmd); return -EFAULT; } cmd[count] = '\0'; sptr = cmd; token = strsep(&sptr, " "); if (!token) goto failure; if (kstrtou8(token, 0, &pattern_idx)) goto failure; if (pattern_idx > (MAXNUM_PERIODIC_TX_PTRNS - 1)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Pattern index %d is not in the range (0 ~ %d).", __func__, pattern_idx, MAXNUM_PERIODIC_TX_PTRNS - 1); goto failure; } token = strsep(&sptr, " "); if (!token) goto failure; if (kstrtou8(token, 0, &pattern_duration)) goto failure; if (!pattern_duration) { delPeriodicTxPtrnParams = vos_mem_malloc(sizeof(tSirDelPeriodicTxPtrn)); if (!delPeriodicTxPtrnParams) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Memory allocation for delPeriodicTxPtrnParams " "failed!", __func__); vos_mem_free(cmd); return -EFAULT; } delPeriodicTxPtrnParams->ucPatternIdBitmap = 1 << pattern_idx; vos_mem_copy(delPeriodicTxPtrnParams->macAddress, pAdapter->macAddressCurrent.bytes, 6); if (eHAL_STATUS_SUCCESS != sme_DelPeriodicTxPtrn(pHddCtx->hHal, delPeriodicTxPtrnParams)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: sme_DelPeriodicTxPtrn() failed!", __func__); vos_mem_free(delPeriodicTxPtrnParams); goto failure; } vos_mem_free(delPeriodicTxPtrnParams); vos_mem_free(cmd); return count; } if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Not in Connected state!", __func__); goto failure; } token = strsep(&sptr, " "); if (!token) goto failure; pattern_buf = token; pattern_buf[strlen(pattern_buf) - 1] = '\0'; pattern_len = strlen(pattern_buf); if (pattern_len % 2) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Malformed pattern!", __func__); goto failure; } else pattern_len >>= 1; if (pattern_len < 14 || pattern_len > PERIODIC_TX_PTRN_MAX_SIZE) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Not an 802.3 frame!", __func__); goto failure; } addPeriodicTxPtrnParams = vos_mem_malloc(sizeof(tSirAddPeriodicTxPtrn)); if (!addPeriodicTxPtrnParams) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Memory allocation for addPeriodicTxPtrnParams " "failed!", __func__); vos_mem_free(cmd); return -EFAULT; } addPeriodicTxPtrnParams->ucPtrnId = pattern_idx; addPeriodicTxPtrnParams->usPtrnIntervalMs = pattern_duration * 500; addPeriodicTxPtrnParams->ucPtrnSize = pattern_len; vos_mem_copy(addPeriodicTxPtrnParams->macAddress, pAdapter->macAddressCurrent.bytes, 6); for(i = 0; i < addPeriodicTxPtrnParams->ucPtrnSize; i++) { addPeriodicTxPtrnParams->ucPattern[i] = (hdd_parse_hex(pattern_buf[0]) << 4) + hdd_parse_hex(pattern_buf[1]); pattern_buf += 2; } if (eHAL_STATUS_SUCCESS != sme_AddPeriodicTxPtrn(pHddCtx->hHal, addPeriodicTxPtrnParams)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: sme_AddPeriodicTxPtrn() failed!", __func__); vos_mem_free(addPeriodicTxPtrnParams); goto failure; } vos_mem_free(addPeriodicTxPtrnParams); vos_mem_free(cmd); return count; failure: vos_mem_free(cmd); return -EINVAL; }