summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArchana Ramachandran <archanar@codeaurora.org>2016-04-20 16:57:35 -0700
committerNandini Suresh <snandini@codeaurora.org>2016-06-29 18:41:22 -0700
commitd5d2e926c87d95fdbbe169667c7693cde70eaef3 (patch)
tree05982dd6318c7511745907153cf2e9c08ee932b9
parent99bac319a8e7dd2ddf76a2d8dcaa8950b5d4e8e2 (diff)
qcacld-3.0: Dynamic antenna switch in TDLS operation
qcacld-2.0 to qcacld-3.0 propagation Add dynamic antenna mode change capability for TDLS operation. CRs-Fixed: 951596 Change-Id: Ie0b141fbebe0bfa8a173503fc0ec375095240237
-rw-r--r--core/hdd/inc/wlan_hdd_main.h2
-rw-r--r--core/hdd/inc/wlan_hdd_tdls.h9
-rw-r--r--core/hdd/src/wlan_hdd_ioctl.c9
-rw-r--r--core/hdd/src/wlan_hdd_tdls.c117
4 files changed, 137 insertions, 0 deletions
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index 0bbc37a7fbd1..072e8b6f4714 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -1259,6 +1259,8 @@ struct hdd_context_s {
int32_t tdls_fw_off_chan_mode;
bool enable_tdls_connection_tracker;
uint8_t tdls_external_peer_count;
+ bool tdls_nss_switch_in_progress;
+ int32_t tdls_teardown_peers_cnt;
#endif
void *hdd_ipa;
diff --git a/core/hdd/inc/wlan_hdd_tdls.h b/core/hdd/inc/wlan_hdd_tdls.h
index 7b770ac9e37a..4ad93bc93e2b 100644
--- a/core/hdd/inc/wlan_hdd_tdls.h
+++ b/core/hdd/inc/wlan_hdd_tdls.h
@@ -669,6 +669,9 @@ void wlan_hdd_tdls_update_rx_pkt_cnt(hdd_adapter_t *adapter,
int hdd_set_tdls_scan_type(hdd_context_t *hdd_ctx, int val);
void hdd_tdls_context_init(hdd_context_t *hdd_ctx);
void hdd_tdls_context_destroy(hdd_context_t *hdd_ctx);
+int wlan_hdd_tdls_antenna_switch(hdd_context_t *hdd_ctx,
+ hdd_adapter_t *adapter);
+
#else
static inline void hdd_tdls_notify_mode_change(hdd_adapter_t *adapter,
hdd_context_t *hddctx)
@@ -691,6 +694,12 @@ static inline void wlan_hdd_tdls_update_rx_pkt_cnt(hdd_adapter_t *adapter,
}
static inline void hdd_tdls_context_init(hdd_context_t *hdd_ctx) { }
static inline void hdd_tdls_context_destroy(hdd_context_t *hdd_ctx) { }
+
+static inline int wlan_hdd_tdls_antenna_switch(hdd_context_t *hdd_ctx,
+ hdd_adapter_t *adapter)
+{
+ return 0;
+}
#endif /* End of FEATURE_WLAN_TDLS */
#ifdef FEATURE_WLAN_DIAG_SUPPORT
diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c
index 0d6320ef665b..773951b3952d 100644
--- a/core/hdd/src/wlan_hdd_ioctl.c
+++ b/core/hdd/src/wlan_hdd_ioctl.c
@@ -6611,6 +6611,15 @@ static int drv_cmd_set_antenna_mode(hdd_adapter_t *adapter,
goto exit;
}
+ /* Check TDLS status and update antenna mode */
+ if ((QDF_STA_MODE == adapter->device_mode) &&
+ cds_is_sta_active_connection_exists() &&
+ (hdd_ctx->connected_peer_count > 0)) {
+ ret = wlan_hdd_tdls_antenna_switch(hdd_ctx, adapter);
+ if (0 != ret)
+ goto exit;
+ }
+
params.set_antenna_mode_resp =
(void *)wlan_hdd_soc_set_antenna_mode_cb;
hdd_info("Set antenna mode rx chains: %d tx chains: %d",
diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c
index e1bb1e3dd9a1..7c9cfce9f168 100644
--- a/core/hdd/src/wlan_hdd_tdls.c
+++ b/core/hdd/src/wlan_hdd_tdls.c
@@ -743,6 +743,8 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter)
/* initialize TDLS global context */
pHddCtx->connected_peer_count = 0;
+ pHddCtx->tdls_nss_switch_in_progress = false;
+ pHddCtx->tdls_teardown_peers_cnt = 0;
sme_set_tdls_power_save_prohibited(WLAN_HDD_GET_HAL_CTX(pAdapter),
pAdapter->sessionId, 0);
@@ -4068,6 +4070,17 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
return -EINVAL;
}
+ if (SIR_MAC_TDLS_TEARDOWN == action_code &&
+ pHddCtx->tdls_nss_switch_in_progress) {
+ mutex_lock(&pHddCtx->tdls_lock);
+ if (pHddCtx->tdls_teardown_peers_cnt != 0)
+ pHddCtx->tdls_teardown_peers_cnt--;
+ if (pHddCtx->tdls_teardown_peers_cnt == 0)
+ pHddCtx->tdls_nss_switch_in_progress = false;
+ mutex_unlock(&pHddCtx->tdls_lock);
+ }
+
+
if ((SIR_MAC_TDLS_DIS_REQ == action_code) ||
(SIR_MAC_TDLS_DIS_RSP == action_code)) {
/* for DIS_REQ/DIS_RSP, supplicant does not consider the return
@@ -5744,3 +5757,107 @@ int hdd_set_tdls_scan_type(hdd_context_t *hdd_ctx, int val)
return 0;
}
}
+
+/**
+ * wlan_hdd_tdls_teardown_links() - teardown tdls links
+ * @hddCtx : pointer to hdd context
+ *
+ * Return: 0 if success else non zero
+ */
+static int wlan_hdd_tdls_teardown_links(hdd_context_t *hddctx)
+{
+ uint16_t connected_tdls_peers = 0;
+ uint8_t staidx;
+ hddTdlsPeer_t *curr_peer;
+ hdd_adapter_t *adapter;
+
+ if (eTDLS_SUPPORT_NOT_ENABLED == hddctx->tdls_mode) {
+ hdd_log(LOG1, "TDLS mode is disabled OR not enabled in FW");
+ return 0;
+ }
+
+ adapter = hdd_get_adapter(hddctx, QDF_STA_MODE);
+
+ if (adapter == NULL) {
+ hdd_log(LOGE, "Station Adapter Not Found");
+ return 0;
+ }
+
+ connected_tdls_peers = wlan_hdd_tdls_connected_peers(adapter);
+
+ if (!connected_tdls_peers)
+ return 0;
+
+ for (staidx = 0; staidx < hddctx->max_num_tdls_sta;
+ staidx++) {
+ if (!hddctx->tdlsConnInfo[staidx].staId)
+ continue;
+
+ curr_peer = wlan_hdd_tdls_find_all_peer(hddctx,
+ hddctx->tdlsConnInfo[staidx].peerMac.bytes);
+
+ if (!curr_peer)
+ continue;
+
+ hdd_log(LOG1, "indicate TDLS teardown (staId %d)",
+ curr_peer->staId);
+
+ wlan_hdd_tdls_indicate_teardown(
+ curr_peer->pHddTdlsCtx->pAdapter,
+ curr_peer,
+ eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
+ mutex_lock(&hddctx->tdls_lock);
+ hddctx->tdls_teardown_peers_cnt++;
+ mutex_unlock(&hddctx->tdls_lock);
+ }
+ mutex_lock(&hddctx->tdls_lock);
+ if (hddctx->tdls_teardown_peers_cnt >= 1)
+ hddctx->tdls_nss_switch_in_progress = true;
+ hdd_log(LOGE, "TDLS peers to be torn down = %d",
+ hddctx->tdls_teardown_peers_cnt);
+ mutex_unlock(&hddctx->tdls_lock);
+ hdd_log(LOGE, "TDLS teardown for antenna switch operation starts");
+ return -EAGAIN;
+}
+
+/**
+ * wlan_hdd_tdls_antenna_switch() - Dynamic TDLS antenna switch 1x1 <-> 2x2
+ * antenna mode in standalone station
+ * @hdd_ctx: Pointer to hdd contex
+ * @adapter: Pointer to hdd adapter
+ *
+ * Return: 0 if success else non zero
+ */
+int wlan_hdd_tdls_antenna_switch(hdd_context_t *hdd_ctx,
+ hdd_adapter_t *adapter)
+{
+ uint8_t tdls_peer_cnt;
+ hdd_station_ctx_t *sta_ctx =
+ WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+
+ /* Check whether TDLS antenna switch is in progress */
+ if (hdd_ctx->tdls_nss_switch_in_progress) {
+ hdd_log(LOGE, "TDLS antenna switch is in progress");
+ return -EAGAIN;
+ }
+
+ /* Check whether TDLS is connected or not */
+ mutex_lock(&hdd_ctx->tdls_lock);
+ tdls_peer_cnt = hdd_ctx->connected_peer_count;
+ mutex_unlock(&hdd_ctx->tdls_lock);
+ if (tdls_peer_cnt <= 0)
+ goto tdls_ant_sw_done;
+
+ /* Check the current operating band */
+ if (!IS_5G_CH(sta_ctx->conn_info.operationChannel)) {
+ hdd_log(LOGE, "TDLS is in 2.4G, Ant switch not needed");
+ return 0;
+ }
+
+ /* teardown all the tdls connections */
+ return wlan_hdd_tdls_teardown_links(hdd_ctx);
+
+tdls_ant_sw_done:
+ hdd_log(LOGE, "No TDLS connection established");
+ return 0;
+}