Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 388ec385 authored by Amitkumar Karwar's avatar Amitkumar Karwar Committed by John W. Linville
Browse files

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: default avatarAmitkumar Karwar <akarwar@marvell.com>
Signed-off-by: default avatarBing Zhao <bzhao@marvell.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 013a492e
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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;

+13 −0
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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;
+62 −0
Original line number Diff line number Diff line
@@ -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);
+15 −0
Original line number Diff line number Diff line
@@ -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: