summaryrefslogtreecommitdiff
path: root/CORE/HDD/src
diff options
context:
space:
mode:
authorSunil Dutt <usdutt@qti.qualcomm.com>2013-11-14 18:09:02 +0530
committerAkash Patel <c_akashp@qca.qualcomm.com>2014-04-16 19:26:38 -0700
commit3a956f15f15dc94ae6d34fe417a12ed373f35d9e (patch)
tree67903b717b984586a2a8666daf38dfaae7a23142 /CORE/HDD/src
parente509c2c24ed2e1b31194f27cd49b1356337c18aa (diff)
TDLS : Initiate the TDLS setup only when externally configured.
There are use cases where the driver has to initiate the TDLS setup to the peer only when configured by the external applications This commit addresses the same and the functionality is configured by gTDLSExternalControl parameter. Change-Id: I1a2d8cbe44e78f46b32ebb6ba5d515a691bbc0c5 CRs-fixed: 647521
Diffstat (limited to 'CORE/HDD/src')
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg.c7
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg80211.c112
-rw-r--r--CORE/HDD/src/wlan_hdd_tdls.c131
3 files changed, 219 insertions, 31 deletions
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index 4b359f89e6fa..2d290eac14cb 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -2735,6 +2735,13 @@ REG_VARIABLE( CFG_TDLS_PUAPSD_RX_FRAME_THRESHOLD, WLAN_PARAM_Integer,
CFG_TDLS_PUAPSD_RX_FRAME_THRESHOLD_DEFAULT,
CFG_TDLS_PUAPSD_RX_FRAME_THRESHOLD_MIN,
CFG_TDLS_PUAPSD_RX_FRAME_THRESHOLD_MAX ),
+
+REG_VARIABLE( CFG_TDLS_EXTERNAL_CONTROL, WLAN_PARAM_Integer,
+ hdd_config_t, fTDLSExternalControl,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TDLS_EXTERNAL_CONTROL_DEFAULT,
+ CFG_TDLS_EXTERNAL_CONTROL_MIN,
+ CFG_TDLS_EXTERNAL_CONTROL_MAX ),
#endif
#ifdef WLAN_SOFTAP_VSTA_FEATURE
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index f5c632db4bb7..ab946ca2b034 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -9324,15 +9324,6 @@ static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *d
tSmeTdlsPeerStateParams smeTdlsPeerStateParams;
eHalStatus halStatus = eHAL_STATUS_FAILURE;
#endif
-#ifdef WLAN_FEATURE_TDLS_DEBUG
- const char *tdls_oper_str[]= {
- "NL80211_TDLS_DISCOVERY_REQ",
- "NL80211_TDLS_SETUP",
- "NL80211_TDLS_TEARDOWN",
- "NL80211_TDLS_ENABLE_LINK",
- "NL80211_TDLS_DISABLE_LINK",
- "NL80211_TDLS_UNKNOWN_OPER"};
-#endif
hddTdlsPeer_t *pTdlsPeer;
if ( NULL == peer )
@@ -9351,23 +9342,6 @@ static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *d
return status;
}
- pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
-
- if ( NULL == pTdlsPeer ) {
- hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR " (oper %d) not exsting. ignored",
- __func__, MAC_ADDR_ARRAY(peer), (int)oper);
- return -EINVAL;
- }
-
-#ifdef WLAN_FEATURE_TDLS_DEBUG
- if((int)oper > 4)
- oper = 5;
-
- VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
- "%s: " MAC_ADDRESS_STR " link_status %d (%s) ", "tdls_oper",
- MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status,
- tdls_oper_str[(int)oper]);
-#endif
/* QCA 2.0 Discrete ANDs feature capability in cfg_ini with that
* received from target, so cfg_ini gives combined intersected result
@@ -9390,11 +9364,28 @@ static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *d
VOS_STATUS status;
tCsrTdlsLinkEstablishParams tdlsLinkEstablishParams;
+ pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
+
+ if (NULL == pTdlsPeer)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: peer matching "MAC_ADDRESS_STR
+ " not found, ignore NL80211_TDLS_ENABLE_LINK",
+ __func__, MAC_ADDR_ARRAY(peer));
+ return -EINVAL;
+ }
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: NL80211_TDLS_ENABLE_LINK for peer "
+ MAC_ADDRESS_STR" link_status: %d",
+ __func__, MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status);
+
if (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
{
- hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Staion Index %u "
- MAC_ADDRESS_STR " failed",
- __func__, pTdlsPeer->staId, MAC_ADDR_ARRAY(peer));
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: invalid sta index %u for "
+ MAC_ADDRESS_STR" TDLS_ENABLE_LINK failed",
+ __func__, pTdlsPeer->staId, MAC_ADDR_ARRAY(peer));
return -EINVAL;
}
@@ -9505,6 +9496,21 @@ static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *d
break;
case NL80211_TDLS_DISABLE_LINK:
{
+ pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
+
+ if ( NULL == pTdlsPeer ) {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: peer matching "MAC_ADDRESS_STR
+ " not found, ignore NL80211_TDLS_DISABLE_LINK",
+ __func__, MAC_ADDR_ARRAY(peer));
+ return -EINVAL;
+ }
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: NL80211_TDLS_DISABLE_LINK for peer "
+ MAC_ADDRESS_STR " link_status: %d",
+ __func__, MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status);
+
if(TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
{
long status;
@@ -9534,7 +9540,55 @@ static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *d
}
break;
case NL80211_TDLS_TEARDOWN:
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s : NL80211_TDLS_TEARDOWN for " MAC_ADDRESS_STR,
+ __func__, MAC_ADDR_ARRAY(peer));
+
+ if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) ||
+ (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) {
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: NL80211_TDLS_TEARDOWN, either External control or Implicit trigger not enabled",
+ __func__);
+ return -ENOTSUPP;
+ }
+
+ if ( 0 != wlan_hdd_tdls_remove_force_peer(pAdapter, peer) )
+ return -EINVAL;
+
+ pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
+
+ if ( NULL == pTdlsPeer ) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: peer matching "MAC_ADDRESS_STR
+ " not found, ignore NL80211_TDLS_TEARDOWN",
+ __func__, MAC_ADDR_ARRAY(peer));
+ return -EINVAL;
+ }
+ else {
+ wlan_hdd_tdls_indicate_teardown(pAdapter, pTdlsPeer,
+ eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
+ }
+ break;
+ }
case NL80211_TDLS_SETUP:
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ " %s : NL80211_TDLS_SETUP for " MAC_ADDRESS_STR,
+ __func__, MAC_ADDR_ARRAY(peer));
+
+ if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) ||
+ (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) {
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: NL80211_TDLS_SETUP, either External control or Implicit trigger not enabled",
+ __func__);
+ return -ENOTSUPP;
+ }
+
+ return wlan_hdd_tdls_add_force_peer(pAdapter, peer);
+ }
case NL80211_TDLS_DISCOVERY_REQ:
/* We don't support in-driver setup/teardown/discovery */
return -ENOTSUPP;
diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c
index c0b7f9935319..03aa874dfe9c 100644
--- a/CORE/HDD/src/wlan_hdd_tdls.c
+++ b/CORE/HDD/src/wlan_hdd_tdls.c
@@ -52,6 +52,7 @@ static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(tdlsCtx_t *pHddTdlsCtx);
static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t *pHddTdlsCtx);
static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx);
static void wlan_hdd_tdls_peer_timers_destroy(tdlsCtx_t *pHddTdlsCtx);
+int wpa_tdls_is_allowed_force_peer(tdlsCtx_t *pHddTdlsCtx, u8 *mac);
#ifdef CONFIG_TDLS_IMPLICIT
static void wlan_hdd_tdls_pre_setup(struct work_struct *work);
#endif
@@ -302,6 +303,10 @@ static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData )
"%s: " MAC_ADDRESS_STR " link_status %d"
" tdls_support %d", __func__, MAC_ADDR_ARRAY(curr_peer->peerMac),
curr_peer->link_status, curr_peer->tdls_support);
+ if (pHddCtx->cfg_ini->fTDLSExternalControl &&
+ (0 == wpa_tdls_is_allowed_force_peer (pHddTdlsCtx, curr_peer->peerMac))) {
+ continue;
+ }
if (eTDLS_CAP_SUPPORTED == curr_peer->tdls_support) {
VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
@@ -1457,9 +1462,131 @@ int wlan_hdd_tdls_set_sta_id(hdd_adapter_t *pAdapter, u8 *mac, u8 staId)
return 0;
}
+int wpa_tdls_is_allowed_force_peer(tdlsCtx_t *pHddTdlsCtx, u8 *mac)
+{
+ int i;
+ for (i = 0; i < pHddTdlsCtx->forcePeerCnt; i++)
+ {
+ if (!memcmp(mac, pHddTdlsCtx->forcePeer[i].macAddr, 6))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: " MAC_ADDRESS_STR "is a forced peer",
+ __func__,MAC_ADDR_ARRAY(mac));
+ return 1;
+ }
+ }
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: " MAC_ADDRESS_STR "is not a forced peer",
+ __func__,MAC_ADDR_ARRAY(mac));
+ return 0;
+}
+
+int wlan_hdd_tdls_remove_force_peer(hdd_adapter_t *pAdapter, u8 *mac)
+{
+ int i;
+ tdlsCtx_t *pHddTdlsCtx;
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+
+ if (!pHddCtx)
+ return -1;
+
+ mutex_lock(&pHddCtx->tdls_lock);
+
+ pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
+ if (NULL == pHddTdlsCtx)
+ {
+ mutex_unlock(&pHddCtx->tdls_lock);
+ return -1;
+ }
+
+ for (i=0; i<HDD_MAX_NUM_TDLS_STA; i++)
+ {
+ if (!memcmp(mac, pHddTdlsCtx->forcePeer[i].macAddr, 6))
+ {
+ /*
+ * Entry Already Exists,Clear the entry and return.
+ */
+ memset(pHddTdlsCtx->forcePeer[i].macAddr, 0, 6);
+ pHddTdlsCtx->forcePeerCnt--;
+ mutex_unlock(&pHddCtx->tdls_lock);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: Removed the requested foce peer", __func__);
+ return 0;
+ }
+ }
+
+ /* Should not have come here if the existing entry has to be removed */
+ mutex_unlock(&pHddCtx->tdls_lock);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to remove the requested force peer: No Entry Found ", __func__);
+ return -1;
+}
+
+int wlan_hdd_tdls_add_force_peer(hdd_adapter_t *pAdapter, u8 *mac)
+{
+ int i ;
+ tdlsCtx_t *pHddTdlsCtx;
+ tANI_U8 zeroMac[6] = {0};
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+
+ if (!pHddCtx)
+ return -1;
+
+ mutex_lock(&pHddCtx->tdls_lock);
+
+ pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
+ if (NULL == pHddTdlsCtx)
+ {
+ mutex_unlock(&pHddCtx->tdls_lock);
+ return -1;
+ }
+
+ if (pHddTdlsCtx->forcePeerCnt >= HDD_MAX_NUM_TDLS_STA )
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: Fail to add the requested foce peer : Quota Full forcePeerCnt is %d",
+ __func__,pHddTdlsCtx->forcePeerCnt);
+ /* Quota Full, hence return failure from here*/
+ goto error;
+ }
+
+ for (i=0; i<HDD_MAX_NUM_TDLS_STA; i++)
+ {
+ if (!memcmp(mac, pHddTdlsCtx->forcePeer[i].macAddr, 6))
+ {
+ /*
+ * Entry Already Exists,No need to create a new one.
+ * Hence return from here.
+ */
+ mutex_unlock(&pHddCtx->tdls_lock);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: Add the requested foce peer success : Entry present forcePeerCnt is %d",
+ __func__, pHddTdlsCtx->forcePeerCnt);
+ return 0;
+ }
+ }
+ for (i=0; i<HDD_MAX_NUM_TDLS_STA; i++)
+ {
+ if ( !memcmp(pHddTdlsCtx->forcePeer[i].macAddr, zeroMac, 6) )
+ {
+ memcpy(pHddTdlsCtx->forcePeer[i].macAddr, mac, 6);
+ pHddTdlsCtx->forcePeerCnt++;
+ mutex_unlock(&pHddCtx->tdls_lock);
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: Add the requested foce peer success at index i %d"
+ " forcePeerCnt is %d ",
+ __func__, i, pHddTdlsCtx->forcePeerCnt);
+ return 0;
+ }
+ }
+error:
+ mutex_unlock(&pHddCtx->tdls_lock);
+ return -1;
+}
+
/* if peerMac is found, then it returns pointer to hddTdlsPeer_t
- otherwise, it returns NULL
-*/
+ * otherwise, it returns NULL
+ */
hddTdlsPeer_t *wlan_hdd_tdls_find_peer(hdd_adapter_t *pAdapter, u8 *mac,
tANI_BOOLEAN mutexLock)
{