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

Commit 8a279d5b authored by Amitkumar Karwar's avatar Amitkumar Karwar Committed by John W. Linville
Browse files

mwifiex: add set_antenna handler support



This enables user to set mode of Tx/Rx path using "iw set antenna"
command. For non MIMO chips, the command will be used for selecting
specific antenna or configuring antenna diversity mode.

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 83bfea42
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -941,6 +941,42 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
	return 0;
}

static int
mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
{
	struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
	struct mwifiex_private *priv = mwifiex_get_priv(adapter,
							MWIFIEX_BSS_ROLE_ANY);
	struct mwifiex_ds_ant_cfg ant_cfg;

	if (!tx_ant || !rx_ant)
		return -EOPNOTSUPP;

	if (adapter->hw_dev_mcs_support != HT_STREAM_2X2) {
		/* Not a MIMO chip. User should provide specific antenna number
		 * for Tx/Rx path or enable all antennas for diversity
		 */
		if (tx_ant != rx_ant)
			return -EOPNOTSUPP;

		if ((tx_ant & (tx_ant - 1)) &&
		    (tx_ant != BIT(adapter->number_of_antenna) - 1))
			return -EOPNOTSUPP;

		if ((tx_ant == BIT(adapter->number_of_antenna) - 1) &&
		    (priv->adapter->number_of_antenna > 1)) {
			tx_ant = RF_ANTENNA_AUTO;
			rx_ant = RF_ANTENNA_AUTO;
		}
	}

	ant_cfg.tx_ant = tx_ant;
	ant_cfg.rx_ant = rx_ant;

	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_RF_ANTENNA,
				     HostCmd_ACT_GEN_SET, 0, &ant_cfg);
}

/* cfg80211 operation handler for stop ap.
 * Function stops BSS running at uAP interface.
 */
@@ -1726,6 +1762,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
	.stop_ap = mwifiex_cfg80211_stop_ap,
	.change_beacon = mwifiex_cfg80211_change_beacon,
	.set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,
	.set_antenna = mwifiex_cfg80211_set_antenna,
};

/*
@@ -1778,6 +1815,9 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
	wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
				    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2;

	wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
	wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;

	/* Reserve space for mwifiex specific private data for BSS */
	wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);

+21 −0
Original line number Diff line number Diff line
@@ -227,6 +227,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define HostCmd_CMD_PMIC_REG_ACCESS                   0x00ad
#define HostCmd_CMD_802_11_RF_CHANNEL                 0x001d
#define HostCmd_CMD_RF_TX_PWR                         0x001e
#define HostCmd_CMD_RF_ANTENNA                        0x0020
#define HostCmd_CMD_802_11_DEAUTHENTICATE             0x0024
#define HostCmd_CMD_MAC_CONTROL                       0x0028
#define HostCmd_CMD_802_11_AD_HOC_START               0x002b
@@ -322,6 +323,12 @@ enum ENH_PS_MODES {

#define HostCmd_BSS_TYPE_MASK           0xf000

#define HostCmd_ACT_SET_RX              0x0001
#define HostCmd_ACT_SET_TX              0x0002
#define HostCmd_ACT_SET_BOTH            0x0003

#define RF_ANTENNA_AUTO                 0xFFFF

#define HostCmd_SET_SEQ_NO_BSS_INFO(seq, num, type) {   \
	(((seq) & 0x00ff) |                             \
	 (((num) & 0x000f) << 8)) |                     \
@@ -884,6 +891,18 @@ struct host_cmd_ds_rf_tx_pwr {
	u8 min_power;
} __packed;

struct host_cmd_ds_rf_ant_mimo {
	__le16 action_tx;
	__le16 tx_ant_mode;
	__le16 action_rx;
	__le16 rx_ant_mode;
};

struct host_cmd_ds_rf_ant_siso {
	__le16 action;
	__le16 ant_mode;
};

struct mwifiex_bcn_param {
	u8 bssid[ETH_ALEN];
	u8 rssi;
@@ -1370,6 +1389,8 @@ struct host_cmd_ds_command {
		struct host_cmd_ds_tx_rate_cfg tx_rate_cfg;
		struct host_cmd_ds_txpwr_cfg txp_cfg;
		struct host_cmd_ds_rf_tx_pwr txp;
		struct host_cmd_ds_rf_ant_mimo ant_mimo;
		struct host_cmd_ds_rf_ant_siso ant_siso;
		struct host_cmd_ds_802_11_ps_mode_enh psmode_enh;
		struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg;
		struct host_cmd_ds_802_11_scan scan;
+5 −0
Original line number Diff line number Diff line
@@ -277,6 +277,11 @@ struct mwifiex_ds_11n_amsdu_aggr_ctrl {
	u16 curr_buf_size;
};

struct mwifiex_ds_ant_cfg {
	u32 tx_ant;
	u32 rx_ant;
};

#define MWIFIEX_NUM_OF_CMD_BUFFER	20
#define MWIFIEX_SIZE_OF_CMD_BUFFER	2048

+37 −0
Original line number Diff line number Diff line
@@ -276,6 +276,39 @@ static int mwifiex_cmd_rf_tx_power(struct mwifiex_private *priv,
	return 0;
}

/*
 * This function prepares command to set rf antenna.
 */
static int mwifiex_cmd_rf_antenna(struct mwifiex_private *priv,
				  struct host_cmd_ds_command *cmd,
				  u16 cmd_action,
				  struct mwifiex_ds_ant_cfg *ant_cfg)
{
	struct host_cmd_ds_rf_ant_mimo *ant_mimo = &cmd->params.ant_mimo;
	struct host_cmd_ds_rf_ant_siso *ant_siso = &cmd->params.ant_siso;

	cmd->command = cpu_to_le16(HostCmd_CMD_RF_ANTENNA);

	if (cmd_action != HostCmd_ACT_GEN_SET)
		return 0;

	if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) {
		cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_mimo) +
					S_DS_GEN);
		ant_mimo->action_tx = cpu_to_le16(HostCmd_ACT_SET_TX);
		ant_mimo->tx_ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant);
		ant_mimo->action_rx = cpu_to_le16(HostCmd_ACT_SET_RX);
		ant_mimo->rx_ant_mode = cpu_to_le16((u16)ant_cfg->rx_ant);
	} else {
		cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_siso) +
					S_DS_GEN);
		ant_siso->action = cpu_to_le16(HostCmd_ACT_SET_BOTH);
		ant_siso->ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant);
	}

	return 0;
}

/*
 * This function prepares command to set Host Sleep configuration.
 *
@@ -1076,6 +1109,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
		ret = mwifiex_cmd_rf_tx_power(priv, cmd_ptr, cmd_action,
					      data_buf);
		break;
	case HostCmd_CMD_RF_ANTENNA:
		ret = mwifiex_cmd_rf_antenna(priv, cmd_ptr, cmd_action,
					     data_buf);
		break;
	case HostCmd_CMD_802_11_PS_MODE_ENH:
		ret = mwifiex_cmd_enh_power_mode(priv, cmd_ptr, cmd_action,
						 (uint16_t)cmd_oid, data_buf);
+30 −0
Original line number Diff line number Diff line
@@ -474,6 +474,33 @@ static int mwifiex_ret_rf_tx_power(struct mwifiex_private *priv,
	return 0;
}

/*
 * This function handles the command response of set rf antenna
 */
static int mwifiex_ret_rf_antenna(struct mwifiex_private *priv,
				  struct host_cmd_ds_command *resp)
{
	struct host_cmd_ds_rf_ant_mimo *ant_mimo = &resp->params.ant_mimo;
	struct host_cmd_ds_rf_ant_siso *ant_siso = &resp->params.ant_siso;
	struct mwifiex_adapter *adapter = priv->adapter;

	if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
		dev_dbg(adapter->dev,
			"RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x"
			" Rx action = 0x%x, Rx Mode = 0x%04x\n",
			le16_to_cpu(ant_mimo->action_tx),
			le16_to_cpu(ant_mimo->tx_ant_mode),
			le16_to_cpu(ant_mimo->action_rx),
			le16_to_cpu(ant_mimo->rx_ant_mode));
	else
		dev_dbg(adapter->dev,
			"RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n",
			le16_to_cpu(ant_siso->action),
			le16_to_cpu(ant_siso->ant_mode));

	return 0;
}

/*
 * This function handles the command response of set/get MAC address.
 *
@@ -874,6 +901,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
	case HostCmd_CMD_RF_TX_PWR:
		ret = mwifiex_ret_rf_tx_power(priv, resp);
		break;
	case HostCmd_CMD_RF_ANTENNA:
		ret = mwifiex_ret_rf_antenna(priv, resp);
		break;
	case HostCmd_CMD_802_11_PS_MODE_ENH:
		ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf);
		break;