diff --git a/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h b/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h index 8f51c3c557aa..9b5788deadcc 100644 --- a/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h +++ b/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h @@ -153,6 +153,21 @@ QDF_STATUS ucfg_mc_cp_stats_send_stats_request(struct wlan_objmgr_vdev *vdev, enum stats_req_type type, struct request_info *info); +/** + * wlan_cfg80211_mc_twt_clear_infra_cp_stats() - send request to reset + * control path statistics + * @vdev: pointer to vdev object + * @dialog_id: dialod id of the twt session + * @twt_peer_mac: mac address of the peer + * + * Return: 0 for success or error code for failure + */ +int +wlan_cfg80211_mc_twt_clear_infra_cp_stats( + struct wlan_objmgr_vdev *vdev, + uint32_t dialog_id, + uint8_t twt_peer_mac[QDF_MAC_ADDR_SIZE]); + /** * wlan_cfg80211_mc_twt_get_infra_cp_stats() - send twt get statistic request * @vdev: pointer to vdev object diff --git a/core/hdd/src/wlan_hdd_twt.c b/core/hdd/src/wlan_hdd_twt.c index 0124cdfb8061..f403a848d90b 100644 --- a/core/hdd/src/wlan_hdd_twt.c +++ b/core/hdd/src/wlan_hdd_twt.c @@ -2558,6 +2558,52 @@ hdd_twt_pack_get_stats_resp_nlmsg(struct sk_buff *reply_skb, return QDF_STATUS_SUCCESS; } +/** + * hdd_twt_clear_session_traffic_stats() - Parses twt nl attrributes and + * sends clear twt stats request for a single or all sessions + * @adapter: hdd_adapter + * @twt_param_attr: twt nl attributes + * + * Return: 0 on success, negative value on failure + */ +static int hdd_twt_clear_session_traffic_stats(struct hdd_adapter *adapter, + struct nlattr *twt_param_attr) +{ + struct hdd_station_ctx *hdd_sta_ctx = + WLAN_HDD_GET_STATION_CTX_PTR(adapter); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX + 1]; + int ret, id; + uint32_t dialog_id; + uint8_t peer_mac[QDF_MAC_ADDR_SIZE]; + + ret = wlan_cfg80211_nla_parse_nested( + tb, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX, + twt_param_attr, + qca_wlan_vendor_twt_stats_dialog_policy); + if (ret) + return ret; + + id = QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID; + if (!tb[id]) { + hdd_err_rl("TWT Clear stats - dialog id param is must"); + return -EINVAL; + } + + dialog_id = (uint32_t)nla_get_u8(tb[id]); + + qdf_mem_copy(peer_mac, + hdd_sta_ctx->conn_info.bssid.bytes, + QDF_MAC_ADDR_SIZE); + hdd_debug("dialog_id %d peer mac_addr " QDF_MAC_ADDR_FMT, + dialog_id, QDF_MAC_ADDR_REF(peer_mac)); + + ret = wlan_cfg80211_mc_twt_clear_infra_cp_stats(adapter->vdev, + dialog_id, peer_mac); + + return ret; +} + /** * hdd_twt_get_session_traffic_stats() - Obtains twt session traffic statistics * and sends response to the user space @@ -2794,6 +2840,10 @@ static int hdd_twt_configure(struct hdd_adapter *adapter, ret = hdd_twt_get_session_traffic_stats(adapter, twt_param_attr); break; + case QCA_WLAN_TWT_CLEAR_STATS: + ret = hdd_twt_clear_session_traffic_stats(adapter, + twt_param_attr); + break; default: hdd_err("Invalid TWT Operation"); ret = -EINVAL; diff --git a/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c b/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c index 9d9a2a75ca47..66ae93ec09a3 100644 --- a/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c +++ b/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c @@ -769,6 +769,129 @@ get_twt_stats_fail: return NULL; } + +/** + * infra_cp_stats_reset_cb() - callback function to handle stats event + * due to reset action + * @ev: stats event buffer + * @cookie: a cookie for the request context + * + * Return: None + */ +static void infra_cp_stats_reset_cb(struct infra_cp_stats_event *ev, + void *cookie) +{ + struct infra_cp_stats_event *priv; + struct osif_request *request; + + request = osif_request_get(cookie); + if (!request) { + osif_err("Obsolete request"); + return; + } + + priv = osif_request_priv(request); + + osif_debug("clear stats action %d req_id %d, status %d num_cp_stats %d", + ev->action, ev->request_id, ev->status, + ev->num_twt_infra_cp_stats); + + osif_request_complete(request); + osif_request_put(request); +} + +/** + * @wlan_cfg80211_mc_twt_clear_infra_cp_stats() - send clear twt statistics + * request to firmware + * @vdev: vdev id + * @dialog_id: dialog id of the twt session. + * @twt_peer_mac: peer mac address + * + * Return: 0 for success or error code for failure + */ +int +wlan_cfg80211_mc_twt_clear_infra_cp_stats( + struct wlan_objmgr_vdev *vdev, + uint32_t dialog_id, + uint8_t twt_peer_mac[QDF_MAC_ADDR_SIZE]) +{ + int ret; + void *cookie; + QDF_STATUS status; + struct infra_cp_stats_event *priv; + struct wlan_objmgr_peer *peer; + struct osif_request *request; + struct infra_cp_stats_cmd_info info = {0}; + static const struct osif_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = 2 * CP_STATS_WAIT_TIME_STAT, + .dealloc = wlan_cfg80211_mc_infra_cp_stats_dealloc, + }; + + osif_debug("Enter"); + + request = osif_request_alloc(¶ms); + if (!request) + return -ENOMEM; + + cookie = osif_request_cookie(request); + priv = osif_request_priv(request); + + priv->twt_infra_cp_stats = + qdf_mem_malloc(sizeof(*priv->twt_infra_cp_stats)); + if (!priv->twt_infra_cp_stats) { + ret = -ENOMEM; + goto clear_twt_stats_fail; + } + + info.request_cookie = cookie; + info.stats_id = TYPE_REQ_CTRL_PATH_TWT_STAT; + info.action = ACTION_REQ_CTRL_PATH_STAT_RESET; + + info.infra_cp_stats_resp_cb = infra_cp_stats_reset_cb; + info.num_pdev_ids = 0; + info.num_vdev_ids = MAX_TWT_STAT_VDEV_ENTRIES; + info.vdev_id[0] = wlan_vdev_get_id(vdev); + info.num_mac_addr_list = MAX_TWT_STAT_MAC_ADDR_ENTRIES; + qdf_mem_copy(&info.peer_mac_addr[0], twt_peer_mac, QDF_MAC_ADDR_SIZE); + + info.dialog_id = dialog_id; + info.num_pdev_ids = 0; + + peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_CP_STATS_ID); + if (!peer) { + osif_err("peer is null"); + ret = -EINVAL; + goto clear_twt_stats_fail; + } + wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); + + status = ucfg_infra_cp_stats_register_resp_cb(wlan_vdev_get_psoc(vdev), + &info); + if (QDF_IS_STATUS_ERROR(status)) { + osif_err("Failed to register resp callback: %d", status); + ret = qdf_status_to_os_return(status); + goto clear_twt_stats_fail; + } + + status = ucfg_send_infra_cp_stats_request(vdev, &info); + if (QDF_IS_STATUS_ERROR(status)) { + osif_err("Failed to send twt stats request status: %d", + status); + ret = qdf_status_to_os_return(status); + goto clear_twt_stats_fail; + } + + ret = osif_request_wait_for_response(request); + if (ret) + osif_err("wait failed or timed out ret: %d", ret); + +clear_twt_stats_fail: + osif_request_put(request); + osif_debug("Exit"); + + return ret; +} #endif #endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */