diff --git a/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c b/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c index e6b2047aca71..bd880a2a1e94 100644 --- a/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c +++ b/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c @@ -461,6 +461,12 @@ static void get_station_stats_cb(struct stats_event *ev, void *cookie) summary_size, rssi_size); goto station_stats_cb_fail; } + if (priv->vdev_summary_stats || priv->vdev_chain_rssi || + priv->peer_adv_stats) { + osif_err("invalid context cookie %pK request %pK", + cookie, request); + goto station_stats_cb_fail; + } priv->vdev_summary_stats = qdf_mem_malloc(summary_size); if (!priv->vdev_summary_stats) diff --git a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h index 909c62624589..9420168ce09d 100644 --- a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h +++ b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -158,11 +158,17 @@ QDF_STATUS ucfg_mc_cp_stats_set_pending_req(struct wlan_objmgr_psoc *psoc, * ucfg_mc_cp_stats_reset_pending_req() - API to reset pending request * @psoc: pointer to psoc object * @type: request to update + * @last_req: last request + * @pending: pending request present + * + * The function is an atomic operation of "reset" and "get" last request. * * Return: status of operation */ QDF_STATUS ucfg_mc_cp_stats_reset_pending_req(struct wlan_objmgr_psoc *psoc, - enum stats_req_type type); + enum stats_req_type type, + struct request_info *last_req, + bool *pending); /** * ucfg_mc_cp_stats_get_pending_req() - API to get pending request diff --git a/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c b/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c index 43436ac0d4e6..874643b5d885 100644 --- a/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c +++ b/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c @@ -72,6 +72,7 @@ static void tgt_mc_cp_stats_extract_tx_power(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_vdev *vdev = NULL; struct pdev_mc_cp_stats *pdev_mc_stats; struct pdev_cp_stats *pdev_cp_stats_priv; + bool pending = false; if (!ev->pdev_stats) return; @@ -122,8 +123,10 @@ static void tgt_mc_cp_stats_extract_tx_power(struct wlan_objmgr_psoc *psoc, if (tgt_mc_cp_stats_is_last_event(ev, TYPE_CONNECTION_TX_POWER)) { ucfg_mc_cp_stats_reset_pending_req(psoc, - TYPE_CONNECTION_TX_POWER); - if (last_req.u.get_tx_power_cb) + TYPE_CONNECTION_TX_POWER, + &last_req, + &pending); + if (last_req.u.get_tx_power_cb && pending) last_req.u.get_tx_power_cb(max_pwr, last_req.cookie); } end: @@ -465,9 +468,9 @@ static void tgt_mc_cp_stats_extract_peer_stats(struct wlan_objmgr_psoc *psoc, uint32_t i; QDF_STATUS status; struct request_info last_req = {0}; + bool pending = false; uint32_t selected; - if (is_station_stats) status = ucfg_mc_cp_stats_get_pending_req(psoc, TYPE_STATION_STATS, @@ -542,8 +545,10 @@ complete: tgt_mc_cp_stats_extract_peer_extd_stats(psoc, ev); if (tgt_mc_cp_stats_is_last_event(ev, TYPE_PEER_STATS)) { - ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_PEER_STATS); - tgt_mc_cp_stats_prepare_raw_peer_rssi(psoc, &last_req); + ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_PEER_STATS, + &last_req, &pending); + if (pending && last_req.u.get_peer_rssi_cb) + tgt_mc_cp_stats_prepare_raw_peer_rssi(psoc, &last_req); } } @@ -553,6 +558,7 @@ static void tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc *psoc, { QDF_STATUS status; struct request_info last_req = {0}; + bool pending = false; if (!ev->mib_stats) { cp_stats_debug("no mib stats"); @@ -568,8 +574,9 @@ static void tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc *psoc, } if (tgt_mc_cp_stats_is_last_event(ev, TYPE_MIB_STATS)) { - ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_MIB_STATS); - if (last_req.u.get_mib_stats_cb) + ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_MIB_STATS, + &last_req, &pending); + if (last_req.u.get_mib_stats_cb && pending) last_req.u.get_mib_stats_cb(ev, last_req.cookie); } } @@ -857,6 +864,7 @@ static void tgt_mc_cp_stats_extract_station_stats( { QDF_STATUS status; struct request_info last_req = {0}; + bool pending = false; status = ucfg_mc_cp_stats_get_pending_req(psoc, TYPE_STATION_STATS, @@ -876,9 +884,12 @@ static void tgt_mc_cp_stats_extract_station_stats( * reset type_map bit for station stats . */ if (tgt_mc_cp_stats_is_last_event(ev, TYPE_STATION_STATS)) { - ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_STATION_STATS); - tgt_mc_cp_stats_prepare_n_send_raw_station_stats(psoc, - &last_req); + ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_STATION_STATS, + &last_req, + &pending); + if (pending && last_req.u.get_station_stats_cb) + tgt_mc_cp_stats_prepare_n_send_raw_station_stats( + psoc, &last_req); } } diff --git a/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c b/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c index e93d5a463e0a..44c517de4c30 100644 --- a/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c +++ b/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -532,7 +532,9 @@ QDF_STATUS ucfg_mc_cp_stats_set_pending_req(struct wlan_objmgr_psoc *psoc, } QDF_STATUS ucfg_mc_cp_stats_reset_pending_req(struct wlan_objmgr_psoc *psoc, - enum stats_req_type type) + enum stats_req_type type, + struct request_info *last_req, + bool *pending) { struct psoc_mc_cp_stats *psoc_mc_stats; struct psoc_cp_stats *psoc_cp_stats_priv; @@ -550,6 +552,12 @@ QDF_STATUS ucfg_mc_cp_stats_reset_pending_req(struct wlan_objmgr_psoc *psoc, wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv); psoc_mc_stats = psoc_cp_stats_priv->obj_stats; + if (psoc_mc_stats->pending.type_map & (1 << type)) { + *last_req = psoc_mc_stats->pending.req[type]; + *pending = true; + } else { + *pending = false; + } psoc_mc_stats->pending.type_map &= ~(1 << type); qdf_mem_zero(&psoc_mc_stats->pending.req[type], sizeof(psoc_mc_stats->pending.req[type]));