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

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
......@@ -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);
......
......@@ -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;
......
......@@ -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
......
......@@ -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);
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment