Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rsi: Add support for antenna selection

RSI 9113 device supports single antenna for tx and rx. Support for using
external is added. This can be configured from user space using iw.

Signed-off-by: Prameela Rani Garnepudi <prameela.j04cs@gmail.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>

authored by

Prameela Rani Garnepudi and committed by
Kalle Valo
4edbcd1a 8b36de8c

+117
+78
drivers/net/wireless/rsi/rsi_91x_mac80211.c
··· 1075 1075 return 0; 1076 1076 } 1077 1077 1078 + /** 1079 + * rsi_mac80211_set_antenna() - This function is used to configure 1080 + * tx and rx antennas. 1081 + * @hw: Pointer to the ieee80211_hw structure. 1082 + * @tx_ant: Bitmap for tx antenna 1083 + * @rx_ant: Bitmap for rx antenna 1084 + * 1085 + * Return: 0 on success, Negative error code on failure. 1086 + */ 1087 + static int rsi_mac80211_set_antenna(struct ieee80211_hw *hw, 1088 + u32 tx_ant, u32 rx_ant) 1089 + { 1090 + struct rsi_hw *adapter = hw->priv; 1091 + struct rsi_common *common = adapter->priv; 1092 + u8 antenna = 0; 1093 + 1094 + if (tx_ant > 1 || rx_ant > 1) { 1095 + rsi_dbg(ERR_ZONE, 1096 + "Invalid antenna selection (tx: %d, rx:%d)\n", 1097 + tx_ant, rx_ant); 1098 + rsi_dbg(ERR_ZONE, 1099 + "Use 0 for int_ant, 1 for ext_ant\n"); 1100 + return -EINVAL; 1101 + } 1102 + 1103 + rsi_dbg(INFO_ZONE, "%s: Antenna map Tx %x Rx %d\n", 1104 + __func__, tx_ant, rx_ant); 1105 + 1106 + mutex_lock(&common->mutex); 1107 + 1108 + antenna = tx_ant ? ANTENNA_SEL_UFL : ANTENNA_SEL_INT; 1109 + if (common->ant_in_use != antenna) 1110 + if (rsi_set_antenna(common, antenna)) 1111 + goto fail_set_antenna; 1112 + 1113 + rsi_dbg(INFO_ZONE, "(%s) Antenna path configured successfully\n", 1114 + tx_ant ? "UFL" : "INT"); 1115 + 1116 + common->ant_in_use = antenna; 1117 + 1118 + mutex_unlock(&common->mutex); 1119 + 1120 + return 0; 1121 + 1122 + fail_set_antenna: 1123 + rsi_dbg(ERR_ZONE, "%s: Failed.\n", __func__); 1124 + mutex_unlock(&common->mutex); 1125 + return -EINVAL; 1126 + } 1127 + 1128 + /** 1129 + * rsi_mac80211_get_antenna() - This function is used to configure 1130 + * tx and rx antennas. 1131 + * 1132 + * @hw: Pointer to the ieee80211_hw structure. 1133 + * @tx_ant: Bitmap for tx antenna 1134 + * @rx_ant: Bitmap for rx antenna 1135 + * 1136 + * Return: 0 on success, -1 on failure. 1137 + */ 1138 + static int rsi_mac80211_get_antenna(struct ieee80211_hw *hw, 1139 + u32 *tx_ant, u32 *rx_ant) 1140 + { 1141 + struct rsi_hw *adapter = hw->priv; 1142 + struct rsi_common *common = adapter->priv; 1143 + 1144 + mutex_lock(&common->mutex); 1145 + 1146 + *tx_ant = (common->ant_in_use == ANTENNA_SEL_UFL) ? 1 : 0; 1147 + *rx_ant = 0; 1148 + 1149 + mutex_unlock(&common->mutex); 1150 + 1151 + return 0; 1152 + } 1153 + 1078 1154 static struct ieee80211_ops mac80211_ops = { 1079 1155 .tx = rsi_mac80211_tx, 1080 1156 .start = rsi_mac80211_start, ··· 1167 1091 .ampdu_action = rsi_mac80211_ampdu_action, 1168 1092 .sta_add = rsi_mac80211_sta_add, 1169 1093 .sta_remove = rsi_mac80211_sta_remove, 1094 + .set_antenna = rsi_mac80211_set_antenna, 1095 + .get_antenna = rsi_mac80211_get_antenna, 1170 1096 }; 1171 1097 1172 1098 /**
+33
drivers/net/wireless/rsi/rsi_91x_mgmt.c
··· 1315 1315 } 1316 1316 1317 1317 /** 1318 + * rsi_set_antenna() - This fuction send antenna configuration request 1319 + * to device 1320 + * 1321 + * @common: Pointer to the driver private structure. 1322 + * @antenna: bitmap for tx antenna selection 1323 + * 1324 + * Return: 0 on Success, negative error code on failure 1325 + */ 1326 + int rsi_set_antenna(struct rsi_common *common, u8 antenna) 1327 + { 1328 + struct rsi_mac_frame *cmd_frame; 1329 + struct sk_buff *skb; 1330 + 1331 + skb = dev_alloc_skb(FRAME_DESC_SZ); 1332 + if (!skb) { 1333 + rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", 1334 + __func__); 1335 + return -ENOMEM; 1336 + } 1337 + 1338 + memset(skb->data, 0, FRAME_DESC_SZ); 1339 + cmd_frame = (struct rsi_mac_frame *)skb->data; 1340 + 1341 + cmd_frame->desc_word[1] = cpu_to_le16(ANT_SEL_FRAME); 1342 + cmd_frame->desc_word[3] = cpu_to_le16(antenna & 0x00ff); 1343 + cmd_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12); 1344 + 1345 + skb_put(skb, FRAME_DESC_SZ); 1346 + 1347 + return rsi_send_internal_mgmt_frame(common, skb); 1348 + } 1349 + 1350 + /** 1318 1351 * rsi_handle_ta_confirm_type() - This function handles the confirm frames. 1319 1352 * @common: Pointer to the driver private structure. 1320 1353 * @msg: Pointer to received packet.
+1
drivers/net/wireless/rsi/rsi_main.h
··· 206 206 bool hw_data_qs_blocked; 207 207 208 208 int tx_power; 209 + u8 ant_in_use; 209 210 }; 210 211 211 212 struct rsi_hw {
+5
drivers/net/wireless/rsi/rsi_mgmt.h
··· 141 141 #define RSI_SUPP_FILTERS (FIF_ALLMULTI | FIF_PROBE_REQ |\ 142 142 FIF_BCN_PRBRESP_PROMISC) 143 143 144 + #define ANTENNA_SEL_INT 0x02 /* RF_OUT_2 / Integerated */ 145 + #define ANTENNA_SEL_UFL 0x03 /* RF_OUT_1 / U.FL */ 146 + 144 147 /* Rx filter word definitions */ 145 148 #define PROMISCOUS_MODE BIT(0) 146 149 #define ALLOW_DATA_ASSOC_PEER BIT(1) ··· 204 201 BG_SCAN_PROBE_REQ, 205 202 CW_MODE_REQ, 206 203 PER_CMD_PKT, 204 + ANT_SEL_FRAME = 0x20, 207 205 RADIO_PARAMS_UPDATE = 0x29 208 206 }; 209 207 ··· 330 326 int rsi_band_check(struct rsi_common *common); 331 327 int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word); 332 328 int rsi_send_radio_params_update(struct rsi_common *common); 329 + int rsi_set_antenna(struct rsi_common *common, u8 antenna); 333 330 #endif