diff options
| author | Atul Mittal <atulmt@qti.qualcomm.com> | 2014-08-02 23:48:23 +0530 |
|---|---|---|
| committer | AnjaneeDevi Kapparapu <c_akappa@qti.qualcomm.com> | 2014-09-19 21:29:30 +0530 |
| commit | 667586483074f9f8afedd040bfdfb03852078e98 (patch) | |
| tree | d52cd4e1b37f6681d0c75d5547cebc38e1464c70 | |
| parent | a739f00f64e749bba383afe2275d6f75167c65b4 (diff) | |
qcacld: TDLS external control through HAL
TDLS can be enabled/disabled from HAL. MAC address is used
to identify the peer to which the link will be setup. Add
the required functionality and vendor commands in HDD to support
this.
Change-Id: I7ca409d34440151f1b36fcf6647a4bd4231fdb62
CRs-Fixed: 703684
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_cfg80211.h | 63 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_tdls.h | 83 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_cfg80211.c | 563 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_tdls.c | 212 | ||||
| -rw-r--r-- | CORE/SME/inc/sme_Api.h | 2 | ||||
| -rw-r--r-- | CORE/SME/src/sme_common/sme_Api.c | 9 |
6 files changed, 834 insertions, 98 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h index 79e4cab47ff4..6560a5e67aa4 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -159,6 +159,11 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE = 31, QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE = 32, QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE = 33, + /* EXT TDLS */ + QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE = 34, + QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE = 35, + QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS = 36, + QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE = 37, }; enum qca_nl80211_vendor_subcmds_index { @@ -197,8 +202,62 @@ enum qca_nl80211_vendor_subcmds_index { QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX, QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX, QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX, -#endif -}; /* WLAN_FEATURE_LINK_LAYER_STATS */ +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + /* EXT TDLS */ + QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX, +}; + +/* EXT TDLS */ +enum qca_wlan_vendor_attr_tdls_enable { + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_INVALID = 0, + /* An array of 6 x Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR, + /* signed 32-bit value, but lets keep as unsigned for now */ + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL, + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS, + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS, + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX = + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_tdls_disable { + QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_INVALID = 0, + /* An array of 6 x Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX = + QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_tdls_get_status { + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_INVALID = 0, + /* An array of 6 x Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR, + /* signed 32-bit value, but lets keep as unsigned for now */ + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE, + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX = + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_tdls_state { + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_INVALID = 0, + /* An array of 6 x Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR, + /* signed 32-bit value, but lets keep as unsigned for now */ + QCA_WLAN_VENDOR_ATTR_TDLS_NEW_STATE, + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_REASON, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAX = + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_AFTER_LAST - 1, +}; enum qca_wlan_vendor_attr { QCA_WLAN_VENDOR_ATTR_INVALID = 0, diff --git a/CORE/HDD/inc/wlan_hdd_tdls.h b/CORE/HDD/inc/wlan_hdd_tdls.h index 8ffb12d0a9ff..bd8625c20109 100644 --- a/CORE/HDD/inc/wlan_hdd_tdls.h +++ b/CORE/HDD/inc/wlan_hdd_tdls.h @@ -120,6 +120,45 @@ typedef enum eTDLSLinkStatus { eTDLS_LINK_TEARING, } tTDLSLinkStatus; + +typedef enum { + eTDLS_LINK_SUCCESS, /* Success */ + eTDLS_LINK_UNSPECIFIED = -1, /* Unspecified reason */ + eTDLS_LINK_NOT_SUPPORTED = -2, /* Remote side doesn't support TDLS */ + eTDLS_LINK_UNSUPPORTED_BAND = -3, /* Remote side doesn't support this + band */ + eTDLS_LINK_NOT_BENEFICIAL = -4, /* Going to AP is better than direct */ + eTDLS_LINK_DROPPED_BY_REMOTE = -5 /* Remote side doesn't want it anymore */ +} tTDLSLinkReason; + +typedef struct { + int channel; /* channel hint, in channel number + (NOT frequency ) */ + int global_operating_class; /* operating class to use */ + int max_latency_ms; /* max latency that can be tolerated + by apps */ + int min_bandwidth_kbps; /* bandwidth required by apps, in kilo + bits per second */ +} tdls_req_params_t; + +typedef enum { + WIFI_TDLS_DISABLED, /* TDLS is not enabled, or is disabled + now */ + WIFI_TDLS_ENABLED, /* TDLS is enabled, but not yet tried */ + WIFI_TDLS_TRYING, /* Direct link is being attempted + (optional) */ + WIFI_TDLS_ESTABLISHED, /* Direct link is established */ + WIFI_TDLS_ESTABLISHED_OFF_CHANNEL, /* Direct link is established using + MCC */ + WIFI_TDLS_DROPPED, /* Direct link was established, but is + now dropped */ + WIFI_TDLS_FAILED /* Direct link failed */ +} tdls_state_t; + +typedef int (*cfg80211_exttdls_callback)(tANI_U8* mac, + tANI_S32 state, + tANI_S32 reason, + void *ctx); typedef struct { tANI_U16 period; tANI_U16 bytes; @@ -180,6 +219,11 @@ typedef struct _hddTdlsPeer_t { tANI_U8 supported_oper_classes[SIR_MAC_MAX_SUPP_OPER_CLASSES]; vos_timer_t initiatorWaitTimeoutTimer; tANI_BOOLEAN isForcedPeer; + tANI_U8 op_class_for_pref_off_chan; + tANI_U8 pref_off_chan_num; + /* EXT TDLS */ + tTDLSLinkReason reason; + cfg80211_exttdls_callback state_change_notification; } hddTdlsPeer_t; typedef struct { @@ -229,9 +273,13 @@ hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, u8 *mac); int wlan_hdd_tdls_set_cap(hdd_adapter_t *pAdapter, u8* mac, tTDLSCapType cap); -void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer, tTDLSLinkStatus status); - -void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter, u8* mac, tTDLSLinkStatus status); +void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer, + tTDLSLinkStatus status, + tTDLSLinkReason reason); +void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter, + u8* mac, + tTDLSLinkStatus linkStatus, + tTDLSLinkReason reason); int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter, u8 *mac); @@ -303,15 +351,40 @@ void wlan_hdd_tdls_timer_restart(hdd_adapter_t *pAdapter, vos_timer_t *timer, v_U32_t expirationTime); void wlan_hdd_tdls_indicate_teardown(hdd_adapter_t *pAdapter, - hddTdlsPeer_t *curr_peer, - tANI_U16 reason); + hddTdlsPeer_t *curr_peer, + tANI_U16 reason); #ifdef CONFIG_TDLS_IMPLICIT void wlan_hdd_tdls_pre_setup_init_work(tdlsCtx_t *pHddTdlsCtx, hddTdlsPeer_t *curr_candidate); #endif +int wlan_hdd_tdls_set_extctrl_param(hdd_adapter_t *pAdapter, + uint8_t *mac, + uint32_t chan, + uint32_t max_latency, + uint32_t op_class, + uint32_t min_bandwidth); + 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, + cfg80211_exttdls_callback callback, + uint32_t chan, + uint32_t max_latency, + uint32_t op_class, + uint32_t min_bandwidth); +/* EXT TDLS */ +int wlan_hdd_tdls_get_status(hdd_adapter_t *pAdapter, + tANI_U8* mac, + tANI_S32 *state, + tANI_S32 *reason); +void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer, + tANI_S32 *state, + tANI_S32 *reason); +int wlan_hdd_set_callback(hddTdlsPeer_t *curr_peer, + cfg80211_exttdls_callback callback); #endif // __HDD_TDSL_H diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 502948901ea6..a1c1911139ac 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -208,6 +208,16 @@ #define LL_STATS_EVENT_BUF_SIZE 4096 #endif +/* EXT TDLS */ +/* + * Used to allocate the size of 4096 for the TDLS. + * The size of 4096 is considered assuming that all data per + * respective event fit with in the limit.Please take a call + * on the limit based on the data requirements on link layer + * statistics. + */ +#define EXTTDLS_EVENT_BUF_SIZE 4096 + static const u32 hdd_cipher_suites[] = { WLAN_CIPHER_SUITE_WEP40, @@ -1034,6 +1044,11 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS }, #endif /* WLAN_FEATURE_LINK_LAYER_STATS */ +/* EXT TDLS */ + [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE + }, }; int is_driver_dfs_capable(struct wiphy *wiphy, struct wireless_dev *wdev, @@ -3345,6 +3360,304 @@ static int wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy, } #endif /* WLAN_FEATURE_LINK_LAYER_STATS */ +/* EXT TDLS */ +static const struct nla_policy +wlan_hdd_tdls_config_enable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX +1] = +{ + [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_GLOBAL_OPERATING_CLASS] = + {.type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS] = {.type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS] = {.type = NLA_S32 }, + +}; + +static const struct nla_policy +wlan_hdd_tdls_config_disable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX +1] = +{ + [QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR] = {.type = NLA_UNSPEC }, + +}; + +static const struct nla_policy +wlan_hdd_tdls_config_state_change_policy[ + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAX +1] = +{ + [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR] = {.type = NLA_UNSPEC }, + [QCA_WLAN_VENDOR_ATTR_TDLS_NEW_STATE] = {.type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_REASON] = {.type = NLA_S32 }, + +}; + +static const struct nla_policy +wlan_hdd_tdls_config_get_status_policy[ + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX +1] = +{ + [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR] = {.type = NLA_UNSPEC }, + [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE] = {.type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON] = {.type = NLA_S32 }, + +}; +static int wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, + int data_len) +{ + uint8_t peer[6] = {0}; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX + 1]; + eHalStatus ret; + tANI_S32 state; + tANI_S32 reason; + struct sk_buff *skb = NULL; + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) { + return -EINVAL; + } + if (pHddCtx->cfg_ini->fTDLSExternalControl == FALSE) { + return -ENOTSUPP; + } + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX, + data, data_len, + wlan_hdd_tdls_config_get_status_policy)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid attribute")); + return -EINVAL; + } + + /* Parse and fetch mac address */ + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR]) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr mac addr failed")); + return -EINVAL; + } + + memcpy(peer, nla_data( + tb[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR]), + sizeof(peer)); + hddLog(VOS_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR),MAC_ADDR_ARRAY(peer)); + + ret = wlan_hdd_tdls_get_status(pAdapter, peer, &state, &reason); + + if (0 != ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("get status Failed")); + return -EINVAL; + } + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + 2 * sizeof(int32_t) + + NLMSG_HDRLEN); + + if (!skb) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + return -EINVAL; + } + hddLog(VOS_TRACE_LEVEL_INFO, FL("Reason (%d) Status (%d) tdls peer " MAC_ADDRESS_STR), + reason, + state, + MAC_ADDR_ARRAY(peer)); + + if (nla_put_s32(skb, QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE, state) || + nla_put_s32(skb, QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON, reason)) { + + hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail")); + goto nla_put_failure; + } + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EINVAL; +} + +static int wlan_hdd_cfg80211_exttdls_callback(tANI_U8* mac, + tANI_S32 state, + tANI_S32 reason, + void *ctx) +{ + hdd_adapter_t* pAdapter = (hdd_adapter_t*)ctx; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + struct sk_buff *skb = NULL; + + if (wlan_hdd_validate_context(pHddCtx)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid ")); + return -EINVAL; + } + + if (pHddCtx->cfg_ini->fTDLSExternalControl == FALSE) { + return -ENOTSUPP; + } + skb = cfg80211_vendor_event_alloc( + pHddCtx->wiphy, + EXTTDLS_EVENT_BUF_SIZE + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX, + GFP_KERNEL); + + if (!skb) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("cfg80211_vendor_event_alloc failed")); + return -EINVAL; + } + hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering ")); + hddLog(VOS_TRACE_LEVEL_INFO, "Reason (%d) Status (%d)", reason, state); + hddLog(VOS_TRACE_LEVEL_WARN, "tdls peer " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(mac)); + + if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR, + VOS_MAC_ADDR_SIZE, mac) || + nla_put_s32(skb, QCA_WLAN_VENDOR_ATTR_TDLS_NEW_STATE, state) || + nla_put_s32(skb, QCA_WLAN_VENDOR_ATTR_TDLS_STATE_REASON, reason) + ) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail")); + goto nla_put_failure; + } + + cfg80211_vendor_event(skb, GFP_KERNEL); + return (0); + +nla_put_failure: + kfree_skb(skb); + return -EINVAL; +} + +static int wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, + int data_len) +{ + uint8_t peer[6] = {0}; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX + 1]; + eHalStatus status; + tdls_req_params_t pReqMsg = {0}; + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("HDD context is not valid")); + return -EINVAL; + } + if (pHddCtx->cfg_ini->fTDLSExternalControl == FALSE) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("TDLS External Control is not enabled")); + return -ENOTSUPP; + } + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX, + data, data_len, + wlan_hdd_tdls_config_enable_policy)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR")); + return -EINVAL; + } + + /* Parse and fetch mac address */ + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR]) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr mac addr failed")); + return -EINVAL; + } + + memcpy(peer, nla_data( + tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR]), + sizeof(peer)); + hddLog(VOS_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR),MAC_ADDR_ARRAY(peer)); + + /* Parse and fetch channel */ + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL]) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr channel failed")); + return -EINVAL; + } + pReqMsg.channel = nla_get_s32( + tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL]); + hddLog(VOS_TRACE_LEVEL_INFO, FL("Channel Num (%d)"), pReqMsg.channel); + + /* Parse and fetch global operating class */ + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS]) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr operating class failed")); + return -EINVAL; + } + pReqMsg.global_operating_class = nla_get_s32( + tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS]); + hddLog(VOS_TRACE_LEVEL_INFO, FL("Operating class (%d)"), + pReqMsg.global_operating_class); + + /* Parse and fetch latency ms */ + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS]) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr latency failed")); + return -EINVAL; + } + pReqMsg.max_latency_ms = nla_get_s32( + tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS]); + hddLog(VOS_TRACE_LEVEL_INFO, FL("Latency (%d)"), + pReqMsg.max_latency_ms); + + /* Parse and fetch required bandwidth kbps */ + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS]) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr bandwidth failed")); + return -EINVAL; + } + + pReqMsg.min_bandwidth_kbps = nla_get_s32( + tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS]); + hddLog(VOS_TRACE_LEVEL_INFO, FL("Bandwidth (%d)"), + pReqMsg.min_bandwidth_kbps); + + return (wlan_hdd_tdls_extctrl_config_peer(pAdapter, + peer, + wlan_hdd_cfg80211_exttdls_callback, + pReqMsg.channel, + pReqMsg.max_latency_ms, + pReqMsg.global_operating_class, + pReqMsg.min_bandwidth_kbps)); +} + +static int wlan_hdd_cfg80211_exttdls_disable(struct wiphy *wiphy, + struct wireless_dev *wdev, + void *data, + int data_len) +{ + u8 peer[6] = {0}; + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX + 1]; + eHalStatus status; + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("HDD context is not valid")); + return -EINVAL; + } + if (pHddCtx->cfg_ini->fTDLSExternalControl == FALSE) { + + return -ENOTSUPP; + } + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX, + data, data_len, + wlan_hdd_tdls_config_disable_policy)) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR")); + return -EINVAL; + } + /* Parse and fetch mac address */ + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR]) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr mac addr failed")); + return -EINVAL; + } + + memcpy(peer, nla_data( + tb[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR]), + sizeof(peer)); + hddLog(VOS_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR),MAC_ADDR_ARRAY(peer)); + + return (wlan_hdd_tdls_extctrl_deconfig_peer(pAdapter, peer)); +} + + const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { { @@ -3477,8 +3790,32 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, .doit = wlan_hdd_cfg80211_ll_stats_get - } + }, #endif /* WLAN_FEATURE_LINK_LAYER_STATS */ +/* EXT TDLS */ + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_exttdls_enable + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_exttdls_disable + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wlan_hdd_cfg80211_exttdls_get_status + }, }; @@ -6597,7 +6934,10 @@ static int wlan_hdd_tdls_add_station(struct wiphy *wiphy, } } if (0 == update) - wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING); + wlan_hdd_tdls_set_link_status(pAdapter, + mac, + eTDLS_LINK_CONNECTING, + eTDLS_LINK_SUCCESS); /* debug code */ if (NULL != StaParams) @@ -6671,7 +7011,10 @@ static int wlan_hdd_tdls_add_station(struct wiphy *wiphy, return 0; error: - wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE); + wlan_hdd_tdls_set_link_status(pAdapter, + mac, + eTDLS_LINK_IDLE, + eTDLS_LINK_UNSPECIFIED); return -EPERM; } @@ -12410,6 +12753,116 @@ static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *d return 0; } + +int wlan_hdd_tdls_extctrl_config_peer(hdd_adapter_t *pAdapter, + u8 *peer, + cfg80211_exttdls_callback callback, + u32 chan, + u32 max_latency, + u32 op_class, + u32 min_bandwidth) +{ + hddTdlsPeer_t *pTdlsPeer; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + 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_INFO, + "%s TDLS External control or Implicit Trigger not enabled ", + __func__); + return -ENOTSUPP; + } + + /* To cater the requirement of establishing the TDLS link + * irrespective of the data traffic , get an entry of TDLS peer. + */ + pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, peer); + if (pTdlsPeer == NULL) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: peer " MAC_ADDRESS_STR " does not exist", + __func__, MAC_ADDR_ARRAY(peer)); + return -EINVAL; + } + + if ( 0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, TRUE) ) { + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s TDLS Add Force Peer Failed", + __func__); + return -EINVAL; + } + + if ( 0 != wlan_hdd_tdls_set_extctrl_param(pAdapter, peer, + chan, max_latency, + op_class, min_bandwidth) ) { + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s TDLS Set Peer's External Ctrl Parameter Failed", + __func__); + return -EINVAL; + } + + if ( 0 != wlan_hdd_set_callback(pTdlsPeer, callback) ) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s TDLS set callback Failed", + __func__); + return -EINVAL; + } + + return(0); +} + +int wlan_hdd_tdls_extctrl_deconfig_peer(hdd_adapter_t *pAdapter, u8 *peer) +{ + hddTdlsPeer_t *pTdlsPeer; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + 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_INFO, + "%s TDLS External control or Implicit Trigger not enabled ", + __func__); + return -ENOTSUPP; + } + + + pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE); + + if ( NULL == pTdlsPeer ) { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: " MAC_ADDRESS_STR + "peer matching MAC_ADDRESS_STR not found", + __func__, MAC_ADDR_ARRAY(peer)); + return -EINVAL; + } + else { + wlan_hdd_tdls_indicate_teardown(pAdapter, pTdlsPeer, + eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + } + + if (0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, FALSE)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s Failed", + __func__); + return -EINVAL; + } + /* EXT TDLS */ + if ( 0 != wlan_hdd_set_callback(pTdlsPeer, NULL )) { + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s TDLS set callback Failed", + __func__); + return -EINVAL; + } + return(0); +} static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, u8 *peer, @@ -12510,7 +12963,9 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, return -EINVAL; } } - wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED); + wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, + eTDLS_LINK_CONNECTED, + eTDLS_LINK_SUCCESS); /* start TDLS client registration with TL */ status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature); if (VOS_STATUS_SUCCESS == status) @@ -12559,9 +13014,14 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, pHddCtx->cfg_ini->fTDLSPrefOffChanNum; smeTdlsPeerStateParams.peerCap.prefOffChanBandwidth = pHddCtx->cfg_ini->fTDLSPrefOffChanBandwidth; + smeTdlsPeerStateParams.peerCap.opClassForPrefOffChan = + pTdlsPeer->op_class_for_pref_off_chan; + smeTdlsPeerStateParams.peerCap.opClassForPrefOffChanIsSet = 1; + smeTdlsPeerStateParams.peerCap.prefOffChanNum = + pTdlsPeer->pref_off_chan_num; VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%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", + "%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, opClassForPrefOffChan %d", __func__, MAC_ADDR_ARRAY(peer), smeTdlsPeerStateParams.vdevId, smeTdlsPeerStateParams.peerState, @@ -12575,7 +13035,8 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, smeTdlsPeerStateParams.peerCap.peerChanLen, smeTdlsPeerStateParams.peerCap.peerOperClassLen, smeTdlsPeerStateParams.peerCap.prefOffChanNum, - smeTdlsPeerStateParams.peerCap.prefOffChanBandwidth); + smeTdlsPeerStateParams.peerCap.prefOffChanBandwidth, + smeTdlsPeerStateParams.peerCap.opClassForPrefOffChan); for (i = 0; i < pTdlsPeer->supported_channels_len; i++) { @@ -12661,7 +13122,9 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, "%s: Del station timed out", __func__); return -EPERM; } - wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE); + wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, + eTDLS_LINK_IDLE, + eTDLS_LINK_UNSPECIFIED); } else { @@ -12672,81 +13135,29 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, 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; - } - + status = wlan_hdd_tdls_extctrl_deconfig_peer(pAdapter, peer); - 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); - } - - if (0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, FALSE)) { - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s NL80211_TDLS_TEARDOWN: Set force peer failed for peer " - MAC_ADDRESS_STR, __func__, MAC_ADDR_ARRAY(peer)); - return -EINVAL; - } - break; + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Error in TDLS Teardown", __func__); + return status; + } } + break; case NL80211_TDLS_SETUP: { - hddTdlsPeer_t *pTdlsPeer; - 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; - } - - /* To cater the requirement of establishing the TDLS link - * irrespective of the data traffic , get an entry of TDLS peer. - */ - pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, peer); - - if (pTdlsPeer == NULL) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: peer "MAC_ADDRESS_STR - " does not exist, NL80211_TDLS_SETUP failed", - __func__, MAC_ADDR_ARRAY(peer)); - return -EINVAL; - } - - if (0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, TRUE)) { - - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s NL80211_TDLS_SETUP: Set force peer failed for peer " - MAC_ADDRESS_STR, __func__, MAC_ADDR_ARRAY(peer)); - return -EINVAL; + status = wlan_hdd_tdls_extctrl_config_peer(pAdapter, + peer, + NULL, 0, 0, 0, 0); + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Error in TDLS Setup", __func__); + return status; } - break; } + break; case NL80211_TDLS_DISCOVERY_REQ: /* We don't support in-driver setup/teardown/discovery */ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c index eaec77f0cbdd..aeba3c2ca6d3 100644 --- a/CORE/HDD/src/wlan_hdd_tdls.c +++ b/CORE/HDD/src/wlan_hdd_tdls.c @@ -312,7 +312,11 @@ static v_VOID_t wlan_hdd_tdls_discovery_timeout_peer_cb(v_PVOID_t userData) VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: " MAC_ADDRESS_STR " to idle state", __func__, MAC_ADDR_ARRAY(tmp->peerMac)); - tmp->link_status = eTDLS_LINK_IDLE; + mutex_unlock(&pHddCtx->tdls_lock); + wlan_hdd_tdls_set_peer_link_status(tmp, + eTDLS_LINK_IDLE, + eTDLS_LINK_UNSPECIFIED); + mutex_lock(&pHddCtx->tdls_lock); } } } @@ -916,8 +920,14 @@ int wlan_hdd_tdls_set_cap(hdd_adapter_t *pAdapter, return 0; } -void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer, tTDLSLinkStatus status) +void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer, + tTDLSLinkStatus status, + tTDLSLinkReason reason) { + tANI_S32 state = 0; + tANI_S32 res = 0; + hdd_context_t *pHddCtx; + if (curr_peer == NULL) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, @@ -925,9 +935,27 @@ void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer, tTDLSLinkStatu return; } + if (curr_peer->pHddTdlsCtx == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer->pHddTdlsCtx is NULL")); + return; + } + + pHddCtx = WLAN_HDD_GET_CTX(curr_peer->pHddTdlsCtx->pAdapter); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + return; + } + hddLog(VOS_TRACE_LEVEL_WARN, "tdls set peer " MAC_ADDRESS_STR " link status to %u", MAC_ADDR_ARRAY(curr_peer->peerMac), status); + mutex_lock(&pHddCtx->tdls_lock); + curr_peer->link_status = status; /* If TDLS link status is already passed the discovery state @@ -938,14 +966,40 @@ void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer, tTDLSLinkStatu curr_peer->discovery_attempt = 0; } + mutex_unlock(&pHddCtx->tdls_lock); + + if (curr_peer->isForcedPeer && curr_peer->state_change_notification) + { + /*save the reason for any further query*/ + curr_peer->reason = reason; + wlan_hdd_tdls_get_wifi_hal_state(curr_peer, &state, &res); + + (*curr_peer->state_change_notification)( + curr_peer->peerMac, + state, + res, + curr_peer->pHddTdlsCtx->pAdapter); + + } return; } void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter, u8* mac, - tTDLSLinkStatus linkStatus) + tTDLSLinkStatus linkStatus, + tTDLSLinkReason reason) { + tANI_S32 state = 0; + tANI_S32 res = 0; hddTdlsPeer_t *curr_peer; + 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; + } curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE); if (curr_peer == NULL) @@ -955,6 +1009,8 @@ void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter, return; } + mutex_lock(&pHddCtx->tdls_lock); + curr_peer->link_status= linkStatus; /* If TDLS link status is already passed the discovery state @@ -965,6 +1021,22 @@ void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter, curr_peer->discovery_attempt = 0; } + mutex_unlock(&pHddCtx->tdls_lock); + + if (curr_peer->isForcedPeer && curr_peer->state_change_notification) + { + /*save the reason for any further query*/ + curr_peer->reason = reason; + wlan_hdd_tdls_get_wifi_hal_state(curr_peer, &state, &res); + + (curr_peer->state_change_notification)( + mac, + state, + res, + curr_peer->pHddTdlsCtx->pAdapter); + + } + return; } @@ -1024,7 +1096,9 @@ int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter, u8 *mac) */ if ((tANI_S32) curr_peer->rssi > (tANI_S32) pHddTdlsCtx->threshold_config.rssi_trigger_threshold) { - curr_peer->link_status = eTDLS_LINK_DISCOVERED; + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_DISCOVERED, + eTDLS_LINK_SUCCESS); VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "Rssi Threshold met: "MAC_ADDRESS_STR" rssi = %d threshold= %d" , MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->rssi, @@ -1037,7 +1111,9 @@ int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter, u8 *mac) "Rssi Threshold not met: "MAC_ADDRESS_STR" rssi = %d threshold = %d ", MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->rssi, pHddTdlsCtx->threshold_config.rssi_trigger_threshold); - curr_peer->link_status = eTDLS_LINK_IDLE; + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_IDLE, + eTDLS_LINK_UNSPECIFIED); /* if RSSI threshold is not met then allow further discovery * attempts by decrementing count for the last attempt @@ -1451,6 +1527,32 @@ int wlan_hdd_tdls_set_sta_id(hdd_adapter_t *pAdapter, u8 *mac, u8 staId) return 0; } +int wlan_hdd_tdls_set_extctrl_param(hdd_adapter_t *pAdapter, uint8_t *mac, + uint32_t chan, uint32_t max_latency, + uint32_t op_class, uint32_t min_bandwidth) +{ + hddTdlsPeer_t *curr_peer; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (!pHddCtx) + return -1; + + mutex_lock(&pHddCtx->tdls_lock); + + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, FALSE); + if (curr_peer == NULL) + { + mutex_unlock(&pHddCtx->tdls_lock); + return -1; + } + + curr_peer->op_class_for_pref_off_chan = (uint8_t)op_class; + curr_peer->pref_off_chan_num = (uint8_t)chan; + + mutex_unlock(&pHddCtx->tdls_lock); + return 0; +} + int wlan_hdd_tdls_set_force_peer(hdd_adapter_t *pAdapter, u8 *mac, tANI_BOOLEAN forcePeer) { @@ -1573,7 +1675,9 @@ int wlan_hdd_tdls_reset_peer(hdd_adapter_t *pAdapter, u8 *mac) return -1; } - curr_peer->link_status = eTDLS_LINK_IDLE; + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_IDLE, + eTDLS_LINK_UNSPECIFIED); curr_peer->staId = 0; return 0; @@ -2142,8 +2246,6 @@ static void __wlan_hdd_tdls_pre_setup(struct work_struct *work) temp_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0); - mutex_lock(&pHddCtx->tdls_lock); - if (NULL != temp_peer) { VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: " MAC_ADDRESS_STR " ongoing. pre_setup ignored", @@ -2152,7 +2254,11 @@ static void __wlan_hdd_tdls_pre_setup(struct work_struct *work) } if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support) - curr_peer->link_status = eTDLS_LINK_DISCOVERING; + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_DISCOVERING, + eTDLS_LINK_SUCCESS); + + mutex_lock(&pHddCtx->tdls_lock); /* Ignore discovery attempt if External Control is enabled, that * is, peer is forced. In that case, continue discovery attempt @@ -2173,10 +2279,13 @@ static void __wlan_hdd_tdls_pre_setup(struct work_struct *work) goto done; } } - curr_peer->link_status = eTDLS_LINK_DISCOVERING; mutex_unlock(&pHddCtx->tdls_lock); + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_DISCOVERING, + eTDLS_LINK_SUCCESS); + status = wlan_hdd_cfg80211_send_tdls_discover_req(pHddTdlsCtx->pAdapter->wdev.wiphy, pHddTdlsCtx->pAdapter->dev, peer_mac); @@ -2197,7 +2306,13 @@ static void __wlan_hdd_tdls_pre_setup(struct work_struct *work) VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: " MAC_ADDRESS_STR " discovery could not sent", __func__, MAC_ADDR_ARRAY(curr_peer->peerMac)); if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support) - curr_peer->link_status = eTDLS_LINK_IDLE; + { + mutex_unlock(&pHddCtx->tdls_lock); + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_IDLE, + eTDLS_LINK_UNSPECIFIED); + mutex_lock(&pHddCtx->tdls_lock); + } goto done; } @@ -2376,7 +2491,9 @@ int wlan_hdd_tdls_scan_callback (hdd_adapter_t *pAdapter, "%s: " MAC_ADDRESS_STR ". scan rejected %d. force it to idle", __func__, MAC_ADDR_ARRAY (curr_peer->peerMac), pHddCtx->tdls_scan_ctxt.reject); - wlan_hdd_tdls_set_peer_link_status (curr_peer, eTDLS_LINK_IDLE); + wlan_hdd_tdls_set_peer_link_status (curr_peer, + eTDLS_LINK_IDLE, + eTDLS_LINK_UNSPECIFIED); return 1; } VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, @@ -2554,10 +2671,79 @@ void wlan_hdd_tdls_indicate_teardown(hdd_adapter_t *pAdapter, if (eTDLS_LINK_CONNECTED != curr_peer->link_status) return; - wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_TEARING); + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_TEARING, + eTDLS_LINK_DROPPED_BY_REMOTE); cfg80211_tdls_oper_request(pAdapter->dev, curr_peer->peerMac, NL80211_TDLS_TEARDOWN, reason, GFP_KERNEL); } + + +/*EXT TDLS*/ +int wlan_hdd_set_callback(hddTdlsPeer_t *curr_peer, + cfg80211_exttdls_callback callback) +{ + hdd_context_t *pHddCtx; + hdd_adapter_t *pAdapter; + + if (!curr_peer) return -1; + + pAdapter = curr_peer->pHddTdlsCtx->pAdapter; + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if ((NULL == pHddCtx)) return -1; + + mutex_lock(&pHddCtx->tdls_lock); + + curr_peer->state_change_notification = callback; + + mutex_unlock(&pHddCtx->tdls_lock); + return 0; +} + +void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer, + tANI_S32 *state, + tANI_S32 *reason) +{ + *reason = curr_peer->reason; + + switch(curr_peer->link_status) + { + case eTDLS_LINK_IDLE: + case eTDLS_LINK_DISCOVERING: + case eTDLS_LINK_DISCOVERED: + *state = WIFI_TDLS_ENABLED; + break; + case eTDLS_LINK_CONNECTING: + *state = WIFI_TDLS_TRYING; + break; + case eTDLS_LINK_CONNECTED: + *state = WIFI_TDLS_ESTABLISHED; + break; + case eTDLS_LINK_TEARING: + *state = WIFI_TDLS_DROPPED; + break; + } +} + +int wlan_hdd_tdls_get_status(hdd_adapter_t *pAdapter, + tANI_U8* mac, + tANI_S32 *state, + tANI_S32 *reason) +{ + hddTdlsPeer_t *curr_peer; + + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE); + if (curr_peer == NULL) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("curr_peer is NULL")); + return -EINVAL; + } + + wlan_hdd_tdls_get_wifi_hal_state(curr_peer, state, reason); + return (0); +} + diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h index c3807e15c49c..74a667328465 100644 --- a/CORE/SME/inc/sme_Api.h +++ b/CORE/SME/inc/sme_Api.h @@ -147,6 +147,8 @@ typedef struct _smeTdlsPeerCapParams { tANI_U8 peerOperClass[SME_TDLS_MAX_SUPP_OPER_CLASSES]; tANI_U8 prefOffChanNum; tANI_U8 prefOffChanBandwidth; + tANI_U8 opClassForPrefOffChan; + tANI_U8 opClassForPrefOffChanIsSet; } tSmeTdlsPeerCapParams; typedef enum diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c index 80093088fe40..86d308224398 100644 --- a/CORE/SME/src/sme_common/sme_Api.c +++ b/CORE/SME/src/sme_common/sme_Api.c @@ -11115,8 +11115,12 @@ eHalStatus sme_UpdateTdlsPeerState(tHalHandle hHal, else preOffChanOffset = BW40_LOW_PRIMARY; - pTdlsPeerStateParams->peerCap.opClassForPrefOffChan = - regdm_get_opclass_from_channel(pMac->scan.countryCodeCurrent, + if (peerStateParams->peerCap.opClassForPrefOffChanIsSet) + pTdlsPeerStateParams->peerCap.opClassForPrefOffChan = + peerStateParams->peerCap.opClassForPrefOffChan; + else + pTdlsPeerStateParams->peerCap.opClassForPrefOffChan = + regdm_get_opclass_from_channel(pMac->scan.countryCodeCurrent, pTdlsPeerStateParams->peerCap.prefOffChanNum, preOffChanOffset); @@ -11130,6 +11134,7 @@ eHalStatus sme_UpdateTdlsPeerState(tHalHandle hHal, vos_mem_free(pTdlsPeerStateParams); status = eHAL_STATUS_FAILURE; } + sme_ReleaseGlobalLock(&pMac->sme); } return(status); |
