blob: db2962fbf744bb55d741cd89554a407da897185a [file]
/******************************************************************************
*
* This file is provided under a dual license. When you use or
* distribute this software, you may choose to be licensed under
* version 2 of the GNU General Public License ("GPLv2 License")
* or BSD License.
*
* GPLv2 License
*
* Copyright(C) 2016 MediaTek Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See http://www.gnu.org/licenses/gpl-2.0.html for more details.
*
* BSD LICENSE
*
* Copyright(C) 2016 MediaTek Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
/*
** Id: /os/linux/gl_proc.c
*/
/*! \file "gl_proc.c"
* \brief This file defines the interface which can interact with users
* in /proc fs.
*
* Detail description.
*/
/*******************************************************************************
* C O M P I L E R F L A G S
*******************************************************************************
*/
/*******************************************************************************
* E X T E R N A L R E F E R E N C E S
*******************************************************************************
*/
#include "precomp.h"
#include "gl_os.h"
#include "gl_kal.h"
#include "debug.h"
#include "wlan_lib.h"
#include "debug.h"
#include "wlan_oid.h"
/*******************************************************************************
* C O N S T A N T S
*******************************************************************************
*/
#define PROC_MAX_BUF_SIZE 3000
#define PROC_MCR_ACCESS "mcr"
#define PROC_ROOT_NAME "wlan"
#if CFG_SUPPORT_DEBUG_FS
#define PROC_ROAM_PARAM "roam_param"
#endif
#define PROC_COUNTRY "country"
#define PROC_DRV_STATUS "status"
#define PROC_RX_STATISTICS "rx_statistics"
#define PROC_TX_STATISTICS "tx_statistics"
#define PROC_DBG_LEVEL_NAME "dbgLevel"
#define PROC_DRIVER_CMD "driver"
#define PROC_CFG "cfg"
#define PROC_EFUSE_DUMP "efuse_dump"
#define PROC_GET_TXPWR_TBL "get_txpwr_tbl"
#define PROC_PKT_DELAY_DBG "pktDelay"
#if CFG_SUPPORT_SET_CAM_BY_PROC
#define PROC_SET_CAM "setCAM"
#endif
#define PROC_AUTO_PERF_CFG "autoPerfCfg"
#if CFG_DISCONN_DEBUG_FEATURE
#define PROC_DISCONN_INFO "disconn_info"
#endif
#if CFG_SUPPORT_CSI
#define PROC_CSI_DATA_NAME "csi_data"
#endif
#define PROC_MCR_ACCESS_MAX_USER_INPUT_LEN 20
#define PROC_RX_STATISTICS_MAX_USER_INPUT_LEN 10
#define PROC_TX_STATISTICS_MAX_USER_INPUT_LEN 10
#define PROC_DBG_LEVEL_MAX_USER_INPUT_LEN 20
#define PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN 30
#define PROC_UID_SHELL 2000
#define PROC_GID_WIFI 1010
/* notice: str only can be an array */
#define SNPRINTF(buf, size, arg) {buf += \
snprintf((char *)(buf), size, PRINTF_ARG arg); }
#ifdef CFG_GET_TEMPURATURE
#define PROC_GET_TEMPETATURE "get_temperature"
#endif
/*******************************************************************************
* D A T A T Y P E S
*******************************************************************************
*/
/*******************************************************************************
* P U B L I C D A T A
*******************************************************************************
*/
/*******************************************************************************
* P R I V A T E D A T A
*******************************************************************************
*/
static struct GLUE_INFO *g_prGlueInfo_proc;
static uint32_t u4McrOffset;
static struct proc_dir_entry *gprProcRoot;
static uint8_t aucDbModuleName[][PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN] = {
"INIT", "HAL", "INTR", "REQ", "TX", "RX", "RFTEST", "EMU",
"SW1", "SW2", "SW3", "SW4", "HEM", "AIS", "RLM", "MEM",
"CNM", "RSN", "BSS", "SCN", "SAA", "AAA", "P2P", "QM",
"SEC", "BOW", "WAPI", "ROAMING", "TDLS", "PF", "OID", "NIC"
};
/* This buffer could be overwrite by any proc commands */
static uint8_t g_aucProcBuf[3000];
/* This u32 is only for DriverCmdRead/Write,
* should not be used by other function
*/
static int32_t g_NextDriverReadLen;
/*******************************************************************************
* M A C R O S
*******************************************************************************
*/
#define GET_VARNAME(var) #var
/*******************************************************************************
* F U N C T I O N D E C L A R A T I O N S
*******************************************************************************
*/
#if CFG_SUPPORT_CSI
static int procCSIDataOpen(struct inode *n, struct file *f)
{
struct CSI_INFO_T *prCSIInfo = NULL;
if (g_prGlueInfo_proc && g_prGlueInfo_proc->prAdapter) {
prCSIInfo = &(g_prGlueInfo_proc->prAdapter->rCSIInfo);
prCSIInfo->bIncomplete = FALSE;
}
return 0;
}
static int procCSIDataRelease(struct inode *n, struct file *f)
{
struct CSI_INFO_T *prCSIInfo = NULL;
if (g_prGlueInfo_proc && g_prGlueInfo_proc->prAdapter) {
prCSIInfo = &(g_prGlueInfo_proc->prAdapter->rCSIInfo);
prCSIInfo->bIncomplete = FALSE;
}
return 0;
}
static ssize_t procCSIDataPrepare(
uint8_t *buf,
struct CSI_INFO_T *prCSIInfo,
struct CSI_DATA_T *prCSIData)
{
int32_t i4Pos = 0;
uint8_t *tmpBuf = buf;
uint16_t u2DataSize = prCSIData->u2DataCount * sizeof(int16_t);
uint16_t u2Rsvd1Size = prCSIData->ucRsvd1Cnt * sizeof(int32_t);
enum ENUM_CSI_MODULATION_BW_TYPE_T eModulationType = CSI_TYPE_CCK_BW20;
if (prCSIData->ucBw == 0)
eModulationType = prCSIData->bIsCck ?
CSI_TYPE_CCK_BW20 : CSI_TYPE_OFDM_BW20;
else if (prCSIData->ucBw == 1)
eModulationType = CSI_TYPE_OFDM_BW40;
else if (prCSIData->ucBw == 2)
eModulationType = CSI_TYPE_OFDM_BW80;
put_unaligned(0xAC, (tmpBuf + i4Pos));
i4Pos++;
/* Just bypass total length feild here and update it in the end */
i4Pos += 2;
put_unaligned(CSI_DATA_VER, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(1, (uint16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
put_unaligned(prCSIData->ucFwVer, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(CSI_DATA_TYPE, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(1, (uint16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
put_unaligned(eModulationType, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(CSI_DATA_TS, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(8, (uint16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
put_unaligned(prCSIData->u8TimeStamp, (uint64_t *) (tmpBuf + i4Pos));
i4Pos += 8;
put_unaligned(CSI_DATA_RSSI, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(1, (uint16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
put_unaligned(prCSIData->cRssi, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(CSI_DATA_SNR, (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(1, (uint16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
put_unaligned(prCSIData->ucSNR, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(CSI_DATA_DBW, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(1, (uint16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
put_unaligned(prCSIData->ucDataBw, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(CSI_DATA_CH_IDX, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(1, (uint16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
put_unaligned(prCSIData->ucPrimaryChIdx, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(CSI_DATA_TA, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(MAC_ADDR_LEN, (uint16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
kalMemCopy((tmpBuf + i4Pos), prCSIData->aucTA, MAC_ADDR_LEN);
i4Pos += MAC_ADDR_LEN;
put_unaligned(CSI_DATA_EXTRA_INFO, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(4, (uint16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
put_unaligned(prCSIData->u4ExtraInfo, (uint32_t *) (tmpBuf + i4Pos));
i4Pos += sizeof(uint32_t);
put_unaligned(CSI_DATA_I, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(u2DataSize, (uint16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
kalMemCopy((tmpBuf + i4Pos), prCSIData->ac2IData, u2DataSize);
i4Pos += u2DataSize;
put_unaligned(CSI_DATA_Q, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(u2DataSize, (uint16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
kalMemCopy((tmpBuf + i4Pos), prCSIData->ac2QData, u2DataSize);
i4Pos += u2DataSize;
if (prCSIInfo->ucValue1[CSI_CONFIG_INFO] & CSI_INFO_RSVD1) {
put_unaligned(CSI_DATA_RSVD1, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(u2Rsvd1Size, (uint16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
kalMemCopy((tmpBuf + i4Pos),
prCSIData->ai4Rsvd1,
u2Rsvd1Size);
i4Pos += u2Rsvd1Size;
put_unaligned(CSI_DATA_RSVD2, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(u2Rsvd1Size, (uint16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
kalMemCopy((tmpBuf + i4Pos),
prCSIData->au4Rsvd2,
u2Rsvd1Size);
i4Pos += u2Rsvd1Size;
put_unaligned(CSI_DATA_RSVD3, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(sizeof(int32_t), (int16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
put_unaligned(prCSIData->i4Rsvd3,
(int32_t *) (tmpBuf + i4Pos));
i4Pos += sizeof(int32_t);
}
if (prCSIInfo->ucValue1[CSI_CONFIG_INFO] & CSI_INFO_RSVD2) {
put_unaligned(CSI_DATA_RSVD4, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(sizeof(uint8_t), (int16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
put_unaligned(prCSIData->ucRsvd4, (uint8_t *) (tmpBuf + i4Pos));
i4Pos += sizeof(uint8_t);
}
put_unaligned(CSI_DATA_TX_IDX, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(sizeof(uint8_t), (int16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
put_unaligned(((uint8_t)GET_CSI_TX_IDX(prCSIData->u4TRxIdx)),
(uint8_t *) (tmpBuf + i4Pos));
i4Pos += sizeof(uint8_t);
put_unaligned(CSI_DATA_RX_IDX, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(sizeof(uint8_t), (int16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
put_unaligned(((uint8_t)GET_CSI_RX_IDX(prCSIData->u4TRxIdx)),
(uint8_t *) (tmpBuf + i4Pos));
i4Pos += sizeof(uint8_t);
put_unaligned(CSI_DATA_FRAME_MODE, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(sizeof(uint8_t), (int16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
put_unaligned(prCSIData->ucRxMode,
(uint8_t *) (tmpBuf + i4Pos));
i4Pos += sizeof(uint8_t);
/* add antenna pattern*/
put_unaligned(CSI_DATA_H_IDX, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(sizeof(uint32_t), (int16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
put_unaligned(prCSIData->Antenna_pattern,
(uint32_t *) (tmpBuf + i4Pos));
i4Pos += sizeof(uint32_t);
put_unaligned(CSI_DATA_RX_RATE, (uint8_t *) (tmpBuf + i4Pos));
i4Pos++;
put_unaligned(sizeof(uint8_t), (int16_t *) (tmpBuf + i4Pos));
i4Pos += 2;
put_unaligned(prCSIData->u2RxRate,
(uint8_t *) (tmpBuf + i4Pos));
i4Pos += sizeof(uint8_t);
/*
* The lengths of magic number (1 byte) and total length (2 bytes)
* fields should not be counted in the total length value
*/
put_unaligned(i4Pos - 3, (uint16_t *) (tmpBuf + 1));
return i4Pos;
}
struct CSI_DATA_T rTmpCSIData;
static ssize_t procCSIDataRead(struct file *filp,
char __user *buf, size_t count, loff_t *f_pos)
{
uint8_t *pucProcBuf = kalMemAlloc(PROC_MAX_BUF_SIZE, VIR_MEM_TYPE);
uint8_t *temp = NULL;
uint32_t u4CopySize = 0;
uint32_t u4StartIdx = 0;
int32_t i4Pos = 0;
int32_t i4Ret = 0;
struct CSI_INFO_T *prCSIInfo = NULL;
if (*f_pos > 0 || buf == NULL || pucProcBuf == NULL)
goto freeBuf;
if (g_prGlueInfo_proc && g_prGlueInfo_proc->prAdapter)
prCSIInfo = &(g_prGlueInfo_proc->prAdapter->rCSIInfo);
else
goto freeBuf;
kalMemZero(pucProcBuf, PROC_MAX_BUF_SIZE);
temp = pucProcBuf;
if (prCSIInfo->bIncomplete == FALSE) {
wait_event_interruptible(prCSIInfo->waitq,
prCSIInfo->u4CSIBufferUsed != 0);
/*
* No older CSI data in buffer waiting for reading out,
* so prepare a new one for reading.
*/
if (wlanPopCSIData(g_prGlueInfo_proc->prAdapter,
&rTmpCSIData))
i4Pos = procCSIDataPrepare(temp,
prCSIInfo, &rTmpCSIData);
/* The frist run of reading the CSI data */
u4StartIdx = 0;
if (i4Pos > count) {
#ifdef CFG_SSVD_SVACE64
u4CopySize = (uint32_t)count;
#else
u4CopySize = count;
#endif
prCSIInfo->u4RemainingDataSize = i4Pos - count;
prCSIInfo->u4CopiedDataSize = count;
prCSIInfo->bIncomplete = TRUE;
} else {
u4CopySize = i4Pos;
}
} else {
/* Reading the remaining CSI data in the buffer */
u4StartIdx = prCSIInfo->u4CopiedDataSize;
if (prCSIInfo->u4RemainingDataSize > count) {
#ifdef CFG_SSVD_SVACE64
u4CopySize = (uint32_t)count;
#else
u4CopySize = count;
#endif
prCSIInfo->u4RemainingDataSize -= count;
prCSIInfo->u4CopiedDataSize += count;
} else {
u4CopySize = prCSIInfo->u4RemainingDataSize;
prCSIInfo->bIncomplete = FALSE;
}
}
if (u4StartIdx >= PROC_MAX_BUF_SIZE ||
(u4StartIdx + u4CopySize) > PROC_MAX_BUF_SIZE ||
copy_to_user(buf, temp + u4StartIdx, u4CopySize)) {
DBGLOG(INIT, ERROR, "[CSI] copy to user failed\n");
i4Ret = -EFAULT;
goto freeBuf;
}
*f_pos += u4CopySize;
DBGLOG(INIT, INFO, "[CSI] u4CopySize=%d\n", u4CopySize);
i4Ret = u4CopySize;
freeBuf:
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return i4Ret;
}
#endif
static ssize_t procDbgLevelRead(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos)
{
uint8_t *pucProcBuf = kalMemAlloc(PROC_MAX_BUF_SIZE, VIR_MEM_TYPE);
uint8_t *temp = NULL;
uint8_t *str = NULL;
uint32_t u4CopySize = 0;
uint16_t i;
uint16_t u2ModuleNum = 0;
uint32_t u4StrLen = 0;
uint32_t u4Level1, u4Level2;
int32_t i4Ret = 0;
/* if *f_ops>0, we should return 0 to make cat command exit */
if (*f_pos > 0 || buf == NULL || pucProcBuf == NULL)
goto freeBuf;
kalMemZero(pucProcBuf, PROC_MAX_BUF_SIZE);
temp = pucProcBuf;
str = "\nTEMP|LOUD|INFO|TRACE | EVENT|STATE|WARN|ERROR\n"
"bit7|bit6|bit5|bit4 | bit3|bit2|bit1|bit0\n\n"
"Usage: Module Index:Module Level, such as 0x00:0xff\n\n"
"Debug Module\tIndex\tLevel\tDebug Module\tIndex\tLevel\n\n";
u4StrLen = kalStrLen(str);
kalStrnCpy(temp, str, u4StrLen + 1);
temp += kalStrLen(temp);
u2ModuleNum =
(sizeof(aucDbModuleName) /
PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN) & 0xfe;
for (i = 0; i < u2ModuleNum; i += 2) {
wlanGetDriverDbgLevel(i, &u4Level1);
wlanGetDriverDbgLevel(i + 1, &u4Level2);
SNPRINTF(temp, PROC_MAX_BUF_SIZE - kalStrLen(pucProcBuf),
("DBG_%s_IDX\t(0x%02x):\t0x%02x\t"
"DBG_%s_IDX\t(0x%02x):\t0x%02x\n",
&aucDbModuleName[i][0], i, (uint8_t) u4Level1,
&aucDbModuleName[i + 1][0], i + 1,
(uint8_t) u4Level2));
}
if ((sizeof(aucDbModuleName) /
PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN) & 0x1) {
wlanGetDriverDbgLevel(u2ModuleNum, &u4Level1);
SNPRINTF(temp, PROC_MAX_BUF_SIZE - kalStrLen(pucProcBuf),
("DBG_%s_IDX\t(0x%02x):\t0x%02x\n",
&aucDbModuleName[u2ModuleNum][0], u2ModuleNum,
(uint8_t) u4Level1));
}
u4CopySize = kalStrLen(pucProcBuf);
if (u4CopySize > count)
u4CopySize = count;
if (copy_to_user(buf, pucProcBuf, u4CopySize)) {
DBGLOG(INIT, ERROR, "copy to user failed\n");
i4Ret = -EFAULT;
goto freeBuf;
}
*f_pos += u4CopySize;
i4Ret = u4CopySize;
freeBuf:
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return i4Ret;
}
#if CFG_SUPPORT_CSI
static const struct file_operations csidata_ops = {
.owner = THIS_MODULE,
.read = procCSIDataRead,
.open = procCSIDataOpen,
.release = procCSIDataRelease,
};
#endif
#if WLAN_INCLUDE_PROC
#if CFG_SUPPORT_EASY_DEBUG
static void *procEfuseDump_start(struct seq_file *s, loff_t *pos)
{
static unsigned long counter;
if (*pos == 0)
counter = *pos; /* read file init */
if (counter >= EFUSE_ADDR_MAX)
return NULL;
return &counter;
}
static void *procEfuseDump_next(struct seq_file *s, void *v, loff_t *pos)
{
unsigned long *tmp_v = (unsigned long *)v;
(*tmp_v) += EFUSE_BLOCK_SIZE;
if (*tmp_v >= EFUSE_ADDR_MAX)
return NULL;
return tmp_v;
}
static void procEfuseDump_stop(struct seq_file *s, void *v)
{
/* nothing to do, we use a static value in start() */
}
static int procEfuseDump_show(struct seq_file *s, void *v)
{
uint32_t rStatus = WLAN_STATUS_SUCCESS;
uint32_t u4BufLen = 0;
struct GLUE_INFO *prGlueInfo;
uint32_t idx_addr, idx_value;
struct PARAM_CUSTOM_ACCESS_EFUSE rAccessEfuseInfo = { };
prGlueInfo = g_prGlueInfo_proc;
#if (CFG_EEPROM_PAGE_ACCESS == 1)
ASSERT(prGlueInfo);
if (!prGlueInfo->prAdapter) {
seq_puts(s, "prAdapter is null\n");
return -EPERM;
}
if (prGlueInfo->prAdapter->chip_info &&
!prGlueInfo->prAdapter->chip_info->is_support_efuse) {
seq_puts(s, "efuse ops is invalid\n");
return -EPERM; /* return negative value to stop read process */
}
idx_addr = *(loff_t *) v;
rAccessEfuseInfo.u4Address =
(idx_addr / EFUSE_BLOCK_SIZE) * EFUSE_BLOCK_SIZE;
rStatus = kalIoctl(prGlueInfo,
wlanoidQueryProcessAccessEfuseRead,
&rAccessEfuseInfo,
sizeof(struct PARAM_CUSTOM_ACCESS_EFUSE), TRUE, TRUE,
TRUE, &u4BufLen);
if (rStatus != WLAN_STATUS_SUCCESS) {
seq_printf(s, "efuse read fail (0x%03X)\n",
rAccessEfuseInfo.u4Address);
return 0;
}
for (idx_value = 0; idx_value < EFUSE_BLOCK_SIZE; idx_value++)
seq_printf(s, "0x%03X=0x%02X\n",
rAccessEfuseInfo.u4Address + idx_value,
prGlueInfo->prAdapter->aucEepromVaule[idx_value]);
return 0;
#else
seq_puts(s, "efuse ops is invalid\n");
return -EPERM; /* return negative value to stop read process */
#endif
}
static int procEfuseDumpOpen(struct inode *inode, struct file *file)
{
static const struct seq_operations procEfuseDump_ops = {
.start = procEfuseDump_start,
.next = procEfuseDump_next,
.stop = procEfuseDump_stop,
.show = procEfuseDump_show
};
return seq_open(file, &procEfuseDump_ops);
}
static ssize_t procCfgRead(struct file *filp, char __user *buf, size_t count,
loff_t *f_pos)
{
uint8_t *pucProcBuf = kalMemAlloc(PROC_MAX_BUF_SIZE, VIR_MEM_TYPE);
uint8_t *temp = NULL;
uint8_t *str = NULL;
uint8_t *str2 = "\nERROR DUMP CONFIGURATION:\n";
uint32_t u4CopySize = 0;
uint32_t i;
uint32_t u4StrLen = 0;
int32_t i4Ret = 0;
#define BUFFER_RESERVE_BYTE 50
struct GLUE_INFO *prGlueInfo;
struct WLAN_CFG_ENTRY *prWlanCfgEntry;
struct ADAPTER *prAdapter;
prGlueInfo = *((struct GLUE_INFO **)netdev_priv(gPrDev));
if (!prGlueInfo) {
DBGLOG(INIT, ERROR, "procCfgRead prGlueInfo is NULL????\n");
goto freeBuf;
}
prAdapter = prGlueInfo->prAdapter;
if (!prAdapter) {
DBGLOG(INIT, ERROR, "procCfgRead prAdapter is NULL????\n");
goto freeBuf;
}
/* if *f_ops>0, we should return 0 to make cat command exit */
if (*f_pos > 0 || buf == NULL || pucProcBuf == NULL)
goto freeBuf;
kalMemZero(pucProcBuf, PROC_MAX_BUF_SIZE);
temp = pucProcBuf;
str = "\nDUMP CONFIGURATION :\n"
"<KEY|VALUE> OR <D:KEY|VALUE>\n"
"'D': driver part current setting\n"
"===================================\n";
u4StrLen = kalStrLen(str);
kalStrnCpy(temp, str, u4StrLen + 1);
temp += kalStrLen(temp);
for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) {
prWlanCfgEntry = wlanCfgGetEntryByIndex(prAdapter, i, 0);
if ((!prWlanCfgEntry) || (prWlanCfgEntry->aucKey[0] == '\0'))
break;
SNPRINTF(temp, PROC_MAX_BUF_SIZE - kalStrLen(pucProcBuf),
("%s|%s\n", prWlanCfgEntry->aucKey,
prWlanCfgEntry->aucValue));
if ((temp - pucProcBuf) != kalStrLen(pucProcBuf)) {
DBGLOG(INIT, ERROR,
"Dump configuration error: temp offset=%d, buf length=%u, key[%d]=[%u], val[%d]=[%u]\n",
(int)(temp - pucProcBuf),
(uint32_t)kalStrLen(pucProcBuf),
WLAN_CFG_VALUE_LEN_MAX,
(uint32_t)prWlanCfgEntry->aucKey[
WLAN_CFG_VALUE_LEN_MAX - 1],
WLAN_CFG_VALUE_LEN_MAX,
(uint32_t)prWlanCfgEntry->aucValue[
WLAN_CFG_VALUE_LEN_MAX - 1]);
kalMemSet(pucProcBuf, ' ', u4StrLen);
kalStrnCpy(pucProcBuf, str2, kalStrLen(str2) + 1);
goto procCfgReadLabel;
}
if (kalStrLen(pucProcBuf) >
(PROC_MAX_BUF_SIZE - BUFFER_RESERVE_BYTE))
break;
}
for (i = 0; i < WLAN_CFG_REC_ENTRY_NUM_MAX; i++) {
prWlanCfgEntry = wlanCfgGetEntryByIndex(prAdapter, i, 1);
if ((!prWlanCfgEntry) || (prWlanCfgEntry->aucKey[0] == '\0'))
break;
SNPRINTF(temp, PROC_MAX_BUF_SIZE - kalStrLen(pucProcBuf),
("D:%s|%s\n", prWlanCfgEntry->aucKey,
prWlanCfgEntry->aucValue));
if ((temp - pucProcBuf) != kalStrLen(pucProcBuf)) {
DBGLOG(INIT, ERROR,
"D:Dump configuration error: temp offset=%d, buf length=%u, key[%d]=[%u], val[%d]=[%u]\n",
(int)(temp - pucProcBuf),
(uint32_t)kalStrLen(pucProcBuf),
WLAN_CFG_VALUE_LEN_MAX,
(uint32_t)prWlanCfgEntry->aucKey[
WLAN_CFG_VALUE_LEN_MAX - 1],
WLAN_CFG_VALUE_LEN_MAX,
(uint32_t)prWlanCfgEntry->aucValue[
WLAN_CFG_VALUE_LEN_MAX - 1]);
kalMemSet(pucProcBuf, ' ', u4StrLen);
kalStrnCpy(pucProcBuf, str2, kalStrLen(str2) + 1);
goto procCfgReadLabel;
}
if (kalStrLen(pucProcBuf) >
(PROC_MAX_BUF_SIZE - BUFFER_RESERVE_BYTE))
break;
}
procCfgReadLabel:
u4CopySize = kalStrLen(pucProcBuf);
if (u4CopySize > count)
u4CopySize = count;
if (copy_to_user(buf, pucProcBuf, u4CopySize)) {
DBGLOG(INIT, ERROR, "copy to user failed\n");
i4Ret = -EFAULT;
goto freeBuf;
}
*f_pos += u4CopySize;
i4Ret = u4CopySize;
freeBuf:
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return i4Ret;
}
static ssize_t procCfgWrite(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
uint8_t *pucProcBuf = kalMemAlloc(PROC_MAX_BUF_SIZE, VIR_MEM_TYPE);
int32_t i4CopySize = PROC_MAX_BUF_SIZE-8;
struct GLUE_INFO *prGlueInfo;
uint8_t *pucTmp;
int32_t i4Ret = 0;
if (count <= 0) {
DBGLOG(INIT, ERROR, "Wrong buffer size.\n");
i4Ret = -EFAULT;
goto freeBuf;
}
if (buffer == NULL || pucProcBuf == NULL)
goto freeBuf;
kalMemSet(pucProcBuf, 0, i4CopySize);
i4CopySize = (count < i4CopySize) ? count : (i4CopySize - 1);
pucTmp = pucProcBuf;
SNPRINTF(pucTmp, PROC_MAX_BUF_SIZE - kalStrLen(pucProcBuf),
("%s ", "set_cfg"));
if ((i4CopySize < 0) || (copy_from_user(pucTmp, buffer, i4CopySize))) {
DBGLOG(INIT, ERROR, "error of copy from user\n");
i4Ret = -EFAULT;
goto freeBuf;
}
pucProcBuf[i4CopySize + 8] = '\0';
prGlueInfo = g_prGlueInfo_proc;
priv_driver_set_cfg(prGlueInfo->prDevHandler, pucProcBuf,
kalStrLen(pucProcBuf));
i4Ret = i4CopySize;
freeBuf:
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return i4Ret;
}
static ssize_t procDriverCmdRead(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos)
{
/* DriverCmd read should only be executed right after
* a DriverCmd write because content buffer 'g_aucProcBuf'
* is a global buffer for all proc command, otherwise ,
* the content could be overwrite by other proc command
*/
uint32_t u4CopySize = 0;
/* if *f_ops>0, we should return 0 to make cat command exit */
if (*f_pos > 0 || buf == NULL)
return 0;
if (g_NextDriverReadLen > 0) /* Detect content to show */
u4CopySize = g_NextDriverReadLen;
if (u4CopySize > count)
u4CopySize = count;
if (copy_to_user(buf, g_aucProcBuf, u4CopySize)) {
DBGLOG(INIT, ERROR, "copy to user failed\n");
return -EFAULT;
}
g_NextDriverReadLen = 0;
*f_pos += u4CopySize;
return (ssize_t) u4CopySize;
}
static ssize_t procDriverCmdWrite(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
uint32_t u4CopySize = sizeof(g_aucProcBuf);
struct GLUE_INFO *prGlueInfo;
kalMemSet(g_aucProcBuf, 0, u4CopySize);
u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1);
if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) {
DBGLOG(INIT, ERROR, "error of copy from user\n");
return -EFAULT;
}
g_aucProcBuf[u4CopySize] = '\0';
prGlueInfo = g_prGlueInfo_proc;
/* if g_u4NextDriverReadLen >0,
* the content for next DriverCmdRead will be
* in : g_aucProcBuf with length : g_u4NextDriverReadLen
*/
g_NextDriverReadLen =
priv_driver_cmds(prGlueInfo->prDevHandler, g_aucProcBuf,
sizeof(g_aucProcBuf));
return count;
}
#endif
#endif
static ssize_t procDbgLevelWrite(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
uint32_t u4NewDbgModule, u4NewDbgLevel;
uint8_t *pucProcBuf = kalMemAlloc(PROC_MAX_BUF_SIZE, VIR_MEM_TYPE);
uint8_t *temp = NULL;
uint32_t u4CopySize = PROC_MAX_BUF_SIZE;
int32_t i4Ret = 0;
if (buffer == NULL || pucProcBuf == NULL)
goto freeBuf;
kalMemZero(pucProcBuf, PROC_MAX_BUF_SIZE);
temp = pucProcBuf;
u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1);
if (copy_from_user(pucProcBuf, buffer, u4CopySize)) {
DBGLOG(INIT, ERROR, "error of copy from user\n");
i4Ret = -EFAULT;
goto freeBuf;
}
pucProcBuf[u4CopySize] = '\0';
/*add chip reset cmd for manual test*/
#if CFG_CHIP_RESET_SUPPORT
if (temp[0] == 'R') {
DBGLOG(INIT, ERROR, "WIFI trigger reset!!\n");
glGetRstReason(RST_CMD_TRIGGER);
GL_RESET_TRIGGER(g_prGlueInfo_proc->prAdapter,
RST_FLAG_CHIP_RESET);
temp[0] = 'X';
}
#endif
while (temp) {
if (sscanf(temp,
"0x%x:0x%x", &u4NewDbgModule, &u4NewDbgLevel) != 2) {
DBGLOG(INIT, INFO,
"debug module and debug level should be one byte in length\n");
break;
}
if (u4NewDbgModule == 0xFF) {
wlanSetDriverDbgLevel(DBG_ALL_MODULE_IDX,
(u4NewDbgLevel & DBG_CLASS_MASK));
break;
}
if (u4NewDbgModule >= DBG_MODULE_NUM) {
DBGLOG(INIT, INFO,
"debug module index should less than %d\n",
DBG_MODULE_NUM);
break;
}
wlanSetDriverDbgLevel(u4NewDbgModule,
(u4NewDbgLevel & DBG_CLASS_MASK));
temp = kalStrChr(temp, ',');
if (!temp)
break;
temp++; /* skip ',' */
}
i4Ret = u4CopySize;
freeBuf:
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return i4Ret;
}
#define TXPWR_TABLE_ENTRY(_siso_mcs, _cdd_mcs, _mimo_mcs, _idx) \
{ \
.mcs[STREAM_SISO] = _siso_mcs, \
.mcs[STREAM_CDD] = _cdd_mcs, \
.mcs[STREAM_MIMO] = _mimo_mcs, \
.idx = (_idx), \
}
static struct txpwr_table_entry dsss[] = {
TXPWR_TABLE_ENTRY("DSSS1", "", "", MODULATION_SYSTEM_CCK_1M),
TXPWR_TABLE_ENTRY("DSSS2", "", "", MODULATION_SYSTEM_CCK_2M),
TXPWR_TABLE_ENTRY("CCK5", "", "", MODULATION_SYSTEM_CCK_5M),
TXPWR_TABLE_ENTRY("CCK11", "", "", MODULATION_SYSTEM_CCK_11M),
};
static struct txpwr_table_entry ofdm[] = {
TXPWR_TABLE_ENTRY("OFDM6", "OFDM6", "", MODULATION_SYSTEM_OFDM_6M),
TXPWR_TABLE_ENTRY("OFDM9", "OFDM9", "", MODULATION_SYSTEM_OFDM_9M),
TXPWR_TABLE_ENTRY("OFDM12", "OFDM12", "", MODULATION_SYSTEM_OFDM_12M),
TXPWR_TABLE_ENTRY("OFDM18", "OFDM18", "", MODULATION_SYSTEM_OFDM_18M),
TXPWR_TABLE_ENTRY("OFDM24", "OFDM24", "", MODULATION_SYSTEM_OFDM_24M),
TXPWR_TABLE_ENTRY("OFDM36", "OFDM36", "", MODULATION_SYSTEM_OFDM_36M),
TXPWR_TABLE_ENTRY("OFDM48", "OFDM48", "", MODULATION_SYSTEM_OFDM_48M),
TXPWR_TABLE_ENTRY("OFDM54", "OFDM54", "", MODULATION_SYSTEM_OFDM_54M),
};
static struct txpwr_table_entry ht20[] = {
TXPWR_TABLE_ENTRY("MCS0", "MCS0", "MCS8", MODULATION_SYSTEM_HT20_MCS0),
TXPWR_TABLE_ENTRY("MCS1", "MCS1", "MCS9", MODULATION_SYSTEM_HT20_MCS1),
TXPWR_TABLE_ENTRY("MCS2", "MCS2", "MCS10", MODULATION_SYSTEM_HT20_MCS2),
TXPWR_TABLE_ENTRY("MCS3", "MCS3", "MCS11", MODULATION_SYSTEM_HT20_MCS3),
TXPWR_TABLE_ENTRY("MCS4", "MCS4", "MCS12", MODULATION_SYSTEM_HT20_MCS4),
TXPWR_TABLE_ENTRY("MCS5", "MCS5", "MCS13", MODULATION_SYSTEM_HT20_MCS5),
TXPWR_TABLE_ENTRY("MCS6", "MCS6", "MCS14", MODULATION_SYSTEM_HT20_MCS6),
TXPWR_TABLE_ENTRY("MCS7", "MCS7", "MCS15", MODULATION_SYSTEM_HT20_MCS7),
};
static struct txpwr_table_entry ht40[] = {
TXPWR_TABLE_ENTRY("MCS0", "MCS0", "MCS8", MODULATION_SYSTEM_HT40_MCS0),
TXPWR_TABLE_ENTRY("MCS1", "MCS1", "MCS9", MODULATION_SYSTEM_HT40_MCS1),
TXPWR_TABLE_ENTRY("MCS2", "MCS2", "MCS10", MODULATION_SYSTEM_HT40_MCS2),
TXPWR_TABLE_ENTRY("MCS3", "MCS3", "MCS11", MODULATION_SYSTEM_HT40_MCS3),
TXPWR_TABLE_ENTRY("MCS4", "MCS4", "MCS12", MODULATION_SYSTEM_HT40_MCS4),
TXPWR_TABLE_ENTRY("MCS5", "MCS5", "MCS13", MODULATION_SYSTEM_HT40_MCS5),
TXPWR_TABLE_ENTRY("MCS6", "MCS6", "MCS14", MODULATION_SYSTEM_HT40_MCS6),
TXPWR_TABLE_ENTRY("MCS7", "MCS7", "MCS15", MODULATION_SYSTEM_HT40_MCS7),
TXPWR_TABLE_ENTRY("MCS32", "MCS32", "MCS32",
MODULATION_SYSTEM_HT40_MCS32),
};
static struct txpwr_table_entry vht[] = {
TXPWR_TABLE_ENTRY("MCS0", "MCS0", "MCS0", MODULATION_SYSTEM_VHT20_MCS0),
TXPWR_TABLE_ENTRY("MCS1", "MCS1", "MCS1", MODULATION_SYSTEM_VHT20_MCS1),
TXPWR_TABLE_ENTRY("MCS2", "MCS2", "MCS2", MODULATION_SYSTEM_VHT20_MCS2),
TXPWR_TABLE_ENTRY("MCS3", "MCS3", "MCS3", MODULATION_SYSTEM_VHT20_MCS3),
TXPWR_TABLE_ENTRY("MCS4", "MCS4", "MCS4", MODULATION_SYSTEM_VHT20_MCS4),
TXPWR_TABLE_ENTRY("MCS5", "MCS5", "MCS5", MODULATION_SYSTEM_VHT20_MCS5),
TXPWR_TABLE_ENTRY("MCS6", "MCS6", "MCS6", MODULATION_SYSTEM_VHT20_MCS6),
TXPWR_TABLE_ENTRY("MCS7", "MCS7", "MCS7", MODULATION_SYSTEM_VHT20_MCS7),
TXPWR_TABLE_ENTRY("MCS8", "MCS8", "MCS8", MODULATION_SYSTEM_VHT20_MCS8),
TXPWR_TABLE_ENTRY("MCS9", "MCS9", "MCS9", MODULATION_SYSTEM_VHT20_MCS9),
};
static struct txpwr_table txpwr_tables[] = {
{"Legacy", dsss, ARRAY_SIZE(dsss)},
{"11g", ofdm, ARRAY_SIZE(ofdm)},
{"11a", ofdm, ARRAY_SIZE(ofdm)},
{"HT20", ht20, ARRAY_SIZE(ht20)},
{"HT40", ht40, ARRAY_SIZE(ht40)},
{"VHT20", vht, ARRAY_SIZE(vht)},
{"VHT40", vht, ARRAY_SIZE(vht)},
{"VHT80", vht, ARRAY_SIZE(vht)},
{"VHT160", vht, ARRAY_SIZE(vht)},
};
#define TMP_SZ (512)
#define CDD_PWR_OFFSET (6)
#define TXPWR_DUMP_SZ (8192)
void print_txpwr_tbl(struct txpwr_table *txpwr_tbl, unsigned char ch,
unsigned char *tx_pwr[], char pwr_offset[],
char *stream_buf[], unsigned int stream_pos[])
{
struct txpwr_table_entry *tmp_tbl = txpwr_tbl->tables;
unsigned int idx, pwr_idx, stream_idx;
char pwr[TXPWR_TBL_NUM] = {0}, tmp_pwr = 0;
char prefix[5], tmp[4];
char *buf = NULL;
unsigned int *pos = NULL;
int i;
for (i = 0; i < txpwr_tbl->n_tables; i++) {
idx = tmp_tbl[i].idx;
for (pwr_idx = 0; pwr_idx < TXPWR_TBL_NUM; pwr_idx++) {
if (!tx_pwr[pwr_idx]) {
DBGLOG(REQ, WARN,
"Power table[%d] is NULL\n", pwr_idx);
return;
}
pwr[pwr_idx] = tx_pwr[pwr_idx][idx] +
pwr_offset[pwr_idx];
pwr[pwr_idx] = (pwr[pwr_idx] > MAX_TX_POWER) ?
MAX_TX_POWER : pwr[pwr_idx];
}
for (stream_idx = 0; stream_idx < STREAM_NUM; stream_idx++) {
buf = stream_buf[stream_idx];
pos = &stream_pos[stream_idx];
if (tmp_tbl[i].mcs[stream_idx][0] == '\0')
continue;
switch (stream_idx) {
case STREAM_SISO:
kalStrnCpy(prefix, "siso", sizeof(prefix));
break;
case STREAM_CDD:
kalStrnCpy(prefix, "cdd", sizeof(prefix));
break;
case STREAM_MIMO:
kalStrnCpy(prefix, "mimo", sizeof(prefix));
break;
}
*pos += kalScnprintf(buf + *pos, TMP_SZ - *pos,
"%s, %d, %s, %s, ",
prefix, ch,
txpwr_tbl->phy_mode,
tmp_tbl[i].mcs[stream_idx]);
for (pwr_idx = 0; pwr_idx < TXPWR_TBL_NUM; pwr_idx++) {
tmp_pwr = pwr[pwr_idx];
tmp_pwr = (tmp_pwr > 0) ? tmp_pwr : 0;
if (pwr_idx + 1 == TXPWR_TBL_NUM)
kalStrnCpy(tmp, "\n", sizeof(tmp));
else
kalStrnCpy(tmp, ", ", sizeof(tmp));
*pos += kalScnprintf(buf + *pos, TMP_SZ - *pos,
"%d.%d%s",
tmp_pwr / 2,
tmp_pwr % 2 * 5,
tmp);
}
}
}
}
char *g_txpwr_tbl_read_buffer;
char *g_txpwr_tbl_read_buffer_head;
unsigned int g_txpwr_tbl_read_residual;
static ssize_t procGetTxpwrTblRead(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos)
{
struct GLUE_INFO *prGlueInfo = NULL;
struct ADAPTER *prAdapter = NULL;
struct BSS_INFO *prBssInfo = NULL;
unsigned char ucBssIndex;
struct NETDEV_PRIVATE_GLUE_INFO *prNetDevPrivate = NULL;
uint32_t status;
struct PARAM_CMD_GET_TXPWR_TBL pwr_tbl;
struct POWER_LIMIT *tx_pwr_tbl = pwr_tbl.tx_pwr_tbl;
char *buffer;
unsigned int pos = 0, buf_len = TXPWR_DUMP_SZ, oid_len;
unsigned char i, j;
char *stream_buf[STREAM_NUM] = {NULL};
unsigned int stream_pos[STREAM_NUM] = {0};
unsigned char *tx_pwr[TXPWR_TBL_NUM] = {NULL};
char pwr_offset[TXPWR_TBL_NUM] = {0};
int ret;
if (*f_pos > 0) { /* re-entry */
pos = g_txpwr_tbl_read_residual;
buffer = g_txpwr_tbl_read_buffer;
goto next_entry;
}
prGlueInfo = g_prGlueInfo_proc;
if (!prGlueInfo)
return -EFAULT;
prAdapter = prGlueInfo->prAdapter;
prNetDevPrivate =
(struct NETDEV_PRIVATE_GLUE_INFO *) netdev_priv(gPrDev);
if (prNetDevPrivate->prGlueInfo != prGlueInfo)
return -EFAULT;
ucBssIndex = prNetDevPrivate->ucBssIdx;
prBssInfo = prAdapter->aprBssInfo[ucBssIndex];
if (!prBssInfo)
return -EFAULT;
kalMemZero(&pwr_tbl, sizeof(pwr_tbl));
/* MT7663 no DBDC design */
#if 0
if (prAdapter->rWifiVar.fgDbDcModeEn)
pwr_tbl.ucDbdcIdx = prBssInfo->eDBDCBand;
else
pwr_tbl.ucDbdcIdx = ENUM_BAND_0;
#endif
status = kalIoctl(prGlueInfo,
wlanoidGetTxPwrTbl,
&pwr_tbl,
sizeof(pwr_tbl), TRUE, FALSE, TRUE, &oid_len);
if (status != WLAN_STATUS_SUCCESS) {
DBGLOG(REQ, WARN, "Query Tx Power Table fail\n");
return -EINVAL;
}
buffer = (char *) kalMemAlloc(buf_len, VIR_MEM_TYPE);
if (!buffer)
return -ENOMEM;
g_txpwr_tbl_read_buffer = buffer;
g_txpwr_tbl_read_buffer_head = buffer;
for (i = 0; i < STREAM_NUM; i++) {
stream_buf[i] = (char *) kalMemAlloc(TMP_SZ, VIR_MEM_TYPE);
if (!stream_buf[i]) {
ret = -ENOMEM;
goto out;
}
}
pos = kalScnprintf(buffer, buf_len,
"\n%s",
"spatial stream, Channel, bw, modulation, ");
pos += kalScnprintf(buffer + pos, buf_len - pos,
"%s\n",
"regulatory limit, board limit, target power");
for (i = 0; i < ARRAY_SIZE(txpwr_tables); i++) {
for (j = 0; j < STREAM_NUM; j++) {
kalMemZero(stream_buf[j], TMP_SZ);
stream_pos[j] = 0;
}
for (j = 0; j < TXPWR_TBL_NUM; j++) {
tx_pwr[j] = NULL;
pwr_offset[j] = 0;
}
switch (i) {
case DSSS:
if (pwr_tbl.ucCenterCh > 14)
continue;
for (j = 0; j < TXPWR_TBL_NUM; j++)
tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_dsss;
break;
case OFDM_24G:
if (pwr_tbl.ucCenterCh > 14)
continue;
for (j = 0; j < TXPWR_TBL_NUM; j++)
tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_ofdm;
break;
case OFDM_5G:
if (pwr_tbl.ucCenterCh <= 14)
continue;
for (j = 0; j < TXPWR_TBL_NUM; j++)
tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_ofdm;
break;
case HT20:
for (j = 0; j < TXPWR_TBL_NUM; j++)
tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_ht20;
break;
case HT40:
for (j = 0; j < TXPWR_TBL_NUM; j++)
tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_ht40;
break;
case VHT20:
if (pwr_tbl.ucCenterCh <= 14)
continue;
for (j = 0; j < TXPWR_TBL_NUM; j++)
tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_vht20;
break;
#if 0
case VHT40:
case VHT80:
if (pwr_tbl.ucCenterCh <= 14)
continue;
offset = (i == VHT40) ?
PWR_Vht40_OFFSET : PWR_Vht80_OFFSET;
for (j = 0; j < TXPWR_TBL_NUM; j++) {
tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_vht20;
pwr_offset[j] =
tx_pwr_tbl[j].tx_pwr_vht_OFST[offset];
/* Covert 7bit 2'complement value to 8bit */
pwr_offset[j] |= (pwr_offset[j] & BIT(6)) ?
BIT(7) : 0;
}
break;
#else
case VHT40:
if (pwr_tbl.ucCenterCh <= 14)
continue;
for (j = 0; j < TXPWR_TBL_NUM; j++)
tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_vht40;
break;
case VHT80:
if (pwr_tbl.ucCenterCh <= 14)
continue;
for (j = 0; j < TXPWR_TBL_NUM; j++)
tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_vht80;
break;
case VHT160:
if (pwr_tbl.ucCenterCh <= 14)
continue;
for (j = 0; j < TXPWR_TBL_NUM; j++)
tx_pwr[j] = tx_pwr_tbl[j].tx_pwr_vht160;
break;
#endif
default:
break;
}
print_txpwr_tbl(&txpwr_tables[i], pwr_tbl.ucCenterCh,
tx_pwr, pwr_offset,
stream_buf, stream_pos);
for (j = 0; j < STREAM_NUM; j++) {
pos += kalScnprintf(buffer + pos, buf_len - pos,
"%s",
stream_buf[j]);
}
}
g_txpwr_tbl_read_residual = pos;
next_entry:
if (pos > count)
pos = count;
if (copy_to_user(buf, buffer, pos)) {
DBGLOG(INIT, ERROR, "copy to user failed\n");
ret = -EFAULT;
goto out;
}
g_txpwr_tbl_read_buffer += pos;
g_txpwr_tbl_read_residual -= pos;
*f_pos += pos;
ret = pos;
out:
for (i = 0; i < STREAM_NUM; i++) {
if (stream_buf[i])
kalMemFree(stream_buf[i], VIR_MEM_TYPE, TMP_SZ);
}
if (ret == 0 || ret == -ENOMEM) {
if (g_txpwr_tbl_read_buffer_head)
kalMemFree(g_txpwr_tbl_read_buffer_head,
VIR_MEM_TYPE, buf_len);
g_txpwr_tbl_read_buffer = NULL;
g_txpwr_tbl_read_buffer_head = NULL;
g_txpwr_tbl_read_residual = 0;
}
return ret;
}
#ifdef CFG_GET_TEMPURATURE
static ssize_t proc_get_temperature(struct file *filp,
char __user *buf,
size_t count,
loff_t *f_pos)
{
struct GLUE_INFO *prGlueInfo = NULL;
unsigned int pos = 0, buf_len = 128, oid_len;
char *buffer;
int temperature = 0;
uint32_t rStatus = WLAN_STATUS_SUCCESS;
if (*f_pos > 0)
return 0;
prGlueInfo = g_prGlueInfo_proc;
if (!prGlueInfo)
return -EFAULT;
buffer = (char *) kalMemAlloc(buf_len, VIR_MEM_TYPE);
if (!buffer)
return -ENOMEM;
rStatus = kalIoctl(prGlueInfo,
wlanoidGetTemperature, &temperature,
sizeof(temperature), TRUE, TRUE, TRUE, &oid_len);
pos = kalScnprintf(buffer, buf_len, "Temperature = %d\n", temperature);
if (copy_to_user(buf, buffer, pos)) {
DBGLOG(INIT, ERROR, "copy to user failed\n");
kalMemFree(buffer, VIR_MEM_TYPE, buf_len);
return -EFAULT;
}
*f_pos += pos;
kalMemFree(buffer, VIR_MEM_TYPE, buf_len);
return pos;
}
#endif
#if CFG_DISCONN_DEBUG_FEATURE
static int32_t parseTxRateInfo(IN char *pcBuffer, IN int i4Size,
IN struct TX_VECTOR_BBP_LATCH *prTxV)
{
uint8_t rate, txmode, frmode, sgi, ldpc, nsts, stbc;
int8_t txpwr;
int32_t i4BytesWritten = 0;
rate = TX_VECTOR_GET_TX_RATE(prTxV);
txmode = TX_VECTOR_GET_TX_MODE(prTxV);
frmode = TX_VECTOR_GET_TX_FRMODE(prTxV);
nsts = TX_VECTOR_GET_TX_NSTS(prTxV) + 1;
sgi = TX_VECTOR_GET_TX_SGI(prTxV);
ldpc = TX_VECTOR_GET_TX_LDPC(prTxV);
stbc = TX_VECTOR_GET_TX_STBC(prTxV);
txpwr = TX_VECTOR_GET_TX_PWR(prTxV);
if (prTxV->u4TxVector1 == 0xFFFFFFFF) {
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"%-26s%s%s\n", "Last TX Rate", " = ", "N/A");
} else {
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"%-26s%s", "Last TX Rate", " = ");
if (txmode == TX_RATE_MODE_CCK)
i4BytesWritten += kalScnprintf(
pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"%s, ", rate < 4 ? HW_TX_RATE_CCK_STR[rate] :
HW_TX_RATE_CCK_STR[4]);
else if (txmode == TX_RATE_MODE_OFDM)
i4BytesWritten += kalScnprintf(
pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"%s, ", hw_rate_ofdm_str(rate));
else if ((txmode == TX_RATE_MODE_HTMIX) ||
(txmode == TX_RATE_MODE_HTGF))
i4BytesWritten += kalScnprintf(
pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"MCS%d, ", rate);
else
i4BytesWritten += kalScnprintf(
pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"NSS%d_MCS%d, ", nsts, rate);
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten, "%s, ",
frmode < 4 ? HW_TX_RATE_BW[frmode] : HW_TX_RATE_BW[4]);
if (txmode == TX_RATE_MODE_CCK)
i4BytesWritten += kalScnprintf(
pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"%s, ", rate < 4 ? "LP" : "SP");
else if (txmode == TX_RATE_MODE_OFDM)
;
else
i4BytesWritten += kalScnprintf(
pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"%s, ", sgi == 0 ? "LGI" : "SGI");
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten, "%s%s%s\n",
txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5],
stbc ? ", STBC, " : ", ", ldpc == 0 ? "BCC" : "LDPC");
}
return i4BytesWritten;
}
static int32_t parseRxRateInfo(IN char *pcBuffer, IN int i4Size,
IN struct STA_RECORD *prStaRec)
{
uint32_t txmode, rate, frmode, sgi, nsts, ldpc, stbc, groupid, mu;
int32_t i4BytesWritten = 0;
uint32_t u4RxVector0 = 0, u4RxVector1 = 0;
u4RxVector0 = prStaRec->u4RxVector0;
u4RxVector1 = prStaRec->u4RxVector1;
txmode = (u4RxVector0 & RX_VT_RX_MODE_MASK) >> RX_VT_RX_MODE_OFFSET;
rate = (u4RxVector0 & RX_VT_RX_RATE_MASK) >> RX_VT_RX_RATE_OFFSET;
frmode = (u4RxVector0 & RX_VT_FR_MODE_MASK) >> RX_VT_FR_MODE_OFFSET;
nsts = ((u4RxVector1 & RX_VT_NSTS_MASK) >> RX_VT_NSTS_OFFSET);
stbc = (u4RxVector0 & RX_VT_STBC_MASK) >> RX_VT_STBC_OFFSET;
sgi = u4RxVector0 & RX_VT_SHORT_GI;
ldpc = u4RxVector0 & RX_VT_LDPC;
groupid = (u4RxVector1 & RX_VT_GROUP_ID_MASK) >> RX_VT_GROUP_ID_OFFSET;
if (groupid && groupid != 63) {
mu = 1;
} else {
mu = 0;
nsts += 1;
}
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten, "%-26s%s", "Last RX Rate", " = ");
if (txmode == TX_RATE_MODE_CCK)
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten, "%s, ",
rate < 4 ? HW_TX_RATE_CCK_STR[rate] :
HW_TX_RATE_CCK_STR[4]);
else if (txmode == TX_RATE_MODE_OFDM)
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten, "%s, ",
hw_rate_ofdm_str(rate));
else if ((txmode == TX_RATE_MODE_HTMIX) ||
(txmode == TX_RATE_MODE_HTGF))
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten, "MCS%d, ", rate);
else
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten, "NSS%d_MCS%d, ",
nsts, rate);
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten, "%s, ",
frmode < 4 ? HW_TX_RATE_BW[frmode] : HW_TX_RATE_BW[4]);
if (txmode == TX_RATE_MODE_CCK)
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten, "%s, ",
rate < 4 ? "LP" : "SP");
else if (txmode == TX_RATE_MODE_OFDM)
;
else
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten, "%s, ",
sgi == 0 ? "LGI" : "SGI");
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten, "%s", stbc == 0 ? "" : "STBC, ");
if (mu) {
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten, "%s, %s, %s (%d)\n",
txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5],
ldpc == 0 ? "BCC" : "LDPC", "MU", groupid);
} else {
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten, "%s, %s\n",
txmode < 5 ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[5],
ldpc == 0 ? "BCC" : "LDPC");
}
return i4BytesWritten;
}
static int32_t parseRxRssiInfo(IN char *pcBuffer, IN int i4Size,
IN struct ADAPTER *prAdapter, IN struct STA_RECORD *prStaRec)
{
int32_t i4RSSI0 = 0, i4RSSI1 = 0, i4RSSI2 = 0, i4RSSI3 = 0;
int32_t i4BytesWritten = 0;
uint32_t u4RxVector3 = 0;
u4RxVector3 = prStaRec->u4RxVector3;
i4RSSI0 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI0_MASK) >>
RX_VT_RCPI0_OFFSET);
i4RSSI1 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI1_MASK) >>
RX_VT_RCPI1_OFFSET);
if (prAdapter->rWifiVar.ucNSS > 2) {
i4RSSI2 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI2_MASK) >>
RX_VT_RCPI2_OFFSET);
i4RSSI3 = RCPI_TO_dBm((u4RxVector3 & RX_VT_RCPI3_MASK) >>
RX_VT_RCPI3_OFFSET);
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten, "%-26s%s%d %d %d %d\n",
"Last RX Data RSSI", " = ",
i4RSSI0, i4RSSI1, i4RSSI2, i4RSSI3);
} else
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten, "%-26s%s%d %d\n",
"Last RX Data RSSI", " = ", i4RSSI0, i4RSSI1);
return i4BytesWritten;
}
static uint32_t parseRxRespRssiInfo(IN char *pcBuffer, IN int i4Size,
IN struct ADAPTER *prAdapter,
IN struct PARAM_HW_WLAN_INFO *prHwWlanInfo)
{
int32_t i4BytesWritten = 0;
if (prAdapter->rWifiVar.ucNSS > 2)
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"%-26s%s%d %d %d %d\n", "Tx Response RSSI", " = ",
RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi0),
RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi1),
RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi2),
RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi3));
else
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"%-26s%s%d %d\n", "Tx Response RSSI", " = ",
RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi0),
RCPI_TO_dBm(prHwWlanInfo->rWtblRxCounter.ucRxRcpi1));
return i4BytesWritten;
}
static int32_t parseTxPerInfo(IN char *pcBuffer, IN int i4Size,
IN struct PARAM_HW_WLAN_INFO *prHwWlanInfo,
IN struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics)
{
uint32_t u4InstantPer;
int32_t i4BytesWritten = 0;
uint8_t ucSkipAr;
ucSkipAr = prQueryStaStatistics->ucSkipAr;
if (ucSkipAr) {
u4InstantPer =
(prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt == 0) ?
(0) :
(1000 * (prHwWlanInfo->rWtblTxCounter.u2Rate1FailCnt)
/ (prHwWlanInfo->rWtblTxCounter.u2Rate1TxCnt));
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"%-26s%s%d.%1d%%\n", "instant PER", " = ",
u4InstantPer/10, u4InstantPer%10);
} else {
u4InstantPer = (prQueryStaStatistics->ucPer == 0) ?
(0) : (prQueryStaStatistics->ucPer);
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"%-26s%s%d%%\n", "instant PER", " = ",
u4InstantPer);
}
return i4BytesWritten;
}
static int32_t parseRxPerInfo(IN char *pcBuffer, IN int i4Size,
IN struct ADAPTER *prAdapter,
IN struct PARAM_GET_STA_STATISTICS *prQueryStaStatistics)
{
uint32_t u4InstantPer[ENUM_BAND_NUM];
int32_t i4BytesWritten = 0;
uint8_t ucDbdcIdx;
struct MIB_INFO_STAT *prMibInfo;
prMibInfo = prQueryStaStatistics->rMibInfo;
for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) {
u4InstantPer[ucDbdcIdx] = ((prMibInfo[ucDbdcIdx].u4RxMpduCnt +
prMibInfo[ucDbdcIdx].u4FcsError) == 0) ?
(0) : (1000 * prMibInfo[ucDbdcIdx].u4FcsError /
(prMibInfo[ucDbdcIdx].u4RxMpduCnt +
prMibInfo[ucDbdcIdx].u4FcsError));
if (prAdapter->rWifiVar.fgDbDcModeEn)
i4BytesWritten += kalScnprintf(
pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"[DBDC_%d] :\n",
ucDbdcIdx);
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"%-26s%s%d.%1d%%\n", "instant PER", " = ",
u4InstantPer[ENUM_BAND_0]/10,
u4InstantPer[ENUM_BAND_0]%10);
if (!prAdapter->rWifiVar.fgDbDcModeEn)
break;
}
return i4BytesWritten;
}
static uint32_t parseTrigger(IN char *pcBuffer,
IN int i4Size, IN uint8_t trigger)
{
int32_t i4BytesWritten = 0;
char *pString;
switch (trigger) {
case DISCONNECT_TRIGGER_RESERVED:
pString = GET_VARNAME(DISCONNECT_TRIGGER_RESERVED);
break;
case DISCONNECT_TRIGGER_ACTIVE:
pString = GET_VARNAME(DISCONNECT_TRIGGER_ACTIVE);
break;
case DISCONNECT_TRIGGER_PASSIVE:
pString = GET_VARNAME(DISCONNECT_TRIGGER_PASSIVE);
break;
default:
pString = "N/A";
break;
}
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"%-26s%s%s\n",
"Trigger",
" = ",
pString);
return i4BytesWritten;
}
static uint32_t parseDisconnReasonCode(IN char *pcBuffer,
IN int i4Size, IN uint8_t ucReason)
{
int32_t i4BytesWritten = 0;
char *pString;
switch (ucReason) {
case DISCONNECT_REASON_CODE_RESERVED:
pString = GET_VARNAME(DISCONNECT_REASON_CODE_RESERVED);
break;
case DISCONNECT_REASON_CODE_RADIO_LOST:
pString = GET_VARNAME(DISCONNECT_REASON_CODE_RADIO_LOST);
break;
case DISCONNECT_REASON_CODE_DEAUTHENTICATED:
pString = GET_VARNAME(DISCONNECT_REASON_CODE_DEAUTHENTICATED);
break;
case DISCONNECT_REASON_CODE_DISASSOCIATED:
pString = GET_VARNAME(DISCONNECT_REASON_CODE_DISASSOCIATED);
break;
case DISCONNECT_REASON_CODE_NEW_CONNECTION:
pString = GET_VARNAME(DISCONNECT_REASON_CODE_NEW_CONNECTION);
break;
case DISCONNECT_REASON_CODE_REASSOCIATION:
pString = GET_VARNAME(DISCONNECT_REASON_CODE_REASSOCIATION);
break;
case DISCONNECT_REASON_CODE_ROAMING:
pString = GET_VARNAME(DISCONNECT_REASON_CODE_ROAMING);
break;
default:
pString = "N/A";
break;
}
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"%-26s%s%s\n",
"Disconnect reason",
" = ",
pString);
return i4BytesWritten;
}
static uint32_t parseBcnTimeoutReasonCode(IN char *pcBuffer,
IN int i4Size, IN uint8_t ucReason)
{
int32_t i4BytesWritten = 0;
char *pString;
switch (ucReason) {
case BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_NONADHOC:
pString = GET_VARNAME(
BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_NONADHOC);
break;
case BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_ADHOC:
pString = GET_VARNAME(
BEACON_TIMEOUT_DUE_2_HW_BEACON_LOST_ADHOC);
break;
case BEACON_TIMEOUT_DUE_2_HW_TSF_DRIFT:
pString = GET_VARNAME(
BEACON_TIMEOUT_DUE_2_HW_TSF_DRIFT);
break;
case BEACON_TIMEOUT_DUE_2_NULL_FRAME_THRESHOLD:
pString = GET_VARNAME(
BEACON_TIMEOUT_DUE_2_NULL_FRAME_THRESHOLD);
break;
case BEACON_TIMEOUT_DUE_2_AGING_THRESHOLD:
pString = GET_VARNAME(
BEACON_TIMEOUT_DUE_2_AGING_THRESHOLD);
break;
case BEACON_TIMEOUT_DUE_2_BSSID_BEACON_PEIROD_NOT_ILLIGAL:
pString = GET_VARNAME(
BEACON_TIMEOUT_DUE_2_BSSID_BEACON_PEIROD_NOT_ILLIGAL);
break;
case BEACON_TIMEOUT_DUE_2_CONNECTION_FAIL:
pString = GET_VARNAME(
BEACON_TIMEOUT_DUE_2_CONNECTION_FAIL);
break;
case BEACON_TIMEOUT_DUE_2_ALLOCAT_NULL_PKT_FAIL_THRESHOLD:
pString = GET_VARNAME(
BEACON_TIMEOUT_DUE_2_ALLOCAT_NULL_PKT_FAIL_THRESHOLD);
break;
case BEACON_TIMEOUT_DUE_2_NO_TX_DONE_EVENT:
pString = GET_VARNAME(
BEACON_TIMEOUT_DUE_2_NO_TX_DONE_EVENT);
break;
case BEACON_TIMEOUT_DUE_2_UNSPECIF_REASON:
pString = GET_VARNAME(
BEACON_TIMEOUT_DUE_2_UNSPECIF_REASON);
break;
case BEACON_TIMEOUT_DUE_2_SET_CHIP:
pString = GET_VARNAME(
BEACON_TIMEOUT_DUE_2_SET_CHIP);
break;
case BEACON_TIMEOUT_DUE_2_KEEP_SCAN_AP_MISS_CHECK_FAIL:
pString = GET_VARNAME(
BEACON_TIMEOUT_DUE_2_KEEP_SCAN_AP_MISS_CHECK_FAIL);
break;
case BEACON_TIMEOUT_DUE_2_KEEP_UNCHANGED_LOW_RSSI_CHECK_FAIL:
pString = GET_VARNAME(
BEACON_TIMEOUT_DUE_2_KEEP_UNCHANGED_LOW_RSSI_CHECK_FAIL);
break;
case BEACON_TIMEOUT_DUE_2_NULL_FRAME_LIFE_TIMEOUT:
pString = GET_VARNAME(
BEACON_TIMEOUT_DUE_2_NULL_FRAME_LIFE_TIMEOUT);
break;
case BEACON_TIMEOUT_DUE_2_APR_NO_RESPONSE:
pString = GET_VARNAME(
BEACON_TIMEOUT_DUE_2_APR_NO_RESPONSE);
break;
default:
pString = "N/A";
break;
}
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"%-26s%s%s\n",
"Beacon timeout reason",
" = ",
pString);
return i4BytesWritten;
}
static uint32_t parseDisassocReasonCode(IN char *pcBuffer,
IN int i4Size, IN uint8_t ucReason)
{
int32_t i4BytesWritten = 0;
char *pString;
switch (ucReason) {
case REASON_CODE_RESERVED:
pString = GET_VARNAME(
REASON_CODE_RESERVED);
break;
case REASON_CODE_UNSPECIFIED:
pString = GET_VARNAME(
REASON_CODE_UNSPECIFIED);
break;
case REASON_CODE_PREV_AUTH_INVALID:
pString = GET_VARNAME(
REASON_CODE_PREV_AUTH_INVALID);
break;
case REASON_CODE_DEAUTH_LEAVING_BSS:
pString = GET_VARNAME(
REASON_CODE_DEAUTH_LEAVING_BSS);
break;
case REASON_CODE_DISASSOC_INACTIVITY:
pString = GET_VARNAME(
REASON_CODE_DISASSOC_INACTIVITY);
break;
case REASON_CODE_DISASSOC_AP_OVERLOAD:
pString = GET_VARNAME(
REASON_CODE_DISASSOC_AP_OVERLOAD);
break;
case REASON_CODE_CLASS_2_ERR:
pString = GET_VARNAME(
REASON_CODE_CLASS_2_ERR);
break;
case REASON_CODE_CLASS_3_ERR:
pString = GET_VARNAME(
REASON_CODE_CLASS_3_ERR);
break;
case REASON_CODE_DISASSOC_LEAVING_BSS:
pString = GET_VARNAME(
REASON_CODE_DISASSOC_LEAVING_BSS);
break;
case REASON_CODE_ASSOC_BEFORE_AUTH:
pString = GET_VARNAME(
REASON_CODE_ASSOC_BEFORE_AUTH);
break;
case REASON_CODE_DISASSOC_PWR_CAP_UNACCEPTABLE:
pString = GET_VARNAME(
REASON_CODE_DISASSOC_PWR_CAP_UNACCEPTABLE);
break;
case REASON_CODE_DISASSOC_SUP_CHS_UNACCEPTABLE:
pString = GET_VARNAME(
REASON_CODE_DISASSOC_SUP_CHS_UNACCEPTABLE);
break;
case REASON_CODE_INVALID_INFO_ELEM:
pString = GET_VARNAME(
REASON_CODE_INVALID_INFO_ELEM);
break;
case REASON_CODE_MIC_FAILURE:
pString = GET_VARNAME(
REASON_CODE_MIC_FAILURE);
break;
case REASON_CODE_4_WAY_HANDSHAKE_TIMEOUT:
pString = GET_VARNAME(
REASON_CODE_4_WAY_HANDSHAKE_TIMEOUT);
break;
case REASON_CODE_GROUP_KEY_UPDATE_TIMEOUT:
pString = GET_VARNAME(
REASON_CODE_GROUP_KEY_UPDATE_TIMEOUT);
break;
case REASON_CODE_DIFFERENT_INFO_ELEM:
pString = GET_VARNAME(
REASON_CODE_DIFFERENT_INFO_ELEM);
break;
case REASON_CODE_MULTICAST_CIPHER_NOT_VALID:
pString = GET_VARNAME(
REASON_CODE_MULTICAST_CIPHER_NOT_VALID);
break;
case REASON_CODE_UNICAST_CIPHER_NOT_VALID:
pString = GET_VARNAME(
REASON_CODE_UNICAST_CIPHER_NOT_VALID);
break;
case REASON_CODE_AKMP_NOT_VALID:
pString = GET_VARNAME(
REASON_CODE_AKMP_NOT_VALID);
break;
case REASON_CODE_UNSUPPORTED_RSNE_VERSION:
pString = GET_VARNAME(
REASON_CODE_UNSUPPORTED_RSNE_VERSION);
break;
case REASON_CODE_INVALID_RSNE_CAPABILITIES:
pString = GET_VARNAME(
REASON_CODE_INVALID_RSNE_CAPABILITIES);
break;
case REASON_CODE_IEEE_802_1X_AUTH_FAILED:
pString = GET_VARNAME(
REASON_CODE_IEEE_802_1X_AUTH_FAILED);
break;
case REASON_CODE_CIPHER_REJECT_SEC_POLICY:
pString = GET_VARNAME(
REASON_CODE_CIPHER_REJECT_SEC_POLICY);
break;
case REASON_CODE_DISASSOC_UNSPECIFIED_QOS:
pString = GET_VARNAME(
REASON_CODE_DISASSOC_UNSPECIFIED_QOS);
break;
case REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH:
pString = GET_VARNAME(
REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH);
break;
case REASON_CODE_DISASSOC_ACK_LOST_POOR_CHANNEL:
pString = GET_VARNAME(
REASON_CODE_DISASSOC_ACK_LOST_POOR_CHANNEL);
break;
case REASON_CODE_DISASSOC_TX_OUTSIDE_TXOP_LIMIT:
pString = GET_VARNAME(
REASON_CODE_DISASSOC_TX_OUTSIDE_TXOP_LIMIT);
break;
case REASON_CODE_PEER_WHILE_LEAVING:
pString = GET_VARNAME(
REASON_CODE_PEER_WHILE_LEAVING);
break;
case REASON_CODE_PEER_REFUSE_DLP:
pString = GET_VARNAME(
REASON_CODE_PEER_REFUSE_DLP);
break;
case REASON_CODE_PEER_SETUP_REQUIRED:
pString = GET_VARNAME(
REASON_CODE_PEER_SETUP_REQUIRED);
break;
case REASON_CODE_PEER_TIME_OUT:
pString = GET_VARNAME(
REASON_CODE_PEER_TIME_OUT);
break;
case REASON_CODE_PEER_CIPHER_UNSUPPORTED:
pString = GET_VARNAME(
REASON_CODE_PEER_CIPHER_UNSUPPORTED);
break;
case REASON_CODE_BEACON_TIMEOUT:
pString = GET_VARNAME(
REASON_CODE_BEACON_TIMEOUT);
break;
default:
pString = "N/A";
break;
}
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"%-26s%s%s\n",
"Disassociation reason",
" = ",
pString);
return i4BytesWritten;
}
static uint32_t parseRssiInfo(IN char *pcBuffer, IN int i4Size,
IN struct CMD_NOISE_HISTOGRAM_REPORT *prNoise)
{
int32_t i4BytesWritten = 0;
struct CMD_NOISE_HISTOGRAM_REPORT rEmptyNoise;
kalMemZero(&rEmptyNoise, sizeof(rEmptyNoise));
rEmptyNoise.u2Type = prNoise->u2Type;
rEmptyNoise.u2Len = prNoise->u2Len;
rEmptyNoise.ucAction = prNoise->ucAction;
if (kalMemCmp(prNoise, &rEmptyNoise,
sizeof(struct CMD_NOISE_HISTOGRAM_REPORT)) == 0) {
DBGLOG(INIT, WARN, "Empty info\n");
return i4BytesWritten;
}
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"\n%s", "----- Noise Info -----");
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"\n Power > -55: %10d",
prNoise->u4IPI10);
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"\n-55 >= Power > -60: %10d",
prNoise->u4IPI9);
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"\n-60 >= Power > -65: %10d",
prNoise->u4IPI8);
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"\n-65 >= Power > -70: %10d",
prNoise->u4IPI7);
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"\n-70 >= Power > -75: %10d",
prNoise->u4IPI6);
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"\n-75 >= Power > -80: %10d",
prNoise->u4IPI5);
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"\n-80 >= Power > -83: %10d",
prNoise->u4IPI4);
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"\n-83 >= Power > -86: %10d",
prNoise->u4IPI3);
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"\n-86 >= Power > -89: %10d",
prNoise->u4IPI2);
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"\n-89 >= Power > -92: %10d",
prNoise->u4IPI1);
i4BytesWritten += kalScnprintf(pcBuffer + i4BytesWritten,
i4Size - i4BytesWritten,
"\n-92 >= Power : %10d\n",
prNoise->u4IPI0);
return i4BytesWritten;
}
static ssize_t procDisconnInfoRead(struct file *filp,
char __user *buf, size_t count, loff_t *f_pos)
{
uint8_t *pucProcBuf = kalMemAlloc(PROC_MAX_BUF_SIZE, VIR_MEM_TYPE);
struct GLUE_INFO *prGlueInfo;
struct ADAPTER *prAdapter;
int32_t i4Count = 0;
uint8_t ucDbdcIdx;
uint8_t *temp = NULL;
struct AIS_DISCONN_INFO_T *prDisconn = NULL;
uint8_t cnt;
uint8_t temp_idx = 0;
struct tm broken;
char date[20] = {0};
int32_t i4Ret = 0;
/* if *f_ops>0, we should return 0 to make cat command exit */
if (*f_pos > 0 || buf == NULL || pucProcBuf == NULL)
goto freeBuf;
if (g_prDisconnInfo == NULL) {
DBGLOG(INIT, WARN, "NULL g_prDisconnInfo\n");
goto freeBuf;
}
if (g_DisconnInfoIdx >= MAX_DISCONNECT_RECORD) {
DBGLOG(AIS, LOUD, "Invalid g_DisconnInfoIdx\n");
goto freeBuf;
}
prGlueInfo = g_prGlueInfo_proc;
prAdapter = prGlueInfo->prAdapter;
kalMemZero(pucProcBuf, PROC_MAX_BUF_SIZE);
temp = pucProcBuf;
for (cnt = 0; cnt < MAX_DISCONNECT_RECORD; cnt++) {
temp_idx = (g_DisconnInfoIdx + cnt) % MAX_DISCONNECT_RECORD;
prDisconn = g_prDisconnInfo + temp_idx;
#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE
time64_to_tm(prDisconn->tv.tv_sec, 0, &broken);
#else
time_to_tm(prDisconn->tv.tv_sec, 0, &broken);
#endif
kalScnprintf(date,
sizeof(date),
"%02d-%02d %02d:%02d:%02d.%ld",
broken.tm_mon + 1,
broken.tm_mday,
broken.tm_hour,
broken.tm_min,
broken.tm_sec,
#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE
(prDisconn->tv.tv_nsec/USEC_PER_MSEC)
#else
prDisconn->tv.tv_usec
#endif
);
i4Count += kalScnprintf(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
"%s %s %d %s %s %s %s",
"===============",
"Record",
temp_idx,
"(",
date,
")",
"===============");
/* Dump misc info*/
i4Count += kalScnprintf(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
"\n%s", "<Misc Info>\n");
i4Count += parseTrigger(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
prDisconn->ucTrigger);
i4Count += parseDisconnReasonCode(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
prDisconn->ucDisConnReason);
i4Count += parseBcnTimeoutReasonCode(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
prDisconn->ucBcnTimeoutReason);
i4Count += parseDisassocReasonCode(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
prDisconn->ucDisassocReason);
if (prDisconn->u2DisassocSeqNum != 0xFFFF) {
i4Count += kalScnprintf(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
"%-26s%s%d\n",
"Disassociation SeqNum",
" = ",
prDisconn->u2DisassocSeqNum);
}
/* Noise info*/
i4Count += parseRssiInfo(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
&prDisconn->rNoise);
/* Dump RX info */
i4Count += kalScnprintf(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
"\n%s", "<Last Rx Info>\n");
/* Last RX Rate info */
i4Count += parseRxRateInfo(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
&prDisconn->rStaRec);
/* RX PER info */
i4Count += parseRxPerInfo(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
prAdapter,
&prDisconn->rStaStatistics);
/* Last RX RSSI info*/
i4Count += parseRxRssiInfo(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
prAdapter,
&prDisconn->rStaRec);
/* Last RX Resp RSSI */
i4Count += parseRxRespRssiInfo(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
prAdapter,
&prDisconn->rHwInfo);
/* Last Beacon RSSI */
i4Count += kalScnprintf(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
"%-26s%s%d\n", "Beacon RSSI", " = ",
prDisconn->rBcnRssi);
/* Dump TX info */
i4Count += kalScnprintf(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
"\n%s", "<Last Tx Info>\n");
/* Last TX Rate info */
for (ucDbdcIdx = 0; ucDbdcIdx < ENUM_BAND_NUM; ucDbdcIdx++) {
if (prAdapter->rWifiVar.fgDbDcModeEn)
i4Count += kalScnprintf(
temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
"[DBDC_%d] :\n",
ucDbdcIdx);
i4Count += parseTxRateInfo(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
&prDisconn->rStaStatistics
.rTxVector[ucDbdcIdx]);
if (!prAdapter->rWifiVar.fgDbDcModeEn)
break;
}
/* TX PER info */
i4Count += parseTxPerInfo(temp + i4Count,
PROC_MAX_BUF_SIZE - i4Count,
&prDisconn->rHwInfo,
&prDisconn->rStaStatistics);
}
if (copy_to_user(buf, pucProcBuf, i4Count)) {
DBGLOG(INIT, ERROR, "copy to user failed\n");
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return -EFAULT;
}
*f_pos += i4Count;
i4Ret = i4Count;
freeBuf:
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return i4Ret;
}
#endif /* CFG_DISCONN_DEBUG_FEATURE */
static DEFINE_PROC_OPS_STRUCT(dbglevel_ops) = {
DEFINE_PROC_OPS_OWNER(THIS_MODULE)
DEFINE_PROC_OPS_READ(procDbgLevelRead)
DEFINE_PROC_OPS_WRITE(procDbgLevelWrite)
};
#if WLAN_INCLUDE_PROC
#if CFG_SUPPORT_EASY_DEBUG
static DEFINE_PROC_OPS_STRUCT(efusedump_ops) = {
DEFINE_PROC_OPS_OWNER(THIS_MODULE)
DEFINE_PROC_OPS_OPEN(procEfuseDumpOpen)
DEFINE_PROC_OPS_READ(seq_read)
DEFINE_PROC_OPS_LSEEK(seq_lseek)
DEFINE_PROC_OPS_RELEASE(seq_release)
};
static DEFINE_PROC_OPS_STRUCT(drivercmd_ops) = {
DEFINE_PROC_OPS_OWNER(THIS_MODULE)
DEFINE_PROC_OPS_READ(procDriverCmdRead)
DEFINE_PROC_OPS_WRITE(procDriverCmdWrite)
};
static DEFINE_PROC_OPS_STRUCT(cfg_ops) = {
DEFINE_PROC_OPS_OWNER(THIS_MODULE)
DEFINE_PROC_OPS_READ(procCfgRead)
DEFINE_PROC_OPS_WRITE(procCfgWrite)
};
#endif
#endif
static DEFINE_PROC_OPS_STRUCT(get_txpwr_tbl_ops) = {
DEFINE_PROC_OPS_OWNER(THIS_MODULE)
DEFINE_PROC_OPS_READ(procGetTxpwrTblRead)
};
#ifdef CFG_GET_TEMPURATURE
static DEFINE_PROC_OPS_STRUCT(get_temperature_ops) = {
DEFINE_PROC_OPS_OWNER(THIS_MODULE)
DEFINE_PROC_OPS_READ(proc_get_temperature)
};
#endif
#if CFG_DISCONN_DEBUG_FEATURE
static DEFINE_PROC_OPS_STRUCT(disconn_info_ops) = {
DEFINE_PROC_OPS_OWNER(THIS_MODULE)
DEFINE_PROC_OPS_READ(procDisconnInfoRead)
};
#endif
/*******************************************************************************
* F U N C T I O N S
*******************************************************************************
*/
/*----------------------------------------------------------------------------*/
/*!
* \brief The PROC function for reading MCR register to User Space, the offset
* of the MCR is specified in u4McrOffset.
*
* \param[in] page Buffer provided by kernel.
* \param[in out] start Start Address to read(3 methods).
* \param[in] off Offset.
* \param[in] count Allowable number to read.
* \param[out] eof End of File indication.
* \param[in] data Pointer to the private data structure.
*
* \return number of characters print to the buffer from User Space.
*/
/*----------------------------------------------------------------------------*/
static ssize_t procMCRRead(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos)
{
uint8_t *pucProcBuf = kalMemAlloc(PROC_MAX_BUF_SIZE, VIR_MEM_TYPE);
struct GLUE_INFO *prGlueInfo;
struct PARAM_CUSTOM_MCR_RW_STRUCT rMcrInfo;
uint32_t u4BufLen;
uint32_t u4CopySize = 0;
uint8_t *temp = NULL;
uint32_t rStatus = WLAN_STATUS_SUCCESS;
int32_t i4Ret = 0;
/* if *f_ops>0, we should return 0 to make cat command exit */
if (*f_pos > 0 || buf == NULL || pucProcBuf == NULL)
goto freeBuf;
prGlueInfo = g_prGlueInfo_proc;
rMcrInfo.u4McrOffset = u4McrOffset;
rStatus = kalIoctl(prGlueInfo,
wlanoidQueryMcrRead, (void *)&rMcrInfo,
sizeof(rMcrInfo), TRUE, TRUE, TRUE, &u4BufLen);
kalMemZero(pucProcBuf, PROC_MAX_BUF_SIZE);
temp = pucProcBuf;
SNPRINTF(temp, PROC_MAX_BUF_SIZE - kalStrLen(pucProcBuf),
("MCR (0x%08xh): 0x%08x\n", rMcrInfo.u4McrOffset,
rMcrInfo.u4McrData));
u4CopySize = kalStrLen(pucProcBuf);
if (u4CopySize > count)
u4CopySize = count;
if (copy_to_user(buf, pucProcBuf, u4CopySize)) {
DBGLOG(INIT, ERROR, "copy to user failed\n");
i4Ret = -EFAULT;
goto freeBuf;
}
*f_pos += u4CopySize;
i4Ret = u4CopySize;
freeBuf:
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return i4Ret;
} /* end of procMCRRead() */
/*----------------------------------------------------------------------------*/
/*!
* \brief The PROC function for writing MCR register to HW or update u4McrOffset
* for reading MCR later.
*
* \param[in] file pointer to file.
* \param[in] buffer Buffer from user space.
* \param[in] count Number of characters to write
* \param[in] data Pointer to the private data structure.
*
* \return number of characters write from User Space.
*/
/*----------------------------------------------------------------------------*/
static ssize_t procMCRWrite(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
struct GLUE_INFO *prGlueInfo;
/* + 1 for "\0" */
char acBuf[PROC_MCR_ACCESS_MAX_USER_INPUT_LEN + 1];
uint32_t u4CopySize = 0;
struct PARAM_CUSTOM_MCR_RW_STRUCT rMcrInfo;
uint32_t u4BufLen;
uint32_t rStatus = WLAN_STATUS_SUCCESS;
int num = 0;
ASSERT(data);
u4CopySize = (count < sizeof(acBuf)) ? count : (sizeof(acBuf) - 1);
if (copy_from_user(acBuf, buffer, u4CopySize))
return 0;
acBuf[u4CopySize] = '\0';
num =
sscanf(acBuf, "0x%x 0x%x", &rMcrInfo.u4McrOffset,
&rMcrInfo.u4McrData);
switch (num) {
case 2:
/* NOTE: Sometimes we want to test if bus will still be ok,
* after accessing the MCR which is not align to DW boundary.
*/
/* if (IS_ALIGN_4(rMcrInfo.u4McrOffset)) */
{
prGlueInfo = g_prGlueInfo_proc;
u4McrOffset = rMcrInfo.u4McrOffset;
/* rMcrInfo.u4McrOffset, rMcrInfo.u4McrData); */
rStatus = kalIoctl(prGlueInfo,
wlanoidSetMcrWrite,
(void *)&rMcrInfo, sizeof(rMcrInfo),
FALSE, FALSE, TRUE, &u4BufLen);
}
break;
case 1:
/* if (IS_ALIGN_4(rMcrInfo.u4McrOffset)) */
{
u4McrOffset = rMcrInfo.u4McrOffset;
}
break;
default:
break;
}
return u4CopySize;
} /* end of procMCRWrite() */
static DEFINE_PROC_OPS_STRUCT(mcr_ops) = {
DEFINE_PROC_OPS_OWNER(THIS_MODULE)
DEFINE_PROC_OPS_READ(procMCRRead)
DEFINE_PROC_OPS_WRITE(procMCRWrite)
};
#if CFG_SUPPORT_SET_CAM_BY_PROC
static ssize_t procSetCamCfgWrite(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
#define MODULE_NAME_LEN_1 5
uint8_t *pucProcBuf = kalMemAlloc(PROC_MAX_BUF_SIZE, VIR_MEM_TYPE);
uint32_t u4CopySize = PROC_MAX_BUF_SIZE;
uint8_t *temp = NULL;
u_int8_t fgSetCamCfg = FALSE;
uint8_t aucModule[MODULE_NAME_LEN_1];
uint32_t u4Enabled;
uint8_t aucModuleArray[MODULE_NAME_LEN_1] = "CAM";
u_int8_t fgParamValue = TRUE;
struct GLUE_INFO *prGlueInfo = NULL;
struct ADAPTER *prAdapter = NULL;
int32_t i4Ret = 0;
if (buffer == NULL || pucProcBuf == NULL)
goto freeBuf;
kalMemZero(pucProcBuf, PROC_MAX_BUF_SIZE);
u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1);
if (copy_from_user(pucProcBuf, buffer, u4CopySize)) {
DBGLOG(INIT, ERROR, "error of copy from user\n");
i4Ret = -EFAULT;
goto freeBuf;
}
pucProcBuf[u4CopySize] = '\0';
temp = pucProcBuf;
while (temp) {
kalMemSet(aucModule, 0, MODULE_NAME_LEN_1);
/* pick up a string and teminated after meet : */
if (sscanf(temp, "%4s %d", aucModule, &u4Enabled) != 2) {
DBGLOG(INIT, INFO,
"read param fail, aucModule=%s\n", aucModule);
fgParamValue = FALSE;
break;
}
if (kalStrnCmp
(aucModule, aucModuleArray, MODULE_NAME_LEN_1) == 0) {
if (u4Enabled)
fgSetCamCfg = TRUE;
else
fgSetCamCfg = FALSE;
}
temp = kalStrChr(temp, ',');
if (!temp)
break;
temp++; /* skip ',' */
}
if (fgParamValue) {
prGlueInfo = wlanGetGlueInfo();
if (!prGlueInfo)
goto freeBuf;
prAdapter = prGlueInfo->prAdapter;
if (!prAdapter)
goto freeBuf;
nicConfigProcSetCamCfgWrite(prAdapter, fgSetCamCfg);
}
i4Ret = u4CopySize;
freeBuf:
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return i4Ret;
}
static DEFINE_PROC_OPS_STRUCT(proc_set_cam_ops) = {
DEFINE_PROC_OPS_OWNER(THIS_MODULE)
DEFINE_PROC_OPS_WRITE(procSetCamCfgWrite)
};
#endif /*CFG_SUPPORT_SET_CAM_BY_PROC */
static ssize_t procPktDelayDbgCfgRead(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos)
{
uint8_t *pucProcBuf = kalMemAlloc(PROC_MAX_BUF_SIZE, VIR_MEM_TYPE);
uint8_t *temp = NULL;
uint8_t *str = NULL;
uint32_t u4CopySize = 0;
uint8_t ucTxRxFlag;
uint8_t ucTxIpProto;
uint16_t u2TxUdpPort;
uint32_t u4TxDelayThreshold;
uint8_t ucRxIpProto;
uint16_t u2RxUdpPort;
uint32_t u4RxDelayThreshold;
uint32_t u4StrLen = 0;
int32_t i4Ret = 0;
/* if *f_ops>0, we should return 0 to make cat command exit */
if (*f_pos > 0 || buf == NULL || pucProcBuf == NULL)
goto freeBuf;
str = "\nUsage: txLog/rxLog/reset 1(ICMP)/6(TCP)/11(UDP) Dst/SrcPortNum DelayThreshold(us)\n"
"Print tx delay log, such as: echo txLog 0 0 0 > pktDelay\n"
"Print tx UDP delay log, such as: echo txLog 11 0 0 > pktDelay\n"
"Print tx UDP dst port19305 delay log, such as: echo txLog 11 19305 0 > pktDelay\n"
"Print rx UDP src port19305 delay more than 500us log, such as: echo rxLog 11 19305 500 > pktDelay\n"
"Print tx TCP delay more than 500us log, such as: echo txLog 6 0 500 > pktDelay\n"
"Close log, such as: echo reset 0 0 0 > pktDelay\n\n";
u4StrLen = kalStrLen(str);
kalMemZero(pucProcBuf, PROC_MAX_BUF_SIZE);
temp = pucProcBuf;
kalStrnCpy(temp, str, u4StrLen + 1);
temp += kalStrLen(temp);
StatsEnvGetPktDelay(&ucTxRxFlag, &ucTxIpProto, &u2TxUdpPort,
&u4TxDelayThreshold, &ucRxIpProto, &u2RxUdpPort,
&u4RxDelayThreshold);
if (ucTxRxFlag & BIT(0)) {
SNPRINTF(temp, PROC_MAX_BUF_SIZE - kalStrLen(pucProcBuf),
("txLog %x %d %d\n", ucTxIpProto, u2TxUdpPort,
u4TxDelayThreshold));
temp += kalStrLen(temp);
}
if (ucTxRxFlag & BIT(1)) {
SNPRINTF(temp, PROC_MAX_BUF_SIZE - kalStrLen(pucProcBuf),
("rxLog %x %d %d\n", ucRxIpProto, u2RxUdpPort,
u4RxDelayThreshold));
temp += kalStrLen(temp);
}
if (ucTxRxFlag == 0)
SNPRINTF(temp, PROC_MAX_BUF_SIZE - kalStrLen(pucProcBuf),
("reset 0 0 0, there is no tx/rx delay log\n"));
u4CopySize = kalStrLen(pucProcBuf);
if (u4CopySize > count)
u4CopySize = count;
if (copy_to_user(buf, pucProcBuf, u4CopySize)) {
DBGLOG(INIT, ERROR, "copy to user failed\n");
i4Ret = -EFAULT;
goto freeBuf;
}
*f_pos += u4CopySize;
i4Ret = u4CopySize;
freeBuf:
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return i4Ret;
}
static ssize_t procPktDelayDbgCfgWrite(struct file *file, const char *buffer,
size_t count, loff_t *data)
{
#define MODULE_NAME_LENGTH 7
#define MODULE_RESET 0
#define MODULE_TX 1
#define MODULE_RX 2
uint8_t *pucProcBuf = kalMemAlloc(PROC_MAX_BUF_SIZE, VIR_MEM_TYPE);
uint32_t u4CopySize = PROC_MAX_BUF_SIZE;
uint8_t *temp = NULL;
uint8_t aucModule[MODULE_NAME_LENGTH];
uint32_t u4DelayThreshold = 0;
uint32_t u4PortNum = 0;
uint32_t u4IpProto = 0;
uint8_t aucResetArray[MODULE_NAME_LENGTH] = "reset";
uint8_t aucTxArray[MODULE_NAME_LENGTH] = "txLog";
uint8_t aucRxArray[MODULE_NAME_LENGTH] = "rxLog";
uint8_t ucTxOrRx = 0;
int32_t i4Ret = 0;
if (buffer == NULL || pucProcBuf == NULL)
goto freeBuf;
kalMemZero(pucProcBuf, PROC_MAX_BUF_SIZE);
u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1);
if (copy_from_user(pucProcBuf, buffer, u4CopySize)) {
DBGLOG(INIT, ERROR, "error of copy from user\n");
i4Ret = -EFAULT;
goto freeBuf;
}
pucProcBuf[u4CopySize] = '\0';
temp = pucProcBuf;
while (temp) {
kalMemSet(aucModule, 0, MODULE_NAME_LENGTH);
/* pick up a string and teminated after meet : */
if (sscanf
(temp, "%6s %x %d %d", aucModule, &u4IpProto, &u4PortNum,
&u4DelayThreshold) != 4) {
DBGLOG(INIT, INFO,
"read param fail, aucModule=%s\n", aucModule);
break;
}
if (kalStrnCmp
(aucModule, aucResetArray, MODULE_NAME_LENGTH) == 0) {
ucTxOrRx = MODULE_RESET;
} else if (kalStrnCmp
(aucModule, aucTxArray, MODULE_NAME_LENGTH) == 0) {
ucTxOrRx = MODULE_TX;
} else if (kalStrnCmp
(aucModule, aucRxArray, MODULE_NAME_LENGTH) == 0) {
ucTxOrRx = MODULE_RX;
} else {
DBGLOG(INIT, INFO, "input module error!\n");
break;
}
temp = kalStrChr(temp, ',');
if (!temp)
break;
temp++; /* skip ',' */
}
StatsEnvSetPktDelay(ucTxOrRx, (uint8_t) u4IpProto, (uint16_t) u4PortNum,
u4DelayThreshold);
i4Ret = u4CopySize;
freeBuf:
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return i4Ret;
}
static DEFINE_PROC_OPS_STRUCT(proc_pkt_delay_dbg_ops) = {
DEFINE_PROC_OPS_OWNER(THIS_MODULE)
DEFINE_PROC_OPS_READ(procPktDelayDbgCfgRead)
DEFINE_PROC_OPS_WRITE(procPktDelayDbgCfgWrite)
};
#if CFG_SUPPORT_DEBUG_FS
static ssize_t procRoamRead(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos)
{
uint8_t *pucProcBuf = kalMemAlloc(PROC_MAX_BUF_SIZE, VIR_MEM_TYPE);
uint32_t u4CopySize;
uint32_t rStatus;
uint32_t u4BufLen;
int32_t i4Ret = 0;
/* if *f_pos > 0, it means has read successed last time,
* don't try again
*/
if (*f_pos > 0 || buf == NULL || pucProcBuf == NULL)
goto freeBuf;
kalMemZero(pucProcBuf, PROC_MAX_BUF_SIZE);
rStatus =
kalIoctl(g_prGlueInfo_proc, wlanoidGetRoamParams, pucProcBuf,
PROC_MAX_BUF_SIZE, TRUE, FALSE, TRUE, &u4BufLen);
if (rStatus != WLAN_STATUS_SUCCESS) {
DBGLOG(INIT, INFO, "failed to read roam params\n");
i4Ret = -EINVAL;
goto freeBuf;
}
u4CopySize = kalStrLen(pucProcBuf);
if (copy_to_user(buf, pucProcBuf, u4CopySize)) {
DBGLOG(INIT, ERROR, "copy to user failed\n");
i4Ret = -EFAULT;
goto freeBuf;
}
*f_pos += u4CopySize;
i4Ret = u4CopySize;
freeBuf:
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return i4Ret;
}
static ssize_t procRoamWrite(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
uint8_t *pucProcBuf = kalMemAlloc(PROC_MAX_BUF_SIZE, VIR_MEM_TYPE);
uint32_t rStatus;
uint32_t u4BufLen = 0;
uint32_t u4CopySize = PROC_MAX_BUF_SIZE;
int32_t i4Ret = 0;
if (buffer == NULL || pucProcBuf == NULL)
goto freeBuf;
kalMemZero(pucProcBuf, PROC_MAX_BUF_SIZE);
u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1);
if (copy_from_user(pucProcBuf, buffer, u4CopySize)) {
DBGLOG(INIT, ERROR, "error of copy from user\n");
i4Ret = -EFAULT;
goto freeBuf;
}
pucProcBuf[u4CopySize] = '\0';
if (kalStrnCmp(pucProcBuf, "force_roam", 10) == 0)
rStatus =
kalIoctl(g_prGlueInfo_proc, wlanoidSetForceRoam, NULL, 0,
FALSE, FALSE, TRUE, &u4BufLen);
else
rStatus =
kalIoctl(g_prGlueInfo_proc, wlanoidSetRoamParams,
pucProcBuf, kalStrLen(pucProcBuf), FALSE,
FALSE, TRUE, &u4BufLen);
if (rStatus != WLAN_STATUS_SUCCESS) {
DBGLOG(INIT, INFO, "failed to set roam params: %s\n",
pucProcBuf);
i4Ret = -EINVAL;
goto freeBuf;
}
i4Ret = u4CopySize;
freeBuf:
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return i4Ret;
}
static const struct file_operations roam_ops = {
.owner = THIS_MODULE,
.read = procRoamRead,
.write = procRoamWrite,
};
#endif
static ssize_t procCountryRead(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos)
{
uint8_t *pucProcBuf = kalMemAlloc(PROC_MAX_BUF_SIZE, VIR_MEM_TYPE);
uint32_t u4CopySize;
uint32_t country = 0;
int32_t ret = 0;
int32_t i4Ret = 0;
/* if *f_pos > 0, it means has read successed last time */
if (*f_pos > 0 || buf == NULL || pucProcBuf == NULL)
goto freeBuf;
country = rlmDomainGetCountryCode();
kalMemZero(pucProcBuf, PROC_MAX_BUF_SIZE);
if (country) {
ret = kalSnprintf(pucProcBuf, PROC_MAX_BUF_SIZE,
"Current Country Code: %s\n", &country);
if (ret < 0) {
DBGLOG(INIT, ERROR, "snprintf Country Code failed\n");
return -EFAULT;
}
} else {
ret = kalSnprintf(pucProcBuf, PROC_MAX_BUF_SIZE,
"Current Country Code: NULL\n");
if (ret < 0) {
DBGLOG(INIT, ERROR,
"snprintf Country Code NULL failed\n");
return -EFAULT;
}
}
u4CopySize = kalStrLen(pucProcBuf);
if (u4CopySize > count)
u4CopySize = count;
if (copy_to_user(buf, pucProcBuf, u4CopySize)) {
DBGLOG(INIT, ERROR, "copy to user failed\n");
i4Ret = -EFAULT;
goto freeBuf;
}
*f_pos += u4CopySize;
i4Ret = u4CopySize;
freeBuf:
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return i4Ret;
}
static ssize_t procCountryWrite(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
uint8_t *pucProcBuf = kalMemAlloc(PROC_MAX_BUF_SIZE, VIR_MEM_TYPE);
uint32_t u4BufLen = 0;
uint32_t rStatus;
uint32_t u4CopySize = PROC_MAX_BUF_SIZE;
int32_t i4Ret = 0;
if (buffer == NULL || pucProcBuf == NULL)
goto freeBuf;
kalMemZero(pucProcBuf, PROC_MAX_BUF_SIZE);
u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1);
if (u4CopySize < 2) {
DBGLOG(REQ, WARN, "Invaild country code len[%u]\n",
u4CopySize);
i4Ret = -EFAULT;
goto freeBuf;
}
if (copy_from_user(g_aucProcBuf, buffer, u4CopySize)) {
DBGLOG(INIT, ERROR, "error of copy from user\n");
i4Ret = -EFAULT;
goto freeBuf;
}
pucProcBuf[u4CopySize] = '\0';
rStatus = kalIoctl(g_prGlueInfo_proc, wlanoidSetCountryCode,
pucProcBuf, 2, FALSE, FALSE, TRUE, &u4BufLen);
if (rStatus != WLAN_STATUS_SUCCESS) {
DBGLOG(INIT, INFO, "failed set country code: %s\n",
pucProcBuf);
i4Ret = -EINVAL;
goto freeBuf;
}
i4Ret = u4CopySize;
freeBuf:
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return i4Ret;
}
static DEFINE_PROC_OPS_STRUCT(country_ops) = {
DEFINE_PROC_OPS_OWNER(THIS_MODULE)
DEFINE_PROC_OPS_READ(procCountryRead)
DEFINE_PROC_OPS_WRITE(procCountryWrite)
};
static ssize_t procAutoPerfCfgRead(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos)
{
uint8_t *pucProcBuf = kalMemAlloc(PROC_MAX_BUF_SIZE, VIR_MEM_TYPE);
uint8_t *temp = NULL;
uint8_t *str = NULL;
uint32_t u4CopySize = 0;
uint32_t u4StrLen = 0;
int32_t i4Ret = 0;
/* if *f_ops>0, we should return 0 to make cat command exit */
if (*f_pos > 0 || buf == NULL || pucProcBuf == NULL)
goto freeBuf;
str = "Auto Performance Configure Usage:\n"
"\n"
"echo ForceEnable:0 or 1 > /proc/net/wlan/autoPerfCfg\n"
" 1: always enable performance monitor\n"
" 0: restore performance monitor's default strategy\n";
u4StrLen = kalStrLen(str);
kalMemZero(pucProcBuf, PROC_MAX_BUF_SIZE);
temp = pucProcBuf;
kalStrnCpy(temp, str, u4StrLen + 1);
u4CopySize = kalStrLen(pucProcBuf);
if (u4CopySize > count)
u4CopySize = count;
if (copy_to_user(buf, pucProcBuf, u4CopySize)) {
DBGLOG(INIT, WARN, "copy_to_user error\n");
i4Ret = -EFAULT;
goto freeBuf;
}
*f_pos += u4CopySize;
i4Ret = u4CopySize;
freeBuf:
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return i4Ret;
}
static ssize_t procAutoPerfCfgWrite(struct file *file, const char *buffer,
size_t count, loff_t *data)
{
uint8_t *pucProcBuf = kalMemAlloc(PROC_MAX_BUF_SIZE, VIR_MEM_TYPE);
uint32_t u4CoreNum = 0;
uint32_t u4CoreFreq = 0;
uint8_t *temp = NULL;
uint32_t u4CopySize = PROC_MAX_BUF_SIZE;
uint8_t i = 0;
uint32_t u4ForceEnable = 0;
uint8_t aucBuf[32];
int32_t i4Ret = 0;
if (buffer == NULL || pucProcBuf == NULL)
goto freeBuf;
u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1);
kalMemZero(pucProcBuf, PROC_MAX_BUF_SIZE);
if (copy_from_user(pucProcBuf, buffer, u4CopySize)) {
DBGLOG(INIT, WARN, "copy_from_user error\n");
i4Ret = -EFAULT;
goto freeBuf;
}
pucProcBuf[u4CopySize] = '\0';
temp = pucProcBuf;
i = sscanf(temp, "%d:%d", &u4CoreNum, &u4CoreFreq);
if (i == 2) {
DBGLOG(INIT, INFO, "u4CoreNum:%d, u4CoreFreq:%d\n", u4CoreNum,
u4CoreFreq);
kalSetCpuNumFreq(u4CoreNum, u4CoreFreq);
i4Ret = u4CopySize;
goto freeBuf;
}
if (strlen(temp) > sizeof(aucBuf)) {
DBGLOG(INIT, WARN,
"input string(%s) len is too long, over %d\n",
pucProcBuf, (uint32_t) sizeof(aucBuf));
i4Ret = -EFAULT;
goto freeBuf;
}
i = sscanf(temp, "%11s:%d", aucBuf, &u4ForceEnable);
if ((i == 2) && strstr(aucBuf, "ForceEnable")) {
kalPerMonSetForceEnableFlag(u4ForceEnable);
i4Ret = u4CopySize;
goto freeBuf;
}
DBGLOG(INIT, WARN, "parameter format should be ForceEnable:0 or 1\n");
i4Ret = -EFAULT;
freeBuf:
if (pucProcBuf)
kalMemFree(pucProcBuf, VIR_MEM_TYPE, PROC_MAX_BUF_SIZE);
return i4Ret;
}
static DEFINE_PROC_OPS_STRUCT(auto_perf_ops) = {
DEFINE_PROC_OPS_OWNER(THIS_MODULE)
DEFINE_PROC_OPS_READ(procAutoPerfCfgRead)
DEFINE_PROC_OPS_WRITE(procAutoPerfCfgWrite)
};
int32_t procInitFs(void)
{
struct proc_dir_entry *prEntry;
g_NextDriverReadLen = 0;
if (init_net.proc_net == (struct proc_dir_entry *)NULL) {
DBGLOG(INIT, ERROR, "init proc fs fail: proc_net == NULL\n");
return -ENOENT;
}
/*
* Directory: Root (/proc/net/wlan0)
*/
gprProcRoot = proc_mkdir(PROC_ROOT_NAME, init_net.proc_net);
if (!gprProcRoot) {
DBGLOG(INIT, ERROR, "gprProcRoot == NULL\n");
return -ENOENT;
}
proc_set_user(gprProcRoot, KUIDT_INIT(PROC_UID_SHELL),
KGIDT_INIT(PROC_GID_WIFI));
prEntry =
proc_create(PROC_DBG_LEVEL_NAME, 0660, gprProcRoot, &dbglevel_ops);
if (prEntry == NULL) {
DBGLOG(INIT, ERROR,
"Unable to create /proc entry dbgLevel\n\r");
return -1;
}
proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL),
KGIDT_INIT(PROC_GID_WIFI));
prEntry =
proc_create(PROC_AUTO_PERF_CFG, 0660, gprProcRoot, &auto_perf_ops);
if (prEntry == NULL) {
DBGLOG(INIT, ERROR, "Unable to create /proc entry %s/n",
PROC_AUTO_PERF_CFG);
return -1;
}
proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL),
KGIDT_INIT(PROC_GID_WIFI));
return 0;
} /* end of procInitProcfs() */
int32_t procUninitProcFs(void)
{
#if KERNEL_VERSION(3, 9, 0) <= LINUX_VERSION_CODE
remove_proc_subtree(PROC_AUTO_PERF_CFG, gprProcRoot);
remove_proc_subtree(PROC_DBG_LEVEL_NAME, gprProcRoot);
/*
* move PROC_ROOT_NAME to last since it's root directory of the others
* incorrect sequence would cause use-after-free error
*/
remove_proc_subtree(PROC_ROOT_NAME, init_net.proc_net);
#else
remove_proc_entry(PROC_AUTO_PERF_CFG, gprProcRoot);
remove_proc_entry(PROC_DBG_LEVEL_NAME, gprProcRoot);
/*
* move PROC_ROOT_NAME to last since it's root directory of the others
* incorrect sequence would cause use-after-free error
*/
remove_proc_entry(PROC_ROOT_NAME, init_net.proc_net);
#endif
return 0;
}
/*----------------------------------------------------------------------------*/
/*!
* \brief This function clean up a PROC fs created by procInitProcfs().
*
* \param[in] prDev Pointer to the struct net_device.
* \param[in] pucDevName Pointer to the name of net_device.
*
* \return N/A
*/
/*----------------------------------------------------------------------------*/
int32_t procRemoveProcfs(void)
{
remove_proc_entry(PROC_MCR_ACCESS, gprProcRoot);
remove_proc_entry(PROC_DRIVER_CMD, gprProcRoot);
remove_proc_entry(PROC_CFG, gprProcRoot);
remove_proc_entry(PROC_EFUSE_DUMP, gprProcRoot);
remove_proc_entry(PROC_GET_TXPWR_TBL, gprProcRoot);
remove_proc_entry(PROC_PKT_DELAY_DBG, gprProcRoot);
remove_proc_entry(PROC_COUNTRY, gprProcRoot);
#if CFG_SUPPORT_SET_CAM_BY_PROC
remove_proc_entry(PROC_SET_CAM, gprProcRoot);
#endif
#ifdef CFG_GET_TEMPURATURE
remove_proc_entry(PROC_GET_TEMPETATURE, gprProcRoot);
#endif
#if CFG_SUPPORT_DEBUG_FS
remove_proc_entry(PROC_ROAM_PARAM, gprProcRoot);
#endif
#if CFG_SUPPORT_CSI
remove_proc_entry(PROC_CSI_DATA_NAME, gprProcRoot);
#endif
#if CFG_DISCONN_DEBUG_FEATURE
remove_proc_entry(PROC_DISCONN_INFO, gprProcRoot);
#endif
return 0;
} /* end of procRemoveProcfs() */
int32_t procCreateFsEntry(struct GLUE_INFO *prGlueInfo)
{
struct proc_dir_entry *prEntry;
DBGLOG(INIT, INFO, "[%s]\n", __func__);
g_prGlueInfo_proc = prGlueInfo;
prEntry = proc_create(PROC_MCR_ACCESS, 0660, gprProcRoot, &mcr_ops);
if (prEntry == NULL) {
DBGLOG(INIT, ERROR, "Unable to create /proc entry mcr\n\r");
return -1;
}
prEntry =
proc_create(PROC_PKT_DELAY_DBG, 0660, gprProcRoot,
&proc_pkt_delay_dbg_ops);
if (prEntry == NULL) {
DBGLOG(INIT, ERROR,
"Unable to create /proc entry pktDelay\n\r");
return -1;
}
proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL),
KGIDT_INIT(PROC_GID_WIFI));
#if CFG_SUPPORT_SET_CAM_BY_PROC
prEntry =
proc_create(PROC_SET_CAM, 0660, gprProcRoot, &proc_set_cam_ops);
if (prEntry == NULL) {
DBGLOG(INIT, ERROR, "Unable to create /proc entry SetCAM\n\r");
return -1;
}
proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL),
KGIDT_INIT(PROC_GID_WIFI));
#endif
#if CFG_SUPPORT_DEBUG_FS
prEntry = proc_create(PROC_ROAM_PARAM, 0660, gprProcRoot, &roam_ops);
if (prEntry == NULL) {
DBGLOG(INIT, ERROR,
"Unable to create /proc entry roam_param\n\r");
return -1;
}
#endif
prEntry = proc_create(PROC_COUNTRY, 0660, gprProcRoot, &country_ops);
if (prEntry == NULL) {
DBGLOG(INIT, ERROR, "Unable to create /proc entry country\n\r");
return -1;
}
#if CFG_SUPPORT_EASY_DEBUG
prEntry =
proc_create(PROC_DRIVER_CMD, 0660, gprProcRoot, &drivercmd_ops);
if (prEntry == NULL) {
DBGLOG(INIT, ERROR,
"Unable to create /proc entry for driver command\n\r");
return -1;
}
prEntry = proc_create(PROC_CFG, 0660, gprProcRoot, &cfg_ops);
if (prEntry == NULL) {
DBGLOG(INIT, ERROR,
"Unable to create /proc entry for driver cfg\n\r");
return -1;
}
prEntry =
proc_create(PROC_EFUSE_DUMP, 0660, gprProcRoot, &efusedump_ops);
if (prEntry == NULL) {
DBGLOG(INIT, ERROR, "Unable to create /proc entry efuse\n\r");
return -1;
}
#endif
prEntry = proc_create(PROC_GET_TXPWR_TBL, 0660, gprProcRoot,
&get_txpwr_tbl_ops);
if (prEntry == NULL) {
DBGLOG(INIT, ERROR,
"Unable to create /proc entry TXPWR Table\n\r");
return -1;
}
#ifdef CFG_GET_TEMPURATURE
prEntry = proc_create(PROC_GET_TEMPETATURE, 0660, gprProcRoot,
&get_temperature_ops);
if (prEntry == NULL) {
DBGLOG(INIT, ERROR, "Unable to create /proc entry efuse\n\r");
return -1;
}
#endif
#if CFG_SUPPORT_CSI
prEntry =
proc_create(PROC_CSI_DATA_NAME, 0660,
gprProcRoot, &csidata_ops);
if (prEntry == NULL) {
DBGLOG(INIT, ERROR,
"[CSI] Unable to create /proc entry csidata\n\r");
return -1;
}
#endif
#if CFG_DISCONN_DEBUG_FEATURE
prEntry = proc_create(PROC_DISCONN_INFO, 0660, gprProcRoot,
&disconn_info_ops);
if (prEntry == NULL) {
DBGLOG(INIT, ERROR,
"Unable to create /proc entry disconn_info\n\r");
return -1;
}
#endif
return 0;
}
#if 0
/*----------------------------------------------------------------------------*/
/*!
* \brief The PROC function for reading Driver Status to User Space.
*
* \param[in] page Buffer provided by kernel.
* \param[in out] start Start Address to read(3 methods).
* \param[in] off Offset.
* \param[in] count Allowable number to read.
* \param[out] eof End of File indication.
* \param[in] data Pointer to the private data structure.
*
* \return number of characters print to the buffer from User Space.
*/
/*----------------------------------------------------------------------------*/
static int procDrvStatusRead(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct GLUE_INFO *prGlueInfo = ((struct net_device *)data)->priv;
char *p = page;
uint32_t u4Count;
GLUE_SPIN_LOCK_DECLARATION();
ASSERT(data);
/* Kevin: Apply PROC read method 1. */
if (off != 0)
return 0; /* To indicate end of file. */
SNPRINTF(p, page, ("GLUE LAYER STATUS:"));
SNPRINTF(p, page, ("\n=================="));
SNPRINTF(p, page,
("\n* Number of Pending Frames: %ld\n",
prGlueInfo->u4TxPendingFrameNum));
GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM);
wlanoidQueryDrvStatusForLinuxProc(prGlueInfo->prAdapter, p, &u4Count);
GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM);
u4Count += (uint32_t) (p - page);
*eof = 1;
return (int)u4Count;
} /* end of procDrvStatusRead() */
/*----------------------------------------------------------------------------*/
/*!
* \brief The PROC function for reading Driver RX Statistic Counters
* to User Space.
*
* \param[in] page Buffer provided by kernel.
* \param[in out] start Start Address to read(3 methods).
* \param[in] off Offset.
* \param[in] count Allowable number to read.
* \param[out] eof End of File indication.
* \param[in] data Pointer to the private data structure.
*
* \return number of characters print to the buffer from User Space.
*/
/*----------------------------------------------------------------------------*/
static int procRxStatisticsRead(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct GLUE_INFO *prGlueInfo = ((struct net_device *)data)->priv;
char *p = page;
uint32_t u4Count;
GLUE_SPIN_LOCK_DECLARATION();
ASSERT(data);
/* Kevin: Apply PROC read method 1. */
if (off != 0)
return 0; /* To indicate end of file. */
SNPRINTF(p, page, ("RX STATISTICS (Write 1 to clear):"));
SNPRINTF(p, page, ("\n=================================\n"));
GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM);
wlanoidQueryRxStatisticsForLinuxProc(prGlueInfo->prAdapter, p,
&u4Count);
GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM);
u4Count += (uint32_t) (p - page);
*eof = 1;
return (int)u4Count;
} /* end of procRxStatisticsRead() */
/*----------------------------------------------------------------------------*/
/*!
* \brief The PROC function for reset Driver RX Statistic Counters.
*
* \param[in] file pointer to file.
* \param[in] buffer Buffer from user space.
* \param[in] count Number of characters to write
* \param[in] data Pointer to the private data structure.
*
* \return number of characters write from User Space.
*/
/*----------------------------------------------------------------------------*/
static int procRxStatisticsWrite(struct file *file, const char *buffer,
unsigned long count, void *data)
{
struct GLUE_INFO *prGlueInfo = ((struct net_device *)data)->priv;
/* + 1 for "\0" */
char acBuf[PROC_RX_STATISTICS_MAX_USER_INPUT_LEN + 1];
uint32_t u4CopySize;
uint32_t u4ClearCounter;
int32_t rv;
GLUE_SPIN_LOCK_DECLARATION();
ASSERT(data);
u4CopySize =
(count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1);
copy_from_user(acBuf, buffer, u4CopySize);
acBuf[u4CopySize] = '\0';
rv = kstrtoint(acBuf, 0, &u4ClearCounter);
if (rv == 1) {
if (u4ClearCounter == 1) {
GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM);
wlanoidSetRxStatisticsForLinuxProc(prGlueInfo->
prAdapter);
GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM);
}
}
return count;
} /* end of procRxStatisticsWrite() */
/*----------------------------------------------------------------------------*/
/*!
* \brief The PROC function for reading Driver TX Statistic Counters
* to User Space.
*
* \param[in] page Buffer provided by kernel.
* \param[in out] start Start Address to read(3 methods).
* \param[in] off Offset.
* \param[in] count Allowable number to read.
* \param[out] eof End of File indication.
* \param[in] data Pointer to the private data structure.
*
* \return number of characters print to the buffer from User Space.
*/
/*----------------------------------------------------------------------------*/
static int procTxStatisticsRead(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
struct GLUE_INFO *prGlueInfo = ((struct net_device *)data)->priv;
char *p = page;
uint32_t u4Count;
GLUE_SPIN_LOCK_DECLARATION();
ASSERT(data);
/* Kevin: Apply PROC read method 1. */
if (off != 0)
return 0; /* To indicate end of file. */
SNPRINTF(p, page, ("TX STATISTICS (Write 1 to clear):"));
SNPRINTF(p, page, ("\n=================================\n"));
GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM);
wlanoidQueryTxStatisticsForLinuxProc(prGlueInfo->prAdapter, p,
&u4Count);
GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM);
u4Count += (uint32_t) (p - page);
*eof = 1;
return (int)u4Count;
} /* end of procTxStatisticsRead() */
/*----------------------------------------------------------------------------*/
/*!
* \brief The PROC function for reset Driver TX Statistic Counters.
*
* \param[in] file pointer to file.
* \param[in] buffer Buffer from user space.
* \param[in] count Number of characters to write
* \param[in] data Pointer to the private data structure.
*
* \return number of characters write from User Space.
*/
/*----------------------------------------------------------------------------*/
static int procTxStatisticsWrite(struct file *file, const char *buffer,
unsigned long count, void *data)
{
struct GLUE_INFO *prGlueInfo = ((struct net_device *)data)->priv;
/* + 1 for "\0" */
char acBuf[PROC_RX_STATISTICS_MAX_USER_INPUT_LEN + 1];
uint32_t u4CopySize;
uint32_t u4ClearCounter;
int32_t rv;
GLUE_SPIN_LOCK_DECLARATION();
ASSERT(data);
u4CopySize =
(count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1);
copy_from_user(acBuf, buffer, u4CopySize);
acBuf[u4CopySize] = '\0';
rv = kstrtoint(acBuf, 0, &u4ClearCounter);
if (rv == 1) {
if (u4ClearCounter == 1) {
GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM);
wlanoidSetTxStatisticsForLinuxProc(prGlueInfo->
prAdapter);
GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM);
}
}
return count;
} /* end of procTxStatisticsWrite() */
#endif
#ifdef FW_CFG_SUPPORT
#define MAX_CFG_OUTPUT_BUF_LENGTH 1024
static uint8_t aucCfgBuf[CMD_FORMAT_V1_LENGTH];
static uint8_t aucCfgQueryKey[MAX_CMD_NAME_MAX_LENGTH];
static uint8_t aucCfgOutputBuf[MAX_CFG_OUTPUT_BUF_LENGTH];
static ssize_t cfgRead(struct file *filp, char __user *buf, size_t count,
loff_t *f_pos)
{
uint32_t rStatus = WLAN_STATUS_FAILURE;
uint8_t *temp = &aucCfgOutputBuf[0];
uint32_t u4CopySize = 0;
struct CMD_HEADER cmdV1Header;
struct CMD_FORMAT_V1 *pr_cmd_v1 =
(struct CMD_FORMAT_V1 *)cmdV1Header.buffer;
/* if *f_pos > 0, we should return 0 to make cat command exit */
if (*f_pos > 0 || gprGlueInfo == NULL)
return 0;
if (!kalStrLen(aucCfgQueryKey))
return 0;
kalMemSet(aucCfgOutputBuf, 0, MAX_CFG_OUTPUT_BUF_LENGTH);
SNPRINTF(temp, sizeof(aucCfgOutputBuf) - kalStrLen(aucCfgOutputBuf),
("\nprocCfgRead() %s:\n", aucCfgQueryKey));
/* send to FW */
cmdV1Header.cmdVersion = CMD_VER_1;
cmdV1Header.cmdType = CMD_TYPE_QUERY;
cmdV1Header.itemNum = 1;
cmdV1Header.cmdBufferLen = sizeof(struct CMD_FORMAT_V1);
kalMemSet(cmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH);
pr_cmd_v1->itemStringLength = kalStrLen(aucCfgQueryKey);
kalMemCopy(pr_cmd_v1->itemString, aucCfgQueryKey,
kalStrLen(aucCfgQueryKey));
rStatus = kalIoctl(gprGlueInfo,
wlanoidQueryCfgRead,
(void *)&cmdV1Header,
sizeof(cmdV1Header), TRUE, TRUE, TRUE, &u4CopySize);
if (rStatus == WLAN_STATUS_FAILURE)
DBGLOG(INIT, ERROR,
"kalIoctl wlanoidQueryCfgRead fail 0x%x\n",
rStatus);
SNPRINTF(temp, sizeof(aucCfgOutputBuf) - kalStrLen(aucCfgOutputBuf),
("%s\n", cmdV1Header.buffer));
u4CopySize = kalStrLen(aucCfgOutputBuf);
if (u4CopySize > count)
u4CopySize = count;
if (copy_to_user(buf, aucCfgOutputBuf, u4CopySize))
DBGLOG(INIT, ERROR, "copy to user failed\n");
*f_pos += u4CopySize;
return (ssize_t) u4CopySize;
}
static ssize_t cfgWrite(struct file *filp, const char __user *buf,
size_t count, loff_t *f_pos)
{
/* echo xxx xxx > /proc/net/wlan/cfg */
uint8_t i = 0;
uint32_t u4CopySize = sizeof(aucCfgBuf);
uint8_t token_num = 1;
if (count <= 0) {
DBGLOG(INIT, ERROR, "wrong copy size\n");
return -EFAULT;
}
kalMemSet(aucCfgBuf, 0, u4CopySize);
u4CopySize = (count < u4CopySize) ? count : (u4CopySize - 1);
if (copy_from_user(aucCfgBuf, buf, u4CopySize)) {
DBGLOG(INIT, ERROR, "copy from user failed\n");
return -EFAULT;
}
aucCfgBuf[u4CopySize] = '\0';
for (i = 0; i < u4CopySize; i++) {
if (aucCfgBuf[i] == ' ') {
token_num++;
break;
}
}
if (token_num == 1) {
kalMemSet(aucCfgQueryKey, 0, sizeof(aucCfgQueryKey));
u4CopySize = (u4CopySize < sizeof(aucCfgQueryKey)) ?
u4CopySize : sizeof(aucCfgQueryKey);
/* remove the 0x0a */
memcpy(aucCfgQueryKey, aucCfgBuf, u4CopySize);
if (aucCfgQueryKey[u4CopySize - 1] == 0x0a)
aucCfgQueryKey[u4CopySize - 1] = '\0';
} else {
wlanFwCfgParse(gprGlueInfo->prAdapter, aucCfgBuf);
}
return count;
}
static const struct file_operations fwcfg_ops = {
.owner = THIS_MODULE,
.read = cfgRead,
.write = cfgWrite,
};
int32_t cfgRemoveProcEntry(void)
{
remove_proc_entry(PROC_CFG_NAME, gprProcRoot);
return 0;
}
int32_t cfgCreateProcEntry(struct GLUE_INFO *prGlueInfo)
{
struct proc_dir_entry *prEntry;
prGlueInfo->pProcRoot = gprProcRoot;
gprGlueInfo = prGlueInfo;
prEntry = proc_create(PROC_CFG_NAME, 0660, gprProcRoot, &fwcfg_ops);
if (prEntry == NULL) {
DBGLOG(INIT, ERROR, "Unable to create /proc entry cfg\n\r");
return -1;
}
proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL),
KGIDT_INIT(PROC_GID_WIFI));
return 0;
}
#endif