Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,76 @@ static ssize_t mwl_debugfs_txpwrlmt_read(struct file *file,
priv->txpwrlmt_data.len);
}

static ssize_t mwl_debugfs_txpwrlmt_file_read(struct file *file,
char __user *ubuf,
size_t count, loff_t *ppos)
{
struct mwl_priv *priv = (struct mwl_priv *)file->private_data;

const u32 txpwr_cfg_sig = cpu_to_le32(TXPWRLMT_CFG_SIGNATURE);
const u32 txpwr_cfg_ver = 0;
// The binary bytes take 2 chars and one space/nl plus some
// for the header.
int size = (SYSADPT_TXPWRLMT_CFG_BUF_SIZE * 3) + 40;
char *buf = kzalloc(size, GFP_KERNEL);
char *p = buf;
int len = 0;
int remain = priv->txpwrlmt_data.len;
const char *tblp = priv->txpwrlmt_data.buf;

ssize_t ret = 0;

if (!p)
return -ENOMEM;

len += scnprintf(p + len, size - len, "%*ph\n",
TXPWRLMT_CFG_SIG_LEN, &txpwr_cfg_sig);
len += scnprintf(p + len, size - len, "%*ph\n",
TXPWRLMT_CFG_VERSION_INFO_LEN, &txpwr_cfg_ver);

while (remain > sizeof(struct mwl_txpwrlmt_cfg_entry_hdr)) {
struct mwl_txpwrlmt_cfg_entry_hdr* subband_hdr =
(struct mwl_txpwrlmt_cfg_entry_hdr*)tblp;
u16 subband_len = le16_to_cpu(subband_hdr->len);
len += scnprintf(p + len, size - len, "\n%*ph\n",
sizeof(struct mwl_txpwrlmt_cfg_entry_hdr),
tblp);
tblp += sizeof(struct mwl_txpwrlmt_cfg_entry_hdr);
remain -= sizeof(struct mwl_txpwrlmt_cfg_entry_hdr);

// TODO(nhed): maybe add more sanity checks?
while (subband_len > 0) {
u16 hexd_line_cnt = min(subband_len, (u16)32);
len += scnprintf(p + len, size - len, "%*ph\n",
hexd_line_cnt, tblp);
tblp += hexd_line_cnt;
remain -= hexd_line_cnt;
subband_len -= hexd_line_cnt;
}

// Not sure why `\n` delimiters are added between subbands
// into the binary data buffer txpwrlmt_data.buf by
// mwl_fwcmd_get_txpwrlmt_cfg_data() but since we need to skip
// them we may as well test for them.
if (*tblp != '\n') {
printk("Unexpected lack of subband delimiter(s)\n");
ret = -EIO;
goto cleanup;
}
tblp++;
remain--;
}
len += scnprintf(p + len, size - len, "\n");
ret = simple_read_from_buffer(ubuf, count, ppos, p, len);

cleanup:
if (buf) {
kfree(buf);
}

return ret;
}

static ssize_t mwl_debugfs_tx_amsdu_read(struct file *file,
char __user *ubuf,
size_t count, loff_t *ppos)
Expand Down Expand Up @@ -2139,6 +2209,7 @@ MWLWIFI_DEBUGFS_FILE_READ_OPS(ampdu);
MWLWIFI_DEBUGFS_FILE_READ_OPS(stnid);
MWLWIFI_DEBUGFS_FILE_READ_OPS(device_pwrtbl);
MWLWIFI_DEBUGFS_FILE_READ_OPS(txpwrlmt);
MWLWIFI_DEBUGFS_FILE_READ_OPS(txpwrlmt_file);
MWLWIFI_DEBUGFS_FILE_OPS(tx_amsdu);
MWLWIFI_DEBUGFS_FILE_OPS(dump_hostcmd);
MWLWIFI_DEBUGFS_FILE_OPS(dump_probe);
Expand Down Expand Up @@ -2177,6 +2248,7 @@ void mwl_debugfs_init(struct ieee80211_hw *hw)
MWLWIFI_DEBUGFS_ADD_FILE(stnid);
MWLWIFI_DEBUGFS_ADD_FILE(device_pwrtbl);
MWLWIFI_DEBUGFS_ADD_FILE(txpwrlmt);
MWLWIFI_DEBUGFS_ADD_FILE(txpwrlmt_file);
MWLWIFI_DEBUGFS_ADD_FILE(tx_amsdu);
MWLWIFI_DEBUGFS_ADD_FILE(dump_hostcmd);
MWLWIFI_DEBUGFS_ADD_FILE(dump_probe);
Expand Down
58 changes: 48 additions & 10 deletions hif/fwcmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -915,16 +915,23 @@ static u16 mwl_fwcmd_parse_txpwrlmt_cfg(const u8 *src, size_t len,
continue;
}

if (isxdigit(*ptr)) {
if (isxdigit(ptr[0]) && isxdigit(ptr[1])) {
byte_str[0] = *ptr++;
byte_str[1] = *ptr++;
kstrtol(byte_str, 16, &res);
*dptr++ = res;
} else {
ptr++;
// any failure to parse binary data in the hex
// format is complete failure.
return -1;
}
}

// Not able to parse the requested bytes - complete failure.
if((dptr - dst) != parse_len){
return -1;
}

return (ptr - src);
}

Expand Down Expand Up @@ -3699,7 +3706,8 @@ int mwl_fwcmd_set_txpwrlmt_cfg_data(struct ieee80211_hw *hw)
struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_txpwrlmt_cfg *pcmd;
struct mwl_txpwrlmt_cfg_entry_hdr hdr;
u16 id, parsed_len, size;
u16 id, size;
s16 parsed_len;
__le32 txpwr_cfg_sig;
u8 version[TXPWRLMT_CFG_VERSION_INFO_LEN];
const u8 *ptr;
Expand All @@ -3714,21 +3722,32 @@ int mwl_fwcmd_set_txpwrlmt_cfg_data(struct ieee80211_hw *hw)
parsed_len = mwl_fwcmd_parse_txpwrlmt_cfg(ptr, size,
TXPWRLMT_CFG_SIG_LEN,
(u8 *)&txpwr_cfg_sig);
ptr += parsed_len;
size -= parsed_len;

if (le32_to_cpu(txpwr_cfg_sig) != TXPWRLMT_CFG_SIGNATURE) {
if (parsed_len < 0 ||
le32_to_cpu(txpwr_cfg_sig) != TXPWRLMT_CFG_SIGNATURE) {
wiphy_err(hw->wiphy,
"txpwrlmt config signature mismatch\n");
release_firmware(priv->txpwrlmt_file);
priv->txpwrlmt_file = NULL;
return 0;
}

ptr += parsed_len;
size -= parsed_len;

/* Parsing TxPwrLmit Conf file Version */
parsed_len = mwl_fwcmd_parse_txpwrlmt_cfg(ptr, size,
TXPWRLMT_CFG_VERSION_INFO_LEN,
version);

if (parsed_len < 0) {
wiphy_err(hw->wiphy,
"txpwrlmt config failed to read version\n");
release_firmware(priv->txpwrlmt_file);
priv->txpwrlmt_file = NULL;
return 0;
}

ptr += parsed_len;
size -= parsed_len;

Expand All @@ -3740,10 +3759,19 @@ int mwl_fwcmd_set_txpwrlmt_cfg_data(struct ieee80211_hw *hw)
parsed_len = mwl_fwcmd_parse_txpwrlmt_cfg(ptr, size,
parsed_len,
(u8 *)&hdr);

if (parsed_len < 0) {
wiphy_err(hw->wiphy,
"txpwrlmt config failed to parse "
"subband header\n");
release_firmware(priv->txpwrlmt_file);
priv->txpwrlmt_file = NULL;
return 0;
}

ptr += parsed_len;
size -= parsed_len;
data_len = le16_to_cpu(hdr.len) -
sizeof(struct mwl_txpwrlmt_cfg_entry_hdr);
data_len = le16_to_cpu(hdr.len);

pcmd = (struct hostcmd_cmd_txpwrlmt_cfg *)&priv->pcmd_buf[0];

Expand All @@ -3758,6 +3786,16 @@ int mwl_fwcmd_set_txpwrlmt_cfg_data(struct ieee80211_hw *hw)
/* Parsing tx pwr cfg subband header info */
parsed_len = mwl_fwcmd_parse_txpwrlmt_cfg(ptr, size,
data_len, pcmd->data);

if (parsed_len < 0) {
wiphy_err(hw->wiphy,
"txpwrlmt config failed to parse subband data\n");
release_firmware(priv->txpwrlmt_file);
priv->txpwrlmt_file = NULL;
mutex_unlock(&priv->fwcmd_mutex);
return 0;
}

ptr += parsed_len;
size -= parsed_len;

Expand Down Expand Up @@ -3810,8 +3848,6 @@ int mwl_fwcmd_get_txpwrlmt_cfg_data(struct ieee80211_hw *hw)
return -EIO;
}

mutex_unlock(&priv->fwcmd_mutex);

subband_len = le16_to_cpu(pcmd->cmd_hdr.len) -
sizeof(struct hostcmd_header) - 2;
if (total_len <= SYSADPT_TXPWRLMT_CFG_BUF_SIZE) {
Expand All @@ -3827,6 +3863,8 @@ int mwl_fwcmd_get_txpwrlmt_cfg_data(struct ieee80211_hw *hw)
wiphy_err(hw->wiphy,
"TxPwrLmt cfg buf size is not enough\n");
}

mutex_unlock(&priv->fwcmd_mutex);
}

return 0;
Expand Down