qcacld-3.0: Classify qmi/wmi for WMI_REQUEST_STATS_CMDID

Current only TYPE_STATION_STATS is designed to be send
by qmi. and other request type should send by wmi.
if sending by qmi, qmi_get/qmi_put should be call to protect
qmi send and qmi response.

Change to check type and only allow TYPE_STATION_STATS to be
send by qmi.

Change-Id: I57b0bdb6717e259606993ea24ef024745a456664
CRs-Fixed: 3073744
This commit is contained in:
Jingxiang Ge 2021-11-17 20:03:26 +08:00
parent 071b358fb0
commit b160a90b1e
5 changed files with 114 additions and 70 deletions

View File

@ -1320,11 +1320,20 @@ static QDF_STATUS target_if_cp_stats_send_stats_req(
cp_stats_err("wmi_handle is null."); cp_stats_err("wmi_handle is null.");
return QDF_STATUS_E_NULL_VALUE; return QDF_STATUS_E_NULL_VALUE;
} }
/* refer (WMI_REQUEST_STATS_CMDID) */ /* refer (WMI_REQUEST_STATS_CMDID) */
param.stats_id = get_stats_id(type); param.stats_id = get_stats_id(type);
param.vdev_id = req->vdev_id; param.vdev_id = req->vdev_id;
param.pdev_id = req->pdev_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, return wmi_unified_stats_request_send(wmi_handle, req->peer_mac_addr,
&param); &param);
} }

View File

@ -43,6 +43,7 @@
#include <cdp_txrx_stats_struct.h> #include <cdp_txrx_stats_struct.h>
#include <cdp_txrx_peer_ops.h> #include <cdp_txrx_peer_ops.h>
#include <cdp_txrx_host_stats.h> #include <cdp_txrx_host_stats.h>
#include "wlan_hdd_stats.h"
/* /*
* define short names for the global vendor params * 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) if (errno)
return 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); 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); osif_vdev_sync_op_stop(vdev_sync);
return errno; return errno;

View File

@ -242,6 +242,79 @@ hdd_update_station_stats_cached_timestamp(struct hdd_adapter *adapter)
} }
#endif /* FEATURE_CLUB_LL_STATS_AND_GET_STATION */ #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 #ifdef WLAN_FEATURE_LINK_LAYER_STATS
/** /**
@ -2113,61 +2186,6 @@ __wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy,
return 0; 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 * wlan_hdd_cfg80211_ll_stats_get() - get ll stats
* @wiphy: Pointer to wiphy * @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 hdd_context *hdd_ctx = wiphy_priv(wiphy);
struct osif_vdev_sync *vdev_sync; struct osif_vdev_sync *vdev_sync;
int errno; int errno;
qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
errno = wlan_hdd_validate_context(hdd_ctx); errno = wlan_hdd_validate_context(hdd_ctx);
if (0 != errno) if (0 != errno)
return -EINVAL; return -EINVAL;
if (!qdf_ctx)
return -EINVAL;
errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync); errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
if (errno) if (errno)
return errno; return errno;
errno = wlan_hdd_qmi_get_sync_resume(hdd_ctx, qdf_ctx->dev); errno = wlan_hdd_qmi_get_sync_resume();
if (errno) if (errno) {
hdd_err("qmi sync resume failed: %d", errno);
goto end; goto end;
}
errno = __wlan_hdd_cfg80211_ll_stats_get(wiphy, wdev, data, data_len); 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: end:
osif_vdev_sync_op_stop(vdev_sync); 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_context *hdd_ctx = wiphy_priv(wiphy);
struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 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; int errno;
QDF_STATUS status; QDF_STATUS status;
@ -5945,9 +5959,6 @@ static int _wlan_hdd_cfg80211_get_station(struct wiphy *wiphy,
if (errno) if (errno)
return errno; return errno;
if (!qdf_ctx)
return -EINVAL;
status = wlan_hdd_stats_request_needed(adapter); status = wlan_hdd_stats_request_needed(adapter);
if (QDF_IS_STATUS_ERROR(status)) { if (QDF_IS_STATUS_ERROR(status)) {
if (status == QDF_STATUS_E_ALREADY) 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) { if (get_station_fw_request_needed) {
errno = wlan_hdd_qmi_get_sync_resume(hdd_ctx, qdf_ctx->dev); errno = wlan_hdd_qmi_get_sync_resume();
if (errno) if (errno) {
hdd_err("qmi sync resume failed: %d", errno);
return errno; return errno;
}
} }
errno = __wlan_hdd_cfg80211_get_station(wiphy, dev, mac, sinfo); errno = __wlan_hdd_cfg80211_get_station(wiphy, dev, mac, sinfo);
if (get_station_fw_request_needed) 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; get_station_fw_request_needed = true;

View File

@ -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_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 #ifdef WLAN_FEATURE_BIG_DATA_STATS
/** /**
* wlan_hdd_get_big_data_station_stats() - Get big data station statistics * wlan_hdd_get_big_data_station_stats() - Get big data station statistics

View File

@ -8387,8 +8387,17 @@ static int iw_get_statistics(struct net_device *dev,
if (errno) if (errno)
return 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); errno = __iw_get_statistics(dev, info, wrqu, extra);
wlan_hdd_qmi_put_suspend();
end:
osif_vdev_sync_op_stop(vdev_sync); osif_vdev_sync_op_stop(vdev_sync);
return errno; return errno;