mwifiex: add calibration data download feature
User can provide a text file containing calibration data in hex format while loading mwifiex module. It will be downloaded to firmware. eg. insmod mwifiex.ko cal_data_cfg=cal_data.conf Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
013a492ecf
commit
388ec385d5
|
@ -271,6 +271,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
|
|||
#define HostCmd_CMD_802_11_SUBSCRIBE_EVENT 0x0075
|
||||
#define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f
|
||||
#define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083
|
||||
#define HostCmd_CMD_CFG_DATA 0x008f
|
||||
#define HostCmd_CMD_VERSION_EXT 0x0097
|
||||
#define HostCmd_CMD_MEF_CFG 0x009a
|
||||
#define HostCmd_CMD_RSSI_INFO 0x00a4
|
||||
|
@ -465,6 +466,8 @@ enum P2P_MODES {
|
|||
#define MWIFIEX_CRITERIA_UNICAST BIT(1)
|
||||
#define MWIFIEX_CRITERIA_MULTICAST BIT(3)
|
||||
|
||||
#define CFG_DATA_TYPE_CAL 2
|
||||
|
||||
struct mwifiex_ie_types_header {
|
||||
__le16 type;
|
||||
__le16 len;
|
||||
|
@ -1579,6 +1582,12 @@ struct mwifiex_ie_list {
|
|||
struct mwifiex_ie ie_list[MAX_MGMT_IE_INDEX];
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_ds_802_11_cfg_data {
|
||||
__le16 action;
|
||||
__le16 type;
|
||||
__le16 data_len;
|
||||
} __packed;
|
||||
|
||||
struct host_cmd_ds_command {
|
||||
__le16 command;
|
||||
__le16 size;
|
||||
|
@ -1638,6 +1647,7 @@ struct host_cmd_ds_command {
|
|||
struct host_cmd_ds_sys_config uap_sys_config;
|
||||
struct host_cmd_ds_sta_deauth sta_deauth;
|
||||
struct host_cmd_11ac_vht_cfg vht_cfg;
|
||||
struct host_cmd_ds_802_11_cfg_data cfg_data;
|
||||
} params;
|
||||
} __packed;
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#define VERSION "1.0"
|
||||
|
||||
const char driver_version[] = "mwifiex " VERSION " (%s) ";
|
||||
static char *cal_data_cfg;
|
||||
module_param(cal_data_cfg, charp, 0);
|
||||
|
||||
/*
|
||||
* This function registers the device and performs all the necessary
|
||||
|
@ -336,6 +338,13 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
|
|||
|
||||
dev_notice(adapter->dev, "WLAN FW is active\n");
|
||||
|
||||
if (cal_data_cfg) {
|
||||
if ((request_firmware(&adapter->cal_data, cal_data_cfg,
|
||||
adapter->dev)) < 0)
|
||||
dev_err(adapter->dev,
|
||||
"Cal data request_firmware() failed\n");
|
||||
}
|
||||
|
||||
adapter->init_wait_q_woken = false;
|
||||
ret = mwifiex_init_fw(adapter);
|
||||
if (ret == -1) {
|
||||
|
@ -390,6 +399,10 @@ err_init_fw:
|
|||
pr_debug("info: %s: unregister device\n", __func__);
|
||||
adapter->if_ops.unregister_dev(adapter);
|
||||
done:
|
||||
if (adapter->cal_data) {
|
||||
release_firmware(adapter->cal_data);
|
||||
adapter->cal_data = NULL;
|
||||
}
|
||||
release_firmware(adapter->firmware);
|
||||
complete(&adapter->fw_load);
|
||||
return;
|
||||
|
|
|
@ -730,6 +730,7 @@ struct mwifiex_adapter {
|
|||
u16 max_mgmt_ie_index;
|
||||
u8 scan_delay_cnt;
|
||||
u8 empty_tx_q_cnt;
|
||||
const struct firmware *cal_data;
|
||||
|
||||
/* 11AC */
|
||||
u32 is_hw_11ac_capable;
|
||||
|
|
|
@ -1134,6 +1134,55 @@ mwifiex_cmd_mef_cfg(struct mwifiex_private *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* This function parse cal data from ASCII to hex */
|
||||
static u32 mwifiex_parse_cal_cfg(u8 *src, size_t len, u8 *dst)
|
||||
{
|
||||
u8 *s = src, *d = dst;
|
||||
|
||||
while (s - src < len) {
|
||||
if (*s && (isspace(*s) || *s == '\t')) {
|
||||
s++;
|
||||
continue;
|
||||
}
|
||||
if (isxdigit(*s)) {
|
||||
*d++ = simple_strtol(s, NULL, 16);
|
||||
s += 2;
|
||||
} else {
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
return d - dst;
|
||||
}
|
||||
|
||||
/* This function prepares command of set_cfg_data. */
|
||||
static int mwifiex_cmd_cfg_data(struct mwifiex_private *priv,
|
||||
struct host_cmd_ds_command *cmd,
|
||||
u16 cmd_action)
|
||||
{
|
||||
struct host_cmd_ds_802_11_cfg_data *cfg_data = &cmd->params.cfg_data;
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
u32 len, cal_data_offset;
|
||||
u8 *tmp_cmd = (u8 *)cmd;
|
||||
|
||||
cal_data_offset = S_DS_GEN + sizeof(*cfg_data);
|
||||
if ((adapter->cal_data->data) && (adapter->cal_data->size > 0))
|
||||
len = mwifiex_parse_cal_cfg((u8 *)adapter->cal_data->data,
|
||||
adapter->cal_data->size,
|
||||
(u8 *)(tmp_cmd + cal_data_offset));
|
||||
else
|
||||
return -1;
|
||||
|
||||
cfg_data->action = cpu_to_le16(cmd_action);
|
||||
cfg_data->type = cpu_to_le16(CFG_DATA_TYPE_CAL);
|
||||
cfg_data->data_len = cpu_to_le16(len);
|
||||
|
||||
cmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA);
|
||||
cmd->size = cpu_to_le16(S_DS_GEN + sizeof(*cfg_data) + len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function prepares the commands before sending them to the firmware.
|
||||
*
|
||||
|
@ -1152,6 +1201,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
|
|||
case HostCmd_CMD_GET_HW_SPEC:
|
||||
ret = mwifiex_cmd_get_hw_spec(priv, cmd_ptr);
|
||||
break;
|
||||
case HostCmd_CMD_CFG_DATA:
|
||||
ret = mwifiex_cmd_cfg_data(priv, cmd_ptr, cmd_action);
|
||||
break;
|
||||
case HostCmd_CMD_MAC_CONTROL:
|
||||
ret = mwifiex_cmd_mac_control(priv, cmd_ptr, cmd_action,
|
||||
data_buf);
|
||||
|
@ -1384,6 +1436,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
|
|||
*/
|
||||
int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
int ret;
|
||||
u16 enable = true;
|
||||
struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
|
||||
|
@ -1404,6 +1457,15 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
|
|||
HostCmd_ACT_GEN_SET, 0, NULL);
|
||||
if (ret)
|
||||
return -1;
|
||||
|
||||
/* Download calibration data to firmware */
|
||||
if (adapter->cal_data) {
|
||||
ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_CFG_DATA,
|
||||
HostCmd_ACT_GEN_SET, 0, NULL);
|
||||
if (ret)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read MAC address from HW */
|
||||
ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_GET_HW_SPEC,
|
||||
HostCmd_ACT_GEN_GET, 0, NULL);
|
||||
|
|
|
@ -818,6 +818,18 @@ static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* This function handles the command response of set_cfg_data */
|
||||
static int mwifiex_ret_cfg_data(struct mwifiex_private *priv,
|
||||
struct host_cmd_ds_command *resp)
|
||||
{
|
||||
if (resp->result != HostCmd_RESULT_OK) {
|
||||
dev_err(priv->adapter->dev, "Cal data cmd resp failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the command responses.
|
||||
*
|
||||
|
@ -841,6 +853,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
|
|||
case HostCmd_CMD_GET_HW_SPEC:
|
||||
ret = mwifiex_ret_get_hw_spec(priv, resp);
|
||||
break;
|
||||
case HostCmd_CMD_CFG_DATA:
|
||||
ret = mwifiex_ret_cfg_data(priv, resp);
|
||||
break;
|
||||
case HostCmd_CMD_MAC_CONTROL:
|
||||
break;
|
||||
case HostCmd_CMD_802_11_MAC_ADDRESS:
|
||||
|
|
Loading…
Reference in New Issue