From 792df6498215488fd0818430dabb4723f14e82d7 Mon Sep 17 00:00:00 2001 From: Deeksha Gupta Date: Mon, 10 May 2021 12:04:26 +0530 Subject: [PATCH] qcacld-3.0: Support for TWT SAP get_status query command Add support for TWT get_status command in SAP As part of this change, TWT get_status command is supported if 1. If particular dialog_id and particular mac_addr are present 2. If dialog_id = 0 and particular mac_addr are present 3. If no parameter present Change-Id: I5ce1719da7f9a3988ba6e1f04455a06faf9687c6 CRs-Fixed: 2937999 --- .../src/wlan_cp_stats_mc_ucfg_api.c | 53 ++++++--- core/hdd/src/wlan_hdd_twt.c | 110 +++++++++++++++++- 2 files changed, 138 insertions(+), 25 deletions(-) diff --git a/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c b/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c index f6971db171ff..b2b09c651c32 100644 --- a/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c +++ b/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c @@ -32,6 +32,9 @@ #ifdef WLAN_POWER_MANAGEMENT_OFFLOAD #include #endif +#ifdef WLAN_SUPPORT_TWT +#include +#endif #ifdef WLAN_SUPPORT_TWT @@ -44,9 +47,10 @@ * @dest_param: Pointer to copy twt session parameters when a peer with * given dialog id is found * - * Return: true if stats are copied for a peer with given dialog, else false + * Return: Success if stats are copied for a peer with given dialog, + * else failure */ -static bool +static QDF_STATUS ucfg_twt_get_peer_session_param_by_dlg_id(struct peer_mc_cp_stats *mc_stats, uint32_t input_dialog_id, struct wmi_host_twt_session_stats_info @@ -54,26 +58,33 @@ ucfg_twt_get_peer_session_param_by_dlg_id(struct peer_mc_cp_stats *mc_stats, { struct wmi_host_twt_session_stats_info *src_param; uint32_t event_type; - int i; + int i, num_session = 0; + QDF_STATUS qdf_status = QDF_STATUS_E_INVAL; if (!mc_stats || !dest_param) - return false; + return qdf_status; for (i = 0; i < TWT_PEER_MAX_SESSIONS; i++) { event_type = mc_stats->twt_param[i].event_type; src_param = &mc_stats->twt_param[i]; - if ((!event_type) || (src_param->dialog_id != input_dialog_id)) + if (!event_type || + (src_param->dialog_id != input_dialog_id && + input_dialog_id != WLAN_ALL_SESSIONS_DIALOG_ID)) continue; if ((event_type == HOST_TWT_SESSION_SETUP) || (event_type == HOST_TWT_SESSION_UPDATE)) { - qdf_mem_copy(dest_param, src_param, sizeof(*src_param)); - return true; + qdf_mem_copy(&dest_param[num_session], src_param, + sizeof(*src_param)); + qdf_status = QDF_STATUS_SUCCESS; + num_session += 1; + if (num_session >= TWT_PEER_MAX_SESSIONS) + break; } } - return false; + return qdf_status; } /** @@ -114,10 +125,10 @@ ucfg_twt_get_single_peer_session_params(struct wlan_objmgr_psoc *psoc_obj, wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv); peer_mc_stats = peer_cp_stats_priv->peer_stats; - if (ucfg_twt_get_peer_session_param_by_dlg_id(peer_mc_stats, - dialog_id, params)) { - qdf_status = QDF_STATUS_SUCCESS; - } else { + qdf_status = ucfg_twt_get_peer_session_param_by_dlg_id(peer_mc_stats, + dialog_id, + params); + if (QDF_IS_STATUS_ERROR(qdf_status)) { qdf_err("No TWT session for " QDF_MAC_ADDR_FMT " dialog_id %d", QDF_MAC_ADDR_REF(mac_addr), dialog_id); } @@ -192,6 +203,9 @@ ucfg_twt_get_all_peer_session_params(struct wlan_objmgr_psoc *psoc_obj, qdf_list_t *obj_list; int i, num_sessions = 0; + if (!psoc_obj || !params) + return qdf_status; + /* psoc obj lock should be taken before peer list lock */ wlan_psoc_obj_lock(psoc_obj); psoc_objmgr = &psoc_obj->soc_objmgr; @@ -262,18 +276,19 @@ ucfg_twt_get_peer_session_params(struct wlan_objmgr_psoc *psoc_obj, dialog_id = params[0].dialog_id; /* - * Currently twt_get_params nl cmd is sending only dialog_id(STA) and - * mac_addr is being filled by driver in STA peer case. When - * twt_get_params adds support for mac_addr and dialog_id of STA/SAP, - * we need handle unicast/multicast macaddr in - * ucfg_twt_get_all_peer_session_params for all active twt sessions + * Currently for STA case, twt_get_params nl is sending only dialog_id + * and mac_addr is being filled by driver in STA peer case. + * For SAP case, twt_get_params nl is sending dialog_id and + * peer mac_addr. When twt_get_params add mac_addr and dialog_id of + * STA/SAP, we need handle unicast/multicast macaddr in + * ucfg_twt_get_peer_session_params. */ - if (dialog_id <= TWT_MAX_DIALOG_ID) + if (!QDF_IS_ADDR_BROADCAST(mac_addr)) return ucfg_twt_get_single_peer_session_params(psoc_obj, mac_addr, dialog_id, params); - else if (dialog_id == TWT_GET_ALL_PEER_PARAMS_DIALOG_ID) + else return ucfg_twt_get_all_peer_session_params(psoc_obj, params); return QDF_STATUS_E_INVAL; diff --git a/core/hdd/src/wlan_hdd_twt.c b/core/hdd/src/wlan_hdd_twt.c index ecdb96d7f32b..eb57dc585e8a 100644 --- a/core/hdd/src/wlan_hdd_twt.c +++ b/core/hdd/src/wlan_hdd_twt.c @@ -29,6 +29,7 @@ #include "wlan_hdd_twt.h" #include "wlan_hdd_main.h" #include "wlan_hdd_cfg.h" +#include "wlan_hdd_hostapd.h" #include "sme_api.h" #include "wma_twt.h" #include "osif_sync.h" @@ -767,15 +768,82 @@ hdd_twt_get_peer_session_params(struct hdd_context *hdd_ctx, } /** - * hdd_twt_get_session_params() - Parses twt nl attrributes, obtains twt + * hdd_sap_twt_get_session_params() - Parses twt nl attrributes, obtains twt * session parameters based on dialog_id and returns to user via nl layer * @adapter: hdd_adapter * @twt_param_attr: twt nl attributes * * Return: 0 on success, negative value on failure */ -static int hdd_twt_get_session_params(struct hdd_adapter *adapter, - struct nlattr *twt_param_attr) +static int hdd_sap_twt_get_session_params(struct hdd_adapter *adapter, + struct nlattr *twt_param_attr) +{ + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX + 1]; + struct wmi_host_twt_session_stats_info + params[TWT_PSOC_MAX_SESSIONS] = { {0} }; + int ret, id, id1; + QDF_STATUS qdf_status; + struct qdf_mac_addr mac_addr; + bool is_associated; + + ret = wlan_cfg80211_nla_parse_nested( + tb, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX, + twt_param_attr, + qca_wlan_vendor_twt_add_dialog_policy); + if (ret) + return ret; + + id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID; + id1 = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR; + + if (tb[id] && tb[id1]) { + params[0].dialog_id = nla_get_u8(tb[id]); + nla_memcpy(params[0].peer_mac, tb[id1], QDF_MAC_ADDR_SIZE); + } else { + hdd_err_rl("TWT: get_params dialog_id or mac_addr is missing"); + return -EINVAL; + } + + if (QDF_IS_ADDR_BROADCAST(params[0].peer_mac) && + params[0].dialog_id != TWT_ALL_SESSIONS_DIALOG_ID) { + hdd_err_rl("TWT: get_params dialog_is is invalid"); + return -EINVAL; + } + + if (!params[0].dialog_id) + params[0].dialog_id = TWT_ALL_SESSIONS_DIALOG_ID; + + qdf_mem_copy(mac_addr.bytes, params[0].peer_mac, QDF_MAC_ADDR_SIZE); + + if (!qdf_is_macaddr_broadcast(&mac_addr)) { + is_associated = hdd_is_peer_associated(adapter, &mac_addr); + if (!is_associated) { + hdd_err("TWT: Association doesn't exist for STA: " + QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(&mac_addr)); + return -EINVAL; + } + } + + hdd_debug("TWT: get_params dialog_id %d and mac_addr " QDF_MAC_ADDR_FMT, + params[0].dialog_id, QDF_MAC_ADDR_REF(params[0].peer_mac)); + + qdf_status = hdd_twt_get_peer_session_params(adapter->hdd_ctx, + ¶ms[0]); + + return qdf_status_to_os_return(qdf_status); +} + +/** + * hdd_sta_twt_get_session_params() - Parses twt nl attrributes, obtains twt + * session parameters based on dialog_id and returns to user via nl layer + * @adapter: hdd_adapter + * @twt_param_attr: twt nl attributes + * + * Return: 0 on success, negative value on failure + */ +static int hdd_sta_twt_get_session_params(struct hdd_adapter *adapter, + struct nlattr *twt_param_attr) { struct hdd_station_ctx *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); @@ -784,6 +852,7 @@ static int hdd_twt_get_session_params(struct hdd_adapter *adapter, params[TWT_PSOC_MAX_SESSIONS] = { {0} }; int ret, id; QDF_STATUS qdf_status; + struct qdf_mac_addr bcast_addr = QDF_MAC_ADDR_BCAST_INIT; ret = wlan_cfg80211_nla_parse_nested(tb, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX, @@ -812,10 +881,12 @@ static int hdd_twt_get_session_params(struct hdd_adapter *adapter, QDF_MAC_ADDR_SIZE); hdd_debug("TWT: get_params peer mac_addr " QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(params[0].peer_mac)); + } else { + qdf_mem_copy(params[0].peer_mac, &bcast_addr, + QDF_MAC_ADDR_SIZE); } - if ((adapter->device_mode != QDF_SAP_MODE || - params[0].dialog_id != WLAN_ALL_SESSIONS_DIALOG_ID) && + if (params[0].dialog_id != WLAN_ALL_SESSIONS_DIALOG_ID && !ucfg_mlme_is_twt_setup_done(adapter->hdd_ctx->psoc, &hdd_sta_ctx->conn_info.bssid, params[0].dialog_id)) { @@ -826,7 +897,8 @@ static int hdd_twt_get_session_params(struct hdd_adapter *adapter, return qdf_status_to_os_return(qdf_status); } - hdd_debug("TWT: get_params dialog_id %d", params[0].dialog_id); + hdd_debug("TWT: get_params dialog_id %d and mac_addr " QDF_MAC_ADDR_FMT, + params[0].dialog_id, QDF_MAC_ADDR_REF(params[0].peer_mac)); qdf_status = hdd_twt_get_peer_session_params(adapter->hdd_ctx, ¶ms[0]); @@ -834,6 +906,32 @@ static int hdd_twt_get_session_params(struct hdd_adapter *adapter, return qdf_status_to_os_return(qdf_status); } +/** + * hdd_twt_get_session_params() - Parses twt nl attrributes, obtains twt + * session parameters based on dialog_id and returns to user via nl layer + * @adapter: hdd_adapter + * @twt_param_attr: twt nl attributes + * + * Return: 0 on success, negative value on failure + */ +static int hdd_twt_get_session_params(struct hdd_adapter *adapter, + struct nlattr *twt_param_attr) +{ + enum QDF_OPMODE device_mode = adapter->device_mode; + + switch (device_mode) { + case QDF_STA_MODE: + return hdd_sta_twt_get_session_params(adapter, twt_param_attr); + case QDF_SAP_MODE: + return hdd_sap_twt_get_session_params(adapter, twt_param_attr); + default: + hdd_err_rl("TWT terminate is not supported on %s", + qdf_opmode_str(adapter->device_mode)); + } + + return -EOPNOTSUPP; +} + /** * hdd_get_twt_setup_event_len() - Calculates the length of twt * setup nl response