qcacld-4.0: TDLS: provide operating class and channel to HAL

qcacld-2.0 to qcacld-3.0 propagation

1.Provide off channel and operating class info to user space
in HAL API wifi_get_tdls_status. If off channel is not enabled
then provide base channel info and in that case pass opclass as 0.
2.Provide correct tdls state based on tdls off channel
configuration.

Change-Id: Ic60500b95ebddcb88b4e03f29178068c5322b2b9
CRs-Fixed: 838167
This commit is contained in:
Masti, Narayanraddi
2015-11-25 15:41:10 +05:30
committed by Satish Singh
parent c6229d2b6f
commit 0c68510e8c
6 changed files with 275 additions and 160 deletions

View File

@@ -1184,6 +1184,7 @@ struct hdd_context_s {
struct mutex tdls_lock; struct mutex tdls_lock;
uint8_t tdls_off_channel; uint8_t tdls_off_channel;
uint16_t tdls_channel_offset; uint16_t tdls_channel_offset;
int32_t tdls_fw_off_chan_mode;
#endif #endif
#ifdef IPA_OFFLOAD #ifdef IPA_OFFLOAD
@@ -1559,4 +1560,7 @@ void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx);
void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx); void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx);
const char *hdd_get_fwpath(void); const char *hdd_get_fwpath(void);
uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
uint8_t bw_offset);
#endif /* end #if !defined(WLAN_HDD_MAIN_H) */ #endif /* end #if !defined(WLAN_HDD_MAIN_H) */

View File

@@ -228,6 +228,8 @@ typedef enum {
} tdls_state_t; } tdls_state_t;
typedef int (*cfg80211_exttdls_callback)(const uint8_t *mac, typedef int (*cfg80211_exttdls_callback)(const uint8_t *mac,
uint32_t opclass,
uint32_t channel,
uint32_t state, uint32_t state,
int32_t reason, void *ctx); int32_t reason, void *ctx);
@@ -531,10 +533,11 @@ int wlan_hdd_tdls_extctrl_config_peer(hdd_adapter_t *pAdapter,
uint32_t op_class, uint32_t op_class,
uint32_t min_bandwidth); uint32_t min_bandwidth);
int wlan_hdd_tdls_get_status(hdd_adapter_t *pAdapter, int wlan_hdd_tdls_get_status(hdd_adapter_t *pAdapter,
const uint8_t *mac, int32_t *state, const uint8_t *mac, uint32_t *opclass,
uint32_t *channel, uint32_t *state,
int32_t *reason); int32_t *reason);
void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer, void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer,
int32_t *state, int32_t *reason); uint32_t *state, int32_t *reason);
int wlan_hdd_set_callback(hddTdlsPeer_t *curr_peer, int wlan_hdd_set_callback(hddTdlsPeer_t *curr_peer,
cfg80211_exttdls_callback callback); cfg80211_exttdls_callback callback);
void wlan_hdd_update_tdls_info(hdd_adapter_t *adapter, bool tdls_prohibited, void wlan_hdd_update_tdls_info(hdd_adapter_t *adapter, bool tdls_prohibited,

View File

@@ -86,6 +86,7 @@
#ifdef CONFIG_CNSS #ifdef CONFIG_CNSS
#include <net/cnss.h> #include <net/cnss.h>
#endif #endif
#include "cds_regdomain.h"
#include "wlan_hdd_ocb.h" #include "wlan_hdd_ocb.h"
@@ -359,6 +360,24 @@ static int con_mode;
static int curr_con_mode; static int curr_con_mode;
#endif #endif
/* wlan_hdd_find_opclass() - Find operating class for a channel
* @hal: handler to HAL
* @channel: channel id
* @bw_offset: bandwidth offset
*
* Function invokes sme api to find the operating class
*
* Return: operating class
*/
uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
uint8_t bw_offset)
{
uint8_t opclass = 0;
sme_get_opclass(hal, channel, bw_offset, &opclass);
return opclass;
}
/** /**
* hdd_cdf_trace_enable() - configure initial CDF Trace enable * hdd_cdf_trace_enable() - configure initial CDF Trace enable
* @moduleId: Module whose trace level is being configured * @moduleId: Module whose trace level is being configured

View File

@@ -51,6 +51,40 @@ static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx);
int wpa_tdls_is_allowed_force_peer(tdlsCtx_t *pHddTdlsCtx, u8 *mac); int wpa_tdls_is_allowed_force_peer(tdlsCtx_t *pHddTdlsCtx, u8 *mac);
static void wlan_hdd_tdls_pre_setup(struct work_struct *work); static void wlan_hdd_tdls_pre_setup(struct work_struct *work);
/*
* wlan_hdd_tdls_determine_channel_opclass() - determine channel and opclass
* @hddctx: pointer to hdd context
* @adapter: pointer to adapter
* @curr_peer: pointer to current tdls peer
* @channel: pointer to channel
* @opclass: pointer to opclass
*
* Function determines the channel and operating class
*
* Return: None
*/
static void wlan_hdd_tdls_determine_channel_opclass(hdd_context_t *hddctx,
hdd_adapter_t *adapter, hddTdlsPeer_t *curr_peer,
uint32_t *channel, uint32_t *opclass)
{
hdd_station_ctx_t *hdd_sta_ctx;
/*
* If tdls offchannel is not enabled then we provide base channel
* and in that case pass opclass as 0 since opclass is mainly needed
* for offchannel cases.
*/
if (!(hddctx->config->fEnableTDLSOffChannel) ||
(hddctx->tdls_fw_off_chan_mode != ENABLE_CHANSWITCH)) {
hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
*channel = hdd_sta_ctx->conn_info.operationChannel;
*opclass = 0;
} else {
*channel = curr_peer->pref_off_chan_num;
*opclass = curr_peer->op_class_for_pref_off_chan;
}
}
/** /**
* wlan_hdd_tdls_hash_key() - calculate tdls hash key given mac address * wlan_hdd_tdls_hash_key() - calculate tdls hash key given mac address
* @mac: mac address * @mac: mac address
@@ -648,8 +682,12 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter)
pHddTdlsCtx->threshold_config.rssi_teardown_threshold; pHddTdlsCtx->threshold_config.rssi_teardown_threshold;
tInfo->rssi_delta = pHddTdlsCtx->threshold_config.rssi_delta; tInfo->rssi_delta = pHddTdlsCtx->threshold_config.rssi_delta;
tInfo->tdls_options = 0; tInfo->tdls_options = 0;
if (pHddCtx->config->fEnableTDLSOffChannel)
if (pHddCtx->config->fEnableTDLSOffChannel) {
tInfo->tdls_options |= ENA_TDLS_OFFCHAN; tInfo->tdls_options |= ENA_TDLS_OFFCHAN;
pHddCtx->tdls_fw_off_chan_mode = ENABLE_CHANSWITCH;
}
if (pHddCtx->config->fEnableTDLSBufferSta) if (pHddCtx->config->fEnableTDLSBufferSta)
tInfo->tdls_options |= ENA_TDLS_BUFFER_STA; tInfo->tdls_options |= ENA_TDLS_BUFFER_STA;
if (pHddCtx->config->fEnableTDLSSleepSta) if (pHddCtx->config->fEnableTDLSSleepSta)
@@ -862,6 +900,9 @@ hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, const u8 *mac)
cdf_mem_copy(peer->peerMac, mac, sizeof(peer->peerMac)); cdf_mem_copy(peer->peerMac, mac, sizeof(peer->peerMac));
peer->pHddTdlsCtx = pHddTdlsCtx; peer->pHddTdlsCtx = pHddTdlsCtx;
peer->pref_off_chan_num = pHddCtx->config->fTDLSPrefOffChanNum; peer->pref_off_chan_num = pHddCtx->config->fTDLSPrefOffChanNum;
peer->op_class_for_pref_off_chan =
wlan_hdd_find_opclass(pHddCtx->hHal, peer->pref_off_chan_num,
pHddCtx->config->fTDLSPrefOffChanBandwidth);
list_add_tail(&peer->node, head); list_add_tail(&peer->node, head);
mutex_unlock(&pHddCtx->tdls_lock); mutex_unlock(&pHddCtx->tdls_lock);
@@ -905,7 +946,7 @@ void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer,
tTDLSLinkStatus status, tTDLSLinkStatus status,
tTDLSLinkReason reason) tTDLSLinkReason reason)
{ {
int32_t state = 0; uint32_t state = 0;
int32_t res = 0; int32_t res = 0;
hdd_context_t *pHddCtx; hdd_context_t *pHddCtx;
if (curr_peer == NULL) { if (curr_peer == NULL) {
@@ -941,13 +982,19 @@ void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer,
mutex_unlock(&pHddCtx->tdls_lock); mutex_unlock(&pHddCtx->tdls_lock);
if (curr_peer->isForcedPeer && curr_peer->state_change_notification) { if (curr_peer->isForcedPeer && curr_peer->state_change_notification) {
uint32_t opclass;
uint32_t channel;
hdd_adapter_t *adapter = curr_peer->pHddTdlsCtx->pAdapter;
curr_peer->reason = reason; curr_peer->reason = reason;
wlan_hdd_tdls_determine_channel_opclass(pHddCtx, adapter,
curr_peer, &channel, &opclass);
wlan_hdd_tdls_get_wifi_hal_state(curr_peer, &state, &res); wlan_hdd_tdls_get_wifi_hal_state(curr_peer, &state, &res);
(*curr_peer->state_change_notification)(curr_peer->peerMac, (*curr_peer->state_change_notification)(curr_peer->peerMac,
state, opclass, channel,
res, state, res, adapter);
curr_peer->
pHddTdlsCtx->pAdapter);
} }
return; return;
} }
@@ -966,7 +1013,7 @@ void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter,
tTDLSLinkStatus linkStatus, tTDLSLinkStatus linkStatus,
tTDLSLinkReason reason) tTDLSLinkReason reason)
{ {
int32_t state = 0; uint32_t state = 0;
int32_t res = 0; int32_t res = 0;
hddTdlsPeer_t *curr_peer; hddTdlsPeer_t *curr_peer;
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
@@ -994,13 +1041,18 @@ void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter,
} }
mutex_unlock(&pHddCtx->tdls_lock); mutex_unlock(&pHddCtx->tdls_lock);
if (curr_peer->isForcedPeer && curr_peer->state_change_notification) { if (curr_peer->isForcedPeer && curr_peer->state_change_notification) {
uint32_t opclass;
uint32_t channel;
hdd_adapter_t *adapter = curr_peer->pHddTdlsCtx->pAdapter;
curr_peer->reason = reason; curr_peer->reason = reason;
wlan_hdd_tdls_determine_channel_opclass(pHddCtx, adapter,
curr_peer, &channel, &opclass);
wlan_hdd_tdls_get_wifi_hal_state(curr_peer, &state, &res); wlan_hdd_tdls_get_wifi_hal_state(curr_peer, &state, &res);
(curr_peer->state_change_notification)(mac, (curr_peer->state_change_notification)(mac, opclass, channel,
state, state, res, adapter);
res,
curr_peer->pHddTdlsCtx->
pAdapter);
} }
return; return;
@@ -1808,11 +1860,6 @@ int wlan_hdd_tdls_set_extctrl_param(hdd_adapter_t *pAdapter, const uint8_t *mac,
curr_peer->op_class_for_pref_off_chan = (uint8_t) op_class; curr_peer->op_class_for_pref_off_chan = (uint8_t) op_class;
curr_peer->pref_off_chan_num = (uint8_t) chan; curr_peer->pref_off_chan_num = (uint8_t) chan;
if (curr_peer->op_class_for_pref_off_chan)
curr_peer->op_class_for_pref_off_chan_is_set = 1;
else
curr_peer->op_class_for_pref_off_chan_is_set = 0;
mutex_unlock(&pHddCtx->tdls_lock); mutex_unlock(&pHddCtx->tdls_lock);
return 0; return 0;
} }
@@ -1960,6 +2007,22 @@ int wlan_hdd_tdls_reset_peer(hdd_adapter_t *pAdapter, const uint8_t *mac)
return -EINVAL; return -EINVAL;
} }
/*
* Reset preferred offchannel and opclass for offchannel as
* per INI configuration only if peer is not forced one. For
* forced peer, offchannel and opclass is set in HAL API at the
* time of enabling TDLS for that specific peer and so do not overwrite
* those set by user space.
*/
if (false == curr_peer->isForcedPeer) {
curr_peer->pref_off_chan_num =
pHddCtx->config->fTDLSPrefOffChanNum;
curr_peer->op_class_for_pref_off_chan =
wlan_hdd_find_opclass(WLAN_HDD_GET_HAL_CTX(pAdapter),
curr_peer->pref_off_chan_num,
pHddCtx->config->fTDLSPrefOffChanBandwidth);
}
wlan_hdd_tdls_set_peer_link_status(curr_peer, wlan_hdd_tdls_set_peer_link_status(curr_peer,
eTDLS_LINK_IDLE, eTDLS_LINK_IDLE,
eTDLS_LINK_UNSPECIFIED); eTDLS_LINK_UNSPECIFIED);
@@ -2854,9 +2917,24 @@ int wlan_hdd_set_callback(hddTdlsPeer_t *curr_peer,
* Return: Void * Return: Void
*/ */
void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer, void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer,
int32_t *state, int32_t *reason) uint32_t *state, int32_t *reason)
{ {
hdd_context_t *hddctx;
hdd_adapter_t *adapter;
if (!curr_peer) {
hdd_err("curr_peer is NULL");
return;
}
adapter = curr_peer->pHddTdlsCtx->pAdapter;
hddctx = WLAN_HDD_GET_CTX(adapter);
if (0 != (wlan_hdd_validate_context(hddctx)))
return;
*reason = curr_peer->reason; *reason = curr_peer->reason;
switch (curr_peer->link_status) { switch (curr_peer->link_status) {
case eTDLS_LINK_IDLE: case eTDLS_LINK_IDLE:
case eTDLS_LINK_DISCOVERED: case eTDLS_LINK_DISCOVERED:
@@ -2867,7 +2945,11 @@ void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer,
*state = QCA_WIFI_HAL_TDLS_ENABLED; *state = QCA_WIFI_HAL_TDLS_ENABLED;
break; break;
case eTDLS_LINK_CONNECTED: case eTDLS_LINK_CONNECTED:
*state = QCA_WIFI_HAL_TDLS_ESTABLISHED; if ((hddctx->config->fEnableTDLSOffChannel) &&
(hddctx->tdls_fw_off_chan_mode == ENABLE_CHANSWITCH))
*state = QCA_WIFI_HAL_TDLS_ESTABLISHED_OFF_CHANNEL;
else
*state = QCA_WIFI_HAL_TDLS_ESTABLISHED;
break; break;
case eTDLS_LINK_TEARING: case eTDLS_LINK_TEARING:
*state = QCA_WIFI_HAL_TDLS_DROPPED; *state = QCA_WIFI_HAL_TDLS_DROPPED;
@@ -2885,32 +2967,38 @@ void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer,
* Return: 0 if success; negative errno otherwise * Return: 0 if success; negative errno otherwise
*/ */
int wlan_hdd_tdls_get_status(hdd_adapter_t *pAdapter, int wlan_hdd_tdls_get_status(hdd_adapter_t *pAdapter,
const uint8_t *mac, int32_t *state, const uint8_t *mac, uint32_t *opclass,
uint32_t *channel, uint32_t *state,
int32_t *reason) int32_t *reason)
{ {
hddTdlsPeer_t *curr_peer; hddTdlsPeer_t *curr_peer;
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, true); if (0 != (wlan_hdd_validate_context(pHddCtx)))
return -EINVAL;
mutex_lock(&pHddCtx->tdls_lock);
curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, false);
if (curr_peer == NULL) { if (curr_peer == NULL) {
mutex_unlock(&pHddCtx->tdls_lock);
CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
FL("curr_peer is NULL")); FL("curr_peer is NULL"));
*state = QCA_WIFI_HAL_TDLS_DISABLED; *state = QCA_WIFI_HAL_TDLS_DISABLED;
*reason = eTDLS_LINK_UNSPECIFIED; *reason = eTDLS_LINK_UNSPECIFIED;
} else { return -EINVAL;
if (pHddCtx->config->fTDLSExternalControl &&
(false == curr_peer->isForcedPeer)) {
CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
FL("curr_peer is not Forced"));
*state = QCA_WIFI_HAL_TDLS_DISABLED;
*reason = eTDLS_LINK_UNSPECIFIED;
} else {
wlan_hdd_tdls_get_wifi_hal_state(curr_peer,
state, reason);
}
} }
if (pHddCtx->config->fTDLSExternalControl &&
(false == curr_peer->isForcedPeer)) {
hdd_err("curr_peer is not Forced");
*state = QCA_WIFI_HAL_TDLS_DISABLED;
*reason = eTDLS_LINK_UNSPECIFIED;
} else {
wlan_hdd_tdls_determine_channel_opclass(pHddCtx, pAdapter,
curr_peer, channel, opclass);
wlan_hdd_tdls_get_wifi_hal_state(curr_peer, state, reason);
}
mutex_unlock(&pHddCtx->tdls_lock);
wlan_hdd_tdls_get_wifi_hal_state(curr_peer, state, reason);
return 0; return 0;
} }
@@ -2919,12 +3007,12 @@ static const struct nla_policy
wlan_hdd_tdls_config_enable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX + wlan_hdd_tdls_config_enable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX +
1] = { 1] = {
[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR] = {.type = NLA_UNSPEC}, [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR] = {.type = NLA_UNSPEC},
[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL] = {.type = NLA_S32}, [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL] = {.type = NLA_U32},
[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS] = {.type = [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS] = {.type =
NLA_S32}, NLA_U32},
[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS] = {.type = NLA_S32}, [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS] = {.type = NLA_U32},
[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS] = {.type = [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS] = {.type =
NLA_S32}, NLA_U32},
}; };
static const struct nla_policy static const struct nla_policy
wlan_hdd_tdls_config_disable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX + wlan_hdd_tdls_config_disable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX +
@@ -3003,7 +3091,8 @@ __wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy,
nla_data(tb[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR]), nla_data(tb[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR]),
sizeof(peer)); sizeof(peer));
hddLog(CDF_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR), MAC_ADDR_ARRAY(peer)); hddLog(CDF_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR), MAC_ADDR_ARRAY(peer));
ret = wlan_hdd_tdls_get_status(pAdapter, peer, &state, &reason); ret = wlan_hdd_tdls_get_status(pAdapter, peer, &global_operating_class,
&channel, &state, &reason);
if (0 != ret) { if (0 != ret) {
hddLog(CDF_TRACE_LEVEL_ERROR, FL("get status Failed")); hddLog(CDF_TRACE_LEVEL_ERROR, FL("get status Failed"));
return -EINVAL; return -EINVAL;
@@ -3076,14 +3165,14 @@ int wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy,
* Return: 0 for success; negative errno otherwise * Return: 0 for success; negative errno otherwise
*/ */
static int wlan_hdd_cfg80211_exttdls_callback(const uint8_t *mac, static int wlan_hdd_cfg80211_exttdls_callback(const uint8_t *mac,
uint32_t global_operating_class,
uint32_t channel,
uint32_t state, uint32_t state,
int32_t reason, void *ctx) int32_t reason, void *ctx)
{ {
hdd_adapter_t *pAdapter = (hdd_adapter_t *) ctx; hdd_adapter_t *pAdapter = (hdd_adapter_t *) ctx;
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
uint32_t global_operating_class = 0;
uint32_t channel = 0;
ENTER(); ENTER();
@@ -4171,21 +4260,15 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy,
prefOffChanBandwidth = prefOffChanBandwidth =
pHddCtx->config-> pHddCtx->config->
fTDLSPrefOffChanBandwidth; fTDLSPrefOffChanBandwidth;
if (pTdlsPeer-> smeTdlsPeerStateParams.peerCap.
op_class_for_pref_off_chan_is_set) {
smeTdlsPeerStateParams.peerCap.
opClassForPrefOffChanIsSet =
pTdlsPeer->
op_class_for_pref_off_chan_is_set;
smeTdlsPeerStateParams.peerCap.
opClassForPrefOffChan = opClassForPrefOffChan =
pTdlsPeer-> pTdlsPeer->
op_class_for_pref_off_chan; op_class_for_pref_off_chan;
}
CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE(CDF_MODULE_ID_HDD,
CDF_TRACE_LEVEL_INFO, CDF_TRACE_LEVEL_INFO,
"%s: Peer " MAC_ADDRESS_STR "%s: Peer " MAC_ADDRESS_STR
"vdevId: %d, peerState: %d, isPeerResponder: %d, uapsdQueues: 0x%x, maxSp: 0x%x, peerBuffStaSupport: %d, peerOffChanSupport: %d, peerCurrOperClass: %d, selfCurrOperClass: %d, peerChanLen: %d, peerOperClassLen: %d, prefOffChanNum: %d, prefOffChanBandwidth: %d, op_class_for_pref_off_chan_is_set: %d, op_class_for_pref_off_chan: %d", "vdevId: %d, peerState: %d, isPeerResponder: %d, uapsdQueues: 0x%x, maxSp: 0x%x, peerBuffStaSupport: %d, peerOffChanSupport: %d, peerCurrOperClass: %d, selfCurrOperClass: %d, peerChanLen: %d, peerOperClassLen: %d, prefOffChanNum: %d, prefOffChanBandwidth: %d, op_class_for_pref_off_chan: %d",
__func__, __func__,
MAC_ADDR_ARRAY(peer), MAC_ADDR_ARRAY(peer),
smeTdlsPeerStateParams.vdevId, smeTdlsPeerStateParams.vdevId,
@@ -4214,8 +4297,6 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy,
smeTdlsPeerStateParams. smeTdlsPeerStateParams.
peerCap.prefOffChanBandwidth, peerCap.prefOffChanBandwidth,
pTdlsPeer-> pTdlsPeer->
op_class_for_pref_off_chan_is_set,
pTdlsPeer->
op_class_for_pref_off_chan); op_class_for_pref_off_chan);
for (i = 0; for (i = 0;
@@ -4596,6 +4677,7 @@ int hdd_set_tdls_offchannelmode(hdd_adapter_t *adapter, int offchanmode)
hdd_station_ctx_t *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); hdd_station_ctx_t *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
sme_tdls_chan_switch_params chan_switch_params; sme_tdls_chan_switch_params chan_switch_params;
CDF_STATUS status = CDF_STATUS_E_FAILURE;
if (offchanmode < ENABLE_CHANSWITCH || if (offchanmode < ENABLE_CHANSWITCH ||
offchanmode > DISABLE_CHANSWITCH) { offchanmode > DISABLE_CHANSWITCH) {
@@ -4626,46 +4708,24 @@ int hdd_set_tdls_offchannelmode(hdd_adapter_t *adapter, int offchanmode)
FL("TDLS Connection not supported")); FL("TDLS Connection not supported"));
return -ENOTSUPP; return -ENOTSUPP;
} }
hddLog(LOG1, hddLog(LOG1,
FL("TDLS Channel Switch in swmode=%d"), FL("TDLS Channel Switch in swmode=%d tdls_off_channel %d offchanoffset %d"),
offchanmode); offchanmode, hdd_ctx->tdls_off_channel,
hdd_ctx->tdls_channel_offset);
switch (offchanmode) { switch (offchanmode) {
case ENABLE_CHANSWITCH: case ENABLE_CHANSWITCH:
case DISABLE_CHANSWITCH: if (hdd_ctx->tdls_off_channel &&
hddLog(LOG1, hdd_ctx->tdls_channel_offset) {
FL(
"change tdls off channel mode %d tdls_off_channel %d offchanoffset %d"
),
offchanmode, hdd_ctx->tdls_off_channel,
hdd_ctx->tdls_channel_offset);
if (hdd_ctx->tdls_off_channel && hdd_ctx->tdls_channel_offset) {
chan_switch_params.vdev_id = adapter->sessionId;
chan_switch_params.tdls_off_channel = chan_switch_params.tdls_off_channel =
hdd_ctx->tdls_off_channel; hdd_ctx->tdls_off_channel;
chan_switch_params.tdls_off_ch_bw_offset = chan_switch_params.tdls_off_ch_bw_offset =
hdd_ctx->tdls_channel_offset; hdd_ctx->tdls_channel_offset;
chan_switch_params.tdls_off_ch_mode = offchanmode; chan_switch_params.opclass =
chan_switch_params.is_responder = wlan_hdd_find_opclass(WLAN_HDD_GET_HAL_CTX(adapter),
conn_peer->is_responder; chan_switch_params.tdls_off_channel,
cdf_mem_copy(&chan_switch_params.peer_mac_addr, chan_switch_params.tdls_off_ch_bw_offset);
&conn_peer->peerMac,
sizeof(tSirMacAddr));
hddLog(LOG1,
FL("Peer " MAC_ADDRESS_STR
" vdevId: %d, off channel: %d, offset: %d, mode: %d, is_responder: %d"
),
MAC_ADDR_ARRAY(chan_switch_params.
peer_mac_addr),
chan_switch_params.vdev_id,
chan_switch_params.tdls_off_channel,
chan_switch_params.tdls_off_ch_bw_offset,
chan_switch_params.tdls_off_ch_mode,
chan_switch_params.is_responder);
sme_send_tdls_chan_switch_req(
WLAN_HDD_GET_HAL_CTX(adapter),
&chan_switch_params);
} else { } else {
hddLog(LOGE, hddLog(LOGE,
FL( FL(
@@ -4674,6 +4734,11 @@ int hdd_set_tdls_offchannelmode(hdd_adapter_t *adapter, int offchanmode)
return -EINVAL; return -EINVAL;
} }
break; break;
case DISABLE_CHANSWITCH:
chan_switch_params.tdls_off_channel = 0;
chan_switch_params.tdls_off_ch_bw_offset = 0;
chan_switch_params.opclass = 0;
break;
default: default:
hddLog(LOGE, hddLog(LOGE,
FL( FL(
@@ -4681,8 +4746,44 @@ int hdd_set_tdls_offchannelmode(hdd_adapter_t *adapter, int offchanmode)
), ),
offchanmode, hdd_ctx->tdls_off_channel, offchanmode, hdd_ctx->tdls_off_channel,
hdd_ctx->tdls_channel_offset); hdd_ctx->tdls_channel_offset);
break; return -EINVAL;
} /* end switch */ } /* end switch */
chan_switch_params.vdev_id = adapter->sessionId;
chan_switch_params.tdls_off_ch_mode = offchanmode;
chan_switch_params.is_responder =
conn_peer->is_responder;
cdf_mem_copy(&chan_switch_params.peer_mac_addr,
&conn_peer->peerMac,
sizeof(tSirMacAddr));
hdd_log(LOG1,
FL("Peer " MAC_ADDRESS_STR
" vdevId: %d, off channel: %d, offset: %d, mode: %d, is_responder: %d"),
MAC_ADDR_ARRAY(chan_switch_params.peer_mac_addr),
chan_switch_params.vdev_id,
chan_switch_params.tdls_off_channel,
chan_switch_params.tdls_off_ch_bw_offset,
chan_switch_params.tdls_off_ch_mode,
chan_switch_params.is_responder);
status = sme_send_tdls_chan_switch_req(WLAN_HDD_GET_HAL_CTX(adapter),
&chan_switch_params);
if (status != CDF_STATUS_SUCCESS) {
hdd_log(LOG1,
FL("Failed to send channel switch request to sme"));
return -EINVAL;
}
hdd_ctx->tdls_fw_off_chan_mode = offchanmode;
if (ENABLE_CHANSWITCH == offchanmode) {
conn_peer->pref_off_chan_num =
chan_switch_params.tdls_off_channel;
conn_peer->op_class_for_pref_off_chan =
chan_switch_params.opclass;
}
return 0; return 0;
} }

View File

@@ -155,7 +155,6 @@ typedef struct _smeTdlsPeerCapParams {
uint8_t prefOffChanNum; uint8_t prefOffChanNum;
uint8_t prefOffChanBandwidth; uint8_t prefOffChanBandwidth;
uint8_t opClassForPrefOffChan; uint8_t opClassForPrefOffChan;
uint8_t opClassForPrefOffChanIsSet;
} tSmeTdlsPeerCapParams; } tSmeTdlsPeerCapParams;
typedef enum { typedef enum {
@@ -184,6 +183,7 @@ typedef struct sme_tdls_chan_switch_params_struct {
uint8_t tdls_off_channel; /* Target Off Channel */ uint8_t tdls_off_channel; /* Target Off Channel */
uint8_t tdls_off_ch_mode; /* TDLS Off Channel Mode */ uint8_t tdls_off_ch_mode; /* TDLS Off Channel Mode */
uint8_t is_responder; /* is peer responder or initiator */ uint8_t is_responder; /* is peer responder or initiator */
uint8_t opclass; /* tdls operating class */
} sme_tdls_chan_switch_params; } sme_tdls_chan_switch_params;
#endif /* FEATURE_WLAN_TDLS */ #endif /* FEATURE_WLAN_TDLS */
@@ -1056,4 +1056,16 @@ void sme_update_tgt_services(tHalHandle hal, struct wma_tgt_services *cfg);
bool sme_validate_sap_channel_switch(tHalHandle hal, bool sme_validate_sap_channel_switch(tHalHandle hal,
uint16_t sap_ch, eCsrPhyMode sap_phy_mode, uint16_t sap_ch, eCsrPhyMode sap_phy_mode,
uint8_t cc_switch_mode, uint8_t session_id); uint8_t cc_switch_mode, uint8_t session_id);
#ifdef FEATURE_WLAN_TDLS
void sme_get_opclass(tHalHandle hal, uint8_t channel, uint8_t bw_offset,
uint8_t *opclass);
#else
static inline void
sme_get_opclass(tHalHandle hal, uint8_t channel, uint8_t bw_offset,
uint8_t *opclass)
{
}
#endif
#endif /* #if !defined( __SME_API_H ) */ #endif /* #if !defined( __SME_API_H ) */

View File

@@ -10045,49 +10045,9 @@ CDF_STATUS sme_update_tdls_peer_state(tHalHandle hHal,
peerStateParams->peerCap.prefOffChanNum; peerStateParams->peerCap.prefOffChanNum;
peer_cap->prefOffChanBandwidth = peer_cap->prefOffChanBandwidth =
peerStateParams->peerCap.prefOffChanBandwidth; peerStateParams->peerCap.prefOffChanBandwidth;
peer_cap->opClassForPrefOffChan =
peerStateParams->peerCap.opClassForPrefOffChan;
if (peerStateParams->peerCap.opClassForPrefOffChanIsSet) {
peer_cap->opClassForPrefOffChan =
peerStateParams->peerCap.opClassForPrefOffChan;
} else {
/*
* redgm opclass table contains opclass for 40MHz low
* primary, 40MHz high primary and 20MHz. No support
* for 80MHz yet. So first we will check if bit for
* 40MHz is set and if so find matching opclass either
* with low primary or high primary (a channel would
* never be in both) and then search for opclass
* matching 20MHz, else for any BW.
*/
if (peer_cap->prefOffChanBandwidth &
(1 << BW_40_OFFSET_BIT)) {
peer_cap->opClassForPrefOffChan =
cds_regdm_get_opclass_from_channel(
pMac->scan.countryCodeCurrent,
peer_cap->prefOffChanNum,
BW40_LOW_PRIMARY);
if (!peer_cap->opClassForPrefOffChan) {
peer_cap->opClassForPrefOffChan =
cds_regdm_get_opclass_from_channel(
pMac->scan.countryCodeCurrent,
peer_cap->prefOffChanNum,
BW40_HIGH_PRIMARY);
}
} else if (peer_cap->prefOffChanBandwidth &
(1 << BW_20_OFFSET_BIT)) {
peer_cap->opClassForPrefOffChan =
cds_regdm_get_opclass_from_channel(
pMac->scan.countryCodeCurrent,
peer_cap->prefOffChanNum,
BW20);
} else {
peer_cap->opClassForPrefOffChan =
cds_regdm_get_opclass_from_channel(
pMac->scan.countryCodeCurrent,
peer_cap->prefOffChanNum,
BWALL);
}
}
cds_message.type = WMA_UPDATE_TDLS_PEER_STATE; cds_message.type = WMA_UPDATE_TDLS_PEER_STATE;
cds_message.reserved = 0; cds_message.reserved = 0;
cds_message.bodyptr = pTdlsPeerStateParams; cds_message.bodyptr = pTdlsPeerStateParams;
@@ -10159,37 +10119,7 @@ CDF_STATUS sme_send_tdls_chan_switch_req(tHalHandle hal,
chan_switch_params->tdls_off_ch_bw_offset = chan_switch_params->tdls_off_ch_bw_offset =
ch_switch_params->tdls_off_ch_bw_offset; ch_switch_params->tdls_off_ch_bw_offset;
chan_switch_params->is_responder = ch_switch_params->is_responder; chan_switch_params->is_responder = ch_switch_params->is_responder;
chan_switch_params->oper_class = ch_switch_params->opclass;
switch (chan_switch_params->tdls_off_ch_bw_offset) {
case (1 << BW_20_OFFSET_BIT):
chan_switch_params->oper_class =
cds_regdm_get_opclass_from_channel(
mac->scan.countryCodeCurrent,
chan_switch_params->tdls_off_ch,
BW20);
break;
case (1 << BW_40_OFFSET_BIT):
chan_switch_params->oper_class =
cds_regdm_get_opclass_from_channel(
mac->scan.countryCodeCurrent,
chan_switch_params->tdls_off_ch,
BW40_LOW_PRIMARY);
if (!chan_switch_params->oper_class) {
chan_switch_params->oper_class =
cds_regdm_get_opclass_from_channel(
mac->scan.countryCodeCurrent,
chan_switch_params->tdls_off_ch,
BW40_HIGH_PRIMARY);
}
break;
default:
chan_switch_params->oper_class =
cds_regdm_get_opclass_from_channel(
mac->scan.countryCodeCurrent,
chan_switch_params->tdls_off_ch,
BWALL);
break;
} /* end switch */
CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
FL("Country Code=%s, Req offset=%d, Selected Operate Class=%d"), FL("Country Code=%s, Req offset=%d, Selected Operate Class=%d"),
@@ -14916,3 +14846,49 @@ void sme_update_tgt_services(tHalHandle hal, struct wma_tgt_services *cfg)
return; return;
} }
#ifdef FEATURE_WLAN_TDLS
/**
* sme_get_opclass() - determine operating class
* @hal: Pointer to HAL
* @channel: channel id
* @bw_offset: bandwidth offset
* @opclass: pointer to operating class
*
* Function will determine operating class from regdm_get_opclass_from_channel
*
* Return: none
*/
void sme_get_opclass(tHalHandle hal, uint8_t channel, uint8_t bw_offset,
uint8_t *opclass)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
/* redgm opclass table contains opclass for 40MHz low primary,
* 40MHz high primary and 20MHz. No support for 80MHz yet. So
* first we will check if bit for 40MHz is set and if so find
* matching opclass either with low primary or high primary
* (a channel would never be in both) and then search for opclass
* matching 20MHz, else for any BW.
*/
if (bw_offset & (1 << BW_40_OFFSET_BIT)) {
*opclass = cds_regdm_get_opclass_from_channel(
mac_ctx->scan.countryCodeCurrent,
channel, BW40_LOW_PRIMARY);
if (!(*opclass)) {
*opclass = cds_regdm_get_opclass_from_channel(
mac_ctx->scan.countryCodeCurrent,
channel, BW40_HIGH_PRIMARY);
}
} else if (bw_offset & (1 << BW_20_OFFSET_BIT)) {
*opclass = cds_regdm_get_opclass_from_channel(
mac_ctx->scan.countryCodeCurrent,
channel, BW20);
} else {
*opclass = cds_regdm_get_opclass_from_channel(
mac_ctx->scan.countryCodeCurrent,
channel, BWALL);
}
}
#endif