diff options
| author | Atul Mittal <atulmt@qti.qualcomm.com> | 2014-09-24 12:15:17 +0530 |
|---|---|---|
| committer | AnjaneeDevi Kapparapu <c_akappa@qti.qualcomm.com> | 2014-10-15 18:43:58 +0530 |
| commit | 98ea0c9384f56f7244f83d8fecf0a514ee13db34 (patch) | |
| tree | 49821dda1b47158f2efbd99bea03a59005e4ccd0 | |
| parent | 7abff417ef3d222557e8190ec6c45f07c1078688 (diff) | |
qcacld: TDLS: Driver ioctl for off channel commands
TDLS Off Channel ioctl support host side implementation.
These ioctls provide the parameters to FW for switching
to target channel as needed by certification test.
(part 1 HDD)
Change-Id: Ib8002e0c9c989c94ac5fc63cd5bfc26e4bf4ca82
CRs-fixed: 719234
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_cfg.h | 4 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_main.h | 2 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_tdls.h | 9 | ||||
| -rwxr-xr-x | CORE/HDD/src/wlan_hdd_main.c | 33 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_tdls.c | 200 | ||||
| -rw-r--r-- | CORE/MAC/src/include/sirParams.h | 3 | ||||
| -rw-r--r-- | CORE/SME/inc/sme_Api.h | 29 | ||||
| -rw-r--r-- | CORE/SME/src/sme_common/sme_Api.c | 84 |
8 files changed, 348 insertions, 16 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h index d3a9e842e607..2356cacc7279 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_cfg.h @@ -1790,8 +1790,8 @@ typedef enum #define CFG_TDLS_WMM_MODE_ENABLE_DEFAULT (0) #define CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM "gTDLSPrefOffChanNum" -#define CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_MIN (0) -#define CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_MAX (0xFF) +#define CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_MIN (1) +#define CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_MAX (165) #define CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_DEFAULT (36) /* Tdls offchannel bandwidth is now represented in bits as follows. diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index dde032f07ad9..9a26862b1543 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -1375,6 +1375,8 @@ struct hdd_context_s tdls_scan_context_t tdls_scan_ctxt; /* Lock to avoid race condition during TDLS operations*/ struct mutex tdls_lock; + tANI_U8 tdls_off_channel; + tANI_U16 tdls_channel_offset; #endif #ifdef IPA_OFFLOAD diff --git a/CORE/HDD/inc/wlan_hdd_tdls.h b/CORE/HDD/inc/wlan_hdd_tdls.h index 1f9286fcb342..0e6fcc28f575 100644 --- a/CORE/HDD/inc/wlan_hdd_tdls.h +++ b/CORE/HDD/inc/wlan_hdd_tdls.h @@ -70,6 +70,8 @@ should not be more than 2000 */ #define ENA_TDLS_BUFFER_STA (1 << 1) /* TDLS Buffer STA support */ #define ENA_TDLS_SLEEP_STA (1 << 2) /* TDLS Sleep STA support */ +#define TDLS_PEER_LIST_SIZE 256 + typedef struct { tANI_U32 tdls; @@ -180,7 +182,7 @@ typedef struct { struct _hddTdlsPeer_t; typedef struct { - struct list_head peer_list[256]; + struct list_head peer_list[TDLS_PEER_LIST_SIZE]; hdd_adapter_t *pAdapter; #ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER vos_timer_t peerDiscoverTimer; @@ -369,7 +371,6 @@ int wlan_hdd_tdls_set_extctrl_param(hdd_adapter_t *pAdapter, int wlan_hdd_tdls_set_force_peer(hdd_adapter_t *pAdapter, u8 *mac, tANI_BOOLEAN forcePeer); - int wlan_hdd_tdls_extctrl_deconfig_peer(hdd_adapter_t *pAdapter, u8 *peer); int wlan_hdd_tdls_extctrl_config_peer(hdd_adapter_t *pAdapter, u8 *peer, @@ -388,4 +389,8 @@ void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer, tANI_S32 *reason); int wlan_hdd_set_callback(hddTdlsPeer_t *curr_peer, cfg80211_exttdls_callback callback); +hddTdlsPeer_t *wlan_hdd_tdls_find_first_connected_peer(hdd_adapter_t *pAdapter); +int hdd_set_tdls_offchannel(hdd_context_t *pHddCtx, int offchannel); +int hdd_set_tdls_secoffchanneloffset(hdd_context_t *pHddCtx, int offchanoffset); +int hdd_set_tdls_offchannelmode(hdd_adapter_t *pAdapter, int offchanmode); #endif // __HDD_TDSL_H diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 5610729e9576..7d52160b10b3 100755 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -5953,6 +5953,39 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, pHddCtx->is_extwow_app_type2_param_set = TRUE; } #endif +#ifdef FEATURE_WLAN_TDLS + else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) { + tANI_U8 *value = command; + int set_value; + /* Move pointer to point the string */ + value += 26; + sscanf(value, "%d", &set_value); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("Tdls offchannel offset:%d"), + set_value); + ret = hdd_set_tdls_secoffchanneloffset(pHddCtx, set_value); + } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) { + tANI_U8 *value = command; + int set_value; + /* Move pointer to point the string */ + value += 18; + sscanf(value, "%d", &set_value); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("Tdls offchannel mode:%d"), + set_value); + ret = hdd_set_tdls_offchannelmode(pAdapter, set_value); + } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) { + tANI_U8 *value = command; + int set_value; + /* Move pointer to point the string */ + value += 14; + sscanf(value, "%d", &set_value); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("Tdls offchannel num: %d"), + set_value); + ret = hdd_set_tdls_offchannel(pHddCtx, set_value); + } +#endif else { MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_UNSUPPORTED_IOCTL, diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c index f692e93e5b77..137194fe069e 100644 --- a/CORE/HDD/src/wlan_hdd_tdls.c +++ b/CORE/HDD/src/wlan_hdd_tdls.c @@ -185,7 +185,7 @@ static v_VOID_t wlan_hdd_tdls_discover_peer_cb( v_PVOID_t userData ) if (0 == pHddTdlsCtx->discovery_peer_cnt) pHddTdlsCtx->discovery_peer_cnt = wlan_hdd_get_tdls_discovery_peer_cnt(pHddTdlsCtx); - for (i = 0; i < 256; i++) { + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { head = &pHddTdlsCtx->peer_list[i]; list_for_each (pos, head) { @@ -303,7 +303,7 @@ static v_VOID_t wlan_hdd_tdls_discovery_timeout_peer_cb(v_PVOID_t userData) mutex_lock(&pHddCtx->tdls_lock); - for (i = 0; i < 256; i++) { + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { head = &pHddTdlsCtx->peer_list[i]; list_for_each_safe (pos, q, head) { tmp = list_entry(pos, hddTdlsPeer_t, node); @@ -369,7 +369,7 @@ static void wlan_hdd_tdls_free_list(tdlsCtx_t *pHddTdlsCtx) FL("pHddTdlsCtx is NULL")); return; } - for (i = 0; i < 256; i++) + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { head = &pHddTdlsCtx->peer_list[i]; list_for_each_safe (pos, q, head) { @@ -506,7 +506,7 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter) pHddTdlsCtx->pAdapter = pAdapter; - for (i = 0; i < 256; i++) + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { INIT_LIST_HEAD(&pHddTdlsCtx->peer_list[i]); } @@ -782,7 +782,7 @@ static void wlan_hdd_tdls_peer_timers_stop(tdlsCtx_t *pHddTdlsCtx) struct list_head *head; struct list_head *pos; hddTdlsPeer_t *curr_peer; - for (i = 0; i < 256; i++) + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { head = &pHddTdlsCtx->peer_list[i]; list_for_each (pos, head) { @@ -815,7 +815,7 @@ static void wlan_hdd_tdls_peer_timers_destroy(tdlsCtx_t *pHddTdlsCtx) struct list_head *head; struct list_head *pos; hddTdlsPeer_t *curr_peer; - for (i = 0; i < 256; i++) + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { head = &pHddTdlsCtx->peer_list[i]; @@ -1691,7 +1691,7 @@ static void wlan_tdd_tdls_reset_tx_rx(tdlsCtx_t *pHddTdlsCtx) hddTdlsPeer_t *tmp; struct list_head *pos, *q; - for (i = 0; i < 256; i++) { + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { head = &pHddTdlsCtx->peer_list[i]; list_for_each_safe (pos, q, head) { tmp = list_entry(pos, hddTdlsPeer_t, node); @@ -1713,7 +1713,7 @@ static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t *pHddTdls pHddTdlsCtx->discovery_peer_cnt = 0; - for (i = 0; i < 256; i++) { + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { head = &pHddTdlsCtx->peer_list[i]; list_for_each_safe (pos, q, head) { tmp = list_entry(pos, hddTdlsPeer_t, node); @@ -1737,7 +1737,7 @@ static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(tdlsCtx_t *pHddTdlsCtx) * This function expects the callers to acquire the Mutex. */ - for (i = 0; i < 256; i++) { + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { head = &pHddTdlsCtx->peer_list[i]; list_for_each_safe (pos, q, head) { tmp = list_entry(pos, hddTdlsPeer_t, node); @@ -1800,7 +1800,7 @@ int wlan_hdd_tdls_get_all_peers(hdd_adapter_t *pAdapter, char *buf, int buflen) len = scnprintf(buf, buflen, "TDLS not enabled\n"); return len; } - for (i = 0; i < 256; i++) { + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { head = &pHddTdlsCtx->peer_list[i]; list_for_each(pos, head) { @@ -2055,7 +2055,7 @@ static hddTdlsPeer_t *wlan_hdd_tdls_find_progress_peer(hdd_adapter_t *pAdapter, return NULL; } - for (i = 0; i < 256; i++) { + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { head = &pHddTdlsCtx->peer_list[i]; list_for_each(pos, head) { curr_peer = list_entry (pos, hddTdlsPeer_t, node); @@ -2681,7 +2681,6 @@ void wlan_hdd_tdls_indicate_teardown(hdd_adapter_t *pAdapter, GFP_KERNEL); } - /*EXT TDLS*/ int wlan_hdd_set_callback(hddTdlsPeer_t *curr_peer, cfg80211_exttdls_callback callback) @@ -2747,3 +2746,180 @@ int wlan_hdd_tdls_get_status(hdd_adapter_t *pAdapter, return (0); } +hddTdlsPeer_t *wlan_hdd_tdls_find_first_connected_peer(hdd_adapter_t *pAdapter) +{ + int i; + struct list_head *head; + struct list_head *pos; + hddTdlsPeer_t *curr_peer = NULL; + tdlsCtx_t *pHddTdlsCtx; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + return NULL; + } + mutex_lock(&pHddCtx->tdls_lock); + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL == pHddTdlsCtx) { + mutex_unlock(&pHddCtx->tdls_lock); + return NULL; + } + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { + head = &pHddTdlsCtx->peer_list[i]; + list_for_each(pos, head) { + curr_peer = list_entry (pos, hddTdlsPeer_t, node); + if (curr_peer && (curr_peer->link_status == eTDLS_LINK_CONNECTED)) { + mutex_unlock(&pHddCtx->tdls_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + FL(MAC_ADDRESS_STR "eTDLS_LINK_CONNECTED"), + MAC_ADDR_ARRAY(curr_peer->peerMac)); + return curr_peer; + } + } + } + mutex_unlock(&pHddCtx->tdls_lock); + return NULL; +} + +int hdd_set_tdls_offchannel(hdd_context_t *pHddCtx, int offchannel) +{ + if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSOffChannel) && + (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode || + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode)) { + if (offchannel < CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_MIN || + offchannel > CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_MAX) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Invalid tdls off channel %u"), + offchannel); + return -EINVAL; + } + } else { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Either TDLS or TDLS Off-channel is not enabled")); + return -ENOTSUPP; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("change tdls off channel from %d to %d"), + pHddCtx->tdls_off_channel, offchannel); + pHddCtx->tdls_off_channel = offchannel; + return 0; +} + +int hdd_set_tdls_secoffchanneloffset(hdd_context_t *pHddCtx, int offchanoffset) +{ + if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSOffChannel) && + (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode || + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode)) { + pHddCtx->tdls_channel_offset = 0; + switch (offchanoffset) { + case BW_20: + pHddCtx->tdls_channel_offset = (1 << BW_20_OFFSET_BIT); + break; + case BW_40: + pHddCtx->tdls_channel_offset = (1 << BW_40_OFFSET_BIT); + break; + case BW_80: + pHddCtx->tdls_channel_offset = (1 << BW_80_OFFSET_BIT); + break; + case BW_160: + pHddCtx->tdls_channel_offset = (1 << BW_160_OFFSET_BIT); + break; + default: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Invalid tdls secondary off channel offset %d"), + offchanoffset); + return -EINVAL; + }/* end switch */ + } else { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Either TDLS or TDLS Off-channel is not enabled")); + return -ENOTSUPP; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("change tdls secondary off channel offset to 0x%x"), + pHddCtx->tdls_channel_offset); + return 0; +} + +int hdd_set_tdls_offchannelmode(hdd_adapter_t *pAdapter, int offchanmode) +{ + hddTdlsPeer_t *connPeer = NULL; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + tSmeTdlsChanSwitchParams chanSwitchParams; + + if (offchanmode < ENABLE_CHANSWITCH || offchanmode > DISABLE_CHANSWITCH) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Invalid tdls off channel mode %d"), + offchanmode); + return -EINVAL; + } + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("tdls off channel mode req in not associated state %d"), + offchanmode); + return -EPERM; + } + if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSOffChannel) && + (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode || + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode)) { + connPeer = wlan_hdd_tdls_find_first_connected_peer(pAdapter); + if (NULL == connPeer) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + FL("No TDLS Connected Peer")); + return -EPERM; + } + } else { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + FL("TDLS Connection not supported")); + return -ENOTSUPP; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("TDLS Channel Switch in swmode=%d"), + offchanmode); + + switch (offchanmode) { + case ENABLE_CHANSWITCH: + case DISABLE_CHANSWITCH: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("change tdls off channel mode %d tdls_off_channel %d offchanoffset %d"), + offchanmode, pHddCtx->tdls_off_channel, + pHddCtx->tdls_channel_offset); + if (pHddCtx->tdls_off_channel && pHddCtx->tdls_channel_offset) { + chanSwitchParams.vdev_id = pAdapter->sessionId; + chanSwitchParams.tdls_off_channel = pHddCtx->tdls_off_channel; + chanSwitchParams.tdls_off_ch_bw_offset = + pHddCtx->tdls_channel_offset; + chanSwitchParams.tdls_off_ch_mode = offchanmode; + chanSwitchParams.is_responder = connPeer->is_responder; + vos_mem_copy(&chanSwitchParams.peer_mac_addr, + &connPeer->peerMac, + sizeof(tSirMacAddr)); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("Peer " MAC_ADDRESS_STR "vdevId: %d, off channel: %d, offset: %d, mode: %d, is_responder: %d"), + MAC_ADDR_ARRAY(chanSwitchParams.peer_mac_addr), + chanSwitchParams.vdev_id, + chanSwitchParams.tdls_off_channel, + chanSwitchParams.tdls_off_ch_bw_offset, + chanSwitchParams.tdls_off_ch_mode, + chanSwitchParams.is_responder); + + sme_SendTdlsChanSwitchReq(WLAN_HDD_GET_HAL_CTX(pAdapter), + &chanSwitchParams); + } else { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("TDLS off-channel parameters are not set yet!!!")); + return -EINVAL; + } + break; + default: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Incorrect Parameters mode: %d tdls_off_channel: %d offchanoffset: %d"), + offchanmode, pHddCtx->tdls_off_channel, + pHddCtx->tdls_channel_offset); + break; + }/* end switch */ + return 0; +} diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h index 0fd0c50be766..85cf929a9f63 100644 --- a/CORE/MAC/src/include/sirParams.h +++ b/CORE/MAC/src/include/sirParams.h @@ -665,6 +665,9 @@ typedef struct sSirMbMsgP2p #define SIR_HAL_ROAM_OFFLOAD_SYNCH_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 294) #endif +#ifdef FEATURE_WLAN_TDLS +#define SIR_HAL_TDLS_SET_OFFCHAN_MODE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 295) +#endif #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) // CFG message types diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h index 766d4ea21adf..164626217be8 100644 --- a/CORE/SME/inc/sme_Api.h +++ b/CORE/SME/inc/sme_Api.h @@ -165,6 +165,27 @@ typedef struct _smeTdlsPeerStateParams tANI_U32 peerState; tSmeTdlsPeerCapParams peerCap; } tSmeTdlsPeerStateParams; + +#define ENABLE_CHANSWITCH 1 +#define DISABLE_CHANSWITCH 2 +#define BW_20 20 +#define BW_40 40 +#define BW_80 80 +#define BW_160 160 +#define BW_20_OFFSET_BIT 0 +#define BW_40_OFFSET_BIT 1 +#define BW_80_OFFSET_BIT 2 +#define BW_160_OFFSET_BIT 3 + +typedef struct _smeTdlsChanSwitchParams +{ + tANI_U32 vdev_id; + tSirMacAddr peer_mac_addr; + tANI_U16 tdls_off_ch_bw_offset;/* Target Off Channel Bandwidth offset */ + tANI_U8 tdls_off_channel; /* Target Off Channel */ + tANI_U8 tdls_off_ch_mode; /* TDLS Off Channel Mode */ + tANI_U8 is_responder; /* is peer responder or initiator */ +} tSmeTdlsChanSwitchParams; #endif /* FEATURE_WLAN_TDLS */ /* Thermal Mitigation*/ @@ -3390,6 +3411,14 @@ VOS_STATUS sme_DeleteTdlsPeerSta(tHalHandle hHal, tANI_U8 sessionId, tSirMacAddr void sme_SetTdlsPowerSaveProhibited(tHalHandle hHal, tANI_U32 sessionId, v_BOOL_t val); +/* --------------------------------------------------------------------------- + \fn sme_SendTdlsChanSwitchReq + \API to set tdls channel switch parameters. + + \- return void + -------------------------------------------------------------------------*/ +eHalStatus sme_SendTdlsChanSwitchReq(tHalHandle hHal, + tSmeTdlsChanSwitchParams *chSwitchParams); #endif /* --------------------------------------------------------------------------- \fn sme_IsPmcBmps diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c index f481f452d60a..9f3cfc9e1364 100644 --- a/CORE/SME/src/sme_common/sme_Api.c +++ b/CORE/SME/src/sme_common/sme_Api.c @@ -11158,6 +11158,90 @@ eHalStatus sme_UpdateTdlsPeerState(tHalHandle hHal, } return(status); } + +/* --------------------------------------------------------------------------- + \fn sme_SendTdlsChanSwitchReq + \brief API to send TDLS channel switch parameters to WMA. + + \param hHal - Umac handle. + \param chanSwitchParams- vdev, channel, offset, mode, peerMac + \- return VOS_STATUS_SUCCES + -------------------------------------------------------------------------*/ +eHalStatus sme_SendTdlsChanSwitchReq(tHalHandle hHal, + tSmeTdlsChanSwitchParams *chanSwitchParams) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tTdlsChanSwitchParams *pTdlsChanSwitchParams = NULL; + vos_msg_t vosMessage; + status = sme_AcquireGlobalLock(&pMac->sme); + if (eHAL_STATUS_SUCCESS == status) + { + pTdlsChanSwitchParams = vos_mem_malloc(sizeof(*pTdlsChanSwitchParams)); + if (NULL == pTdlsChanSwitchParams) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("failed to allocate mem for tdls chan switch param")); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + vos_mem_zero(pTdlsChanSwitchParams, sizeof(*pTdlsChanSwitchParams)); + + switch (chanSwitchParams->tdls_off_ch_mode) + { + case ENABLE_CHANSWITCH: + pTdlsChanSwitchParams->tdlsSwMode = + WDA_TDLS_ENABLE_OFFCHANNEL; + break; + + case DISABLE_CHANSWITCH: + pTdlsChanSwitchParams->tdlsSwMode = + WDA_TDLS_DISABLE_OFFCHANNEL; + break; + + default: + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("invalid off channel command (%d)"), + chanSwitchParams->tdls_off_ch_mode); + vos_mem_free(pTdlsChanSwitchParams); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + vos_mem_copy(&pTdlsChanSwitchParams->peerMacAddr, + &chanSwitchParams->peer_mac_addr, + sizeof(tSirMacAddr)); + pTdlsChanSwitchParams->vdevId = + chanSwitchParams->vdev_id; + pTdlsChanSwitchParams->tdlsOffCh = + chanSwitchParams->tdls_off_channel; + pTdlsChanSwitchParams->tdlsOffChBwOffset = + chanSwitchParams->tdls_off_ch_bw_offset; + pTdlsChanSwitchParams->is_responder= + chanSwitchParams->is_responder; + pTdlsChanSwitchParams->operClass = + regdm_get_opclass_from_channel(pMac->scan.countryCodeCurrent, + pTdlsChanSwitchParams->tdlsOffCh, + BWALL); + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Selected Operating Class=%d"), + pTdlsChanSwitchParams->operClass); + vosMessage.type = WDA_TDLS_SET_OFFCHAN_MODE; + vosMessage.reserved = 0; + vosMessage.bodyptr = pTdlsChanSwitchParams; + + vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Message Post failed status=%d"), vosStatus); + vos_mem_free(pTdlsChanSwitchParams); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + return(status); +} #endif /* FEATURE_WLAN_TDLS */ eHalStatus sme_GetLinkSpeed(tHalHandle hHal, tSirLinkSpeedInfo *lsReq, void *plsContext, |
