diff --git a/components/target_if/cp_stats/src/target_if_mc_cp_stats.c b/components/target_if/cp_stats/src/target_if_mc_cp_stats.c index 212cf43db57f9..c56b15bde0147 100644 --- a/components/target_if/cp_stats/src/target_if_mc_cp_stats.c +++ b/components/target_if/cp_stats/src/target_if_mc_cp_stats.c @@ -1320,11 +1320,20 @@ static QDF_STATUS target_if_cp_stats_send_stats_req( cp_stats_err("wmi_handle is null."); return QDF_STATUS_E_NULL_VALUE; } + /* refer (WMI_REQUEST_STATS_CMDID) */ param.stats_id = get_stats_id(type); param.vdev_id = req->vdev_id; param.pdev_id = req->pdev_id; + /* only very frequent periodic stats needs to go over QMI. + * for that, wlan_hdd_qmi_get_sync_resume/wlan_hdd_qmi_put_suspend + * needs to be called to cover the period between qmi send and + * qmi resonse. + */ + if (TYPE_STATION_STATS == type) + param.is_qmi_send_support = true; + return wmi_unified_stats_request_send(wmi_handle, req->peer_mac_addr, ¶m); } diff --git a/core/hdd/src/wlan_hdd_station_info.c b/core/hdd/src/wlan_hdd_station_info.c index d67a79f7f683e..58cd393632f63 100644 --- a/core/hdd/src/wlan_hdd_station_info.c +++ b/core/hdd/src/wlan_hdd_station_info.c @@ -43,6 +43,7 @@ #include #include #include +#include "wlan_hdd_stats.h" /* * define short names for the global vendor params @@ -2417,8 +2418,17 @@ int32_t hdd_cfg80211_get_sta_info_cmd(struct wiphy *wiphy, if (errno) return errno; + errno = wlan_hdd_qmi_get_sync_resume(); + if (errno) { + hdd_err("qmi sync resume failed: %d", errno); + goto end; + } + errno = __hdd_cfg80211_get_sta_info_cmd(wiphy, wdev, data, data_len); + wlan_hdd_qmi_put_suspend(); + +end: osif_vdev_sync_op_stop(vdev_sync); return errno; diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index f98b31da36346..ab29510d38bd7 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -242,6 +242,79 @@ hdd_update_station_stats_cached_timestamp(struct hdd_adapter *adapter) } #endif /* FEATURE_CLUB_LL_STATS_AND_GET_STATION */ +#ifdef WLAN_FEATURE_WMI_SEND_RECV_QMI +/** + * wlan_hdd_qmi_get_sync_resume() - Get operation to trigger RTPM + * sync resume without WoW exit + * + * call qmi_get before sending qmi, and do qmi_put after all the + * qmi response rececived from fw. so this request wlan host to + * wait for the last qmi response, if it doesn't wait, qmi put + * which cause MHI enter M3(suspend) before all the qmi response, + * and MHI will trigger a RTPM resume, this violated design of by + * sending cmd by qmi without wow resume. + * + * Returns: 0 for success, non-zero for failure + */ +int wlan_hdd_qmi_get_sync_resume(void) +{ + struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); + + if (wlan_hdd_validate_context(hdd_ctx)) + return -EINVAL; + + if (!hdd_ctx->config->is_qmi_stats_enabled) { + hdd_debug("periodic stats over qmi is disabled"); + return 0; + } + + if (!qdf_ctx) { + hdd_err("qdf_ctx is null"); + return -EINVAL; + } + + return pld_qmi_send_get(qdf_ctx->dev); +} + +/** + * wlan_hdd_qmi_put_suspend() - Put operation to trigger RTPM suspend + * without WoW entry + * + * Returns: 0 for success, non-zero for failure + */ +int wlan_hdd_qmi_put_suspend(void) +{ + struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); + + if (wlan_hdd_validate_context(hdd_ctx)) + return -EINVAL; + + if (!hdd_ctx->config->is_qmi_stats_enabled) { + hdd_debug("periodic stats over qmi is disabled"); + return 0; + } + + if (!qdf_ctx) { + hdd_err("qdf_ctx is null"); + return -EINVAL; + } + + return pld_qmi_send_put(qdf_ctx->dev); +} +#else +int wlan_hdd_qmi_get_sync_resume(void) +{ + return 0; +} + +int wlan_hdd_qmi_put_suspend(void) +{ + return 0; +} +#endif /* end if of WLAN_FEATURE_WMI_SEND_RECV_QMI */ + #ifdef WLAN_FEATURE_LINK_LAYER_STATS /** @@ -2113,61 +2186,6 @@ __wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy, return 0; } -#ifdef WLAN_FEATURE_WMI_SEND_RECV_QMI -/** - * wlan_hdd_qmi_get_sync_resume() - Get operation to trigger RTPM - * sync resume without WoW exit - * @hdd_ctx: hdd context - * @dev: device context - * - * Returns: 0 for success, non-zero for failure - */ -static inline -int wlan_hdd_qmi_get_sync_resume(struct hdd_context *hdd_ctx, - struct device *dev) -{ - if (!hdd_ctx->config->is_qmi_stats_enabled) { - hdd_debug("periodic stats over qmi is disabled"); - return 0; - } - - return pld_qmi_send_get(dev); -} - -/** - * wlan_hdd_qmi_put_suspend() - Put operation to trigger RTPM suspend - * without WoW entry - * @hdd_ctx: hdd context - * @dev: device context - * - * Returns: 0 for success, non-zero for failure - */ -static inline -int wlan_hdd_qmi_put_suspend(struct hdd_context *hdd_ctx, - struct device *dev) -{ - if (!hdd_ctx->config->is_qmi_stats_enabled) { - hdd_debug("periodic stats over qmi is disabled"); - return 0; - } - - return pld_qmi_send_put(dev); -} -#else -static inline -int wlan_hdd_qmi_get_sync_resume(struct hdd_context *hdd_ctx, - struct device *dev) -{ - return 0; -} - -static inline int wlan_hdd_qmi_put_suspend(struct hdd_context *hdd_ctx, - struct device *dev) -{ - return 0; -} -#endif /* end if of WLAN_FEATURE_WMI_SEND_RECV_QMI */ - /** * wlan_hdd_cfg80211_ll_stats_get() - get ll stats * @wiphy: Pointer to wiphy @@ -2185,26 +2203,23 @@ int wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy, struct hdd_context *hdd_ctx = wiphy_priv(wiphy); struct osif_vdev_sync *vdev_sync; int errno; - qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); errno = wlan_hdd_validate_context(hdd_ctx); if (0 != errno) return -EINVAL; - if (!qdf_ctx) - return -EINVAL; - errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync); if (errno) return errno; - errno = wlan_hdd_qmi_get_sync_resume(hdd_ctx, qdf_ctx->dev); - if (errno) + errno = wlan_hdd_qmi_get_sync_resume(); + if (errno) { + hdd_err("qmi sync resume failed: %d", errno); goto end; - + } errno = __wlan_hdd_cfg80211_ll_stats_get(wiphy, wdev, data, data_len); - wlan_hdd_qmi_put_suspend(hdd_ctx, qdf_ctx->dev); + wlan_hdd_qmi_put_suspend(); end: osif_vdev_sync_op_stop(vdev_sync); @@ -5937,7 +5952,6 @@ static int _wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, { struct hdd_context *hdd_ctx = wiphy_priv(wiphy); struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); - qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); int errno; QDF_STATUS status; @@ -5945,9 +5959,6 @@ static int _wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, if (errno) return errno; - if (!qdf_ctx) - return -EINVAL; - status = wlan_hdd_stats_request_needed(adapter); if (QDF_IS_STATUS_ERROR(status)) { if (status == QDF_STATUS_E_ALREADY) @@ -5957,15 +5968,17 @@ static int _wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, } if (get_station_fw_request_needed) { - errno = wlan_hdd_qmi_get_sync_resume(hdd_ctx, qdf_ctx->dev); - if (errno) + errno = wlan_hdd_qmi_get_sync_resume(); + if (errno) { + hdd_err("qmi sync resume failed: %d", errno); return errno; + } } errno = __wlan_hdd_cfg80211_get_station(wiphy, dev, mac, sinfo); if (get_station_fw_request_needed) - wlan_hdd_qmi_put_suspend(hdd_ctx, qdf_ctx->dev); + wlan_hdd_qmi_put_suspend(); get_station_fw_request_needed = true; diff --git a/core/hdd/src/wlan_hdd_stats.h b/core/hdd/src/wlan_hdd_stats.h index a7277e5395d76..0a2ce6cfd28d9 100644 --- a/core/hdd/src/wlan_hdd_stats.h +++ b/core/hdd/src/wlan_hdd_stats.h @@ -492,6 +492,9 @@ int wlan_hdd_get_link_speed(struct hdd_adapter *adapter, uint32_t *link_speed); */ int wlan_hdd_get_station_stats(struct hdd_adapter *adapter); +int wlan_hdd_qmi_get_sync_resume(void); +int wlan_hdd_qmi_put_suspend(void); + #ifdef WLAN_FEATURE_BIG_DATA_STATS /** * wlan_hdd_get_big_data_station_stats() - Get big data station statistics diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 9c2372bf8c806..314e96e69cadb 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -8387,8 +8387,17 @@ static int iw_get_statistics(struct net_device *dev, if (errno) return errno; + errno = wlan_hdd_qmi_get_sync_resume(); + if (errno) { + hdd_err("qmi sync resume failed: %d", errno); + goto end; + } + errno = __iw_get_statistics(dev, info, wrqu, extra); + wlan_hdd_qmi_put_suspend(); + +end: osif_vdev_sync_op_stop(vdev_sync); return errno;