qcacld-3.0: Cache and tx power as part of cp station stats

In the driver, if CLUB_LL_STATS_AND_GET_STATION feature is
enabled, host requests Link Layer stats and station stats
from firmware periodically using a single WMI command.

Host then sends LL_STATS to userspace and caches station stats
in the adapter. Whenever userspace queries station stats, based
on the sta_stats_cached_timestamp, host returns cached stats
from adapter instead of sending a new WMI request.

The current issue, as part of station stats firmware also sends
connection_tx_power stats, which aren't cached into the adapter.
So, whenever userspace queries get_tx_power via nl commands,
host sends a WMI request to firmware for tx_power leading to
platform wakeups and power impacts.

To resolve this issue, cache the tx_power sent by firmware into
the adapter during station stats and return the cached value to
the user space.

Change-Id: Iaefc5629872431cbc6c24090b1edb6cebdad995a
CRs-Fixed: 3439323
このコミットが含まれているのは:
Aditya Kodukula
2023-03-23 13:48:07 -07:00
committed by Madan Koyyalamudi
コミット 3336cc1673
4個のファイルの変更99行の追加10行の削除

ファイルの表示

@@ -1100,6 +1100,58 @@ tgt_send_peer_mc_cp_stats(struct wlan_objmgr_psoc *psoc,
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS
tgt_send_pdev_mc_cp_stats(struct wlan_objmgr_psoc *psoc,
struct stats_event *ev,
struct request_info *last_req)
{
struct wlan_objmgr_pdev *pdev;
struct wlan_objmgr_vdev *vdev = NULL;
struct pdev_mc_cp_stats *pdev_mc_stats;
struct pdev_cp_stats *pdev_cp_stats_priv;
int pdev_id;
if (!ev || !last_req)
return QDF_STATUS_E_NULL_VALUE;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, last_req->vdev_id,
WLAN_CP_STATS_ID);
if (!vdev) {
cp_stats_err("vdev is null");
return QDF_STATUS_E_NULL_VALUE;
}
pdev = wlan_vdev_get_pdev(vdev);
if (!pdev) {
cp_stats_err("pdev is null");
goto end;
}
pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
if (pdev_id != last_req->pdev_id) {
cp_stats_err("pdev_id: %d invalid", pdev_id);
goto end;
}
pdev_cp_stats_priv = wlan_cp_stats_get_pdev_stats_obj(pdev);
if (!pdev_cp_stats_priv) {
cp_stats_err("pdev_cp_stats_priv is null");
goto end;
}
wlan_cp_stats_pdev_obj_lock(pdev_cp_stats_priv);
pdev_mc_stats = pdev_cp_stats_priv->pdev_stats;
ev->pdev_stats->max_pwr = pdev_mc_stats->max_pwr;
wlan_cp_stats_pdev_obj_unlock(pdev_cp_stats_priv);
wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
return QDF_STATUS_SUCCESS;
end:
wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
return QDF_STATUS_E_NULL_VALUE;
}
static void
tgt_mc_cp_stats_send_raw_station_stats(struct wlan_objmgr_psoc *psoc,
struct request_info *last_req)
@@ -1138,6 +1190,17 @@ tgt_mc_cp_stats_send_raw_station_stats(struct wlan_objmgr_psoc *psoc,
cp_stats_err("tgt_send_peer_mc_cp_stats failed");
goto end;
}
info.num_pdev_stats = 1;
info.pdev_stats = qdf_mem_malloc(sizeof(*info.pdev_stats));
if (!info.pdev_stats)
goto end;
status = tgt_send_pdev_mc_cp_stats(psoc, &info, last_req);
if (QDF_IS_STATUS_ERROR(status)) {
cp_stats_err("tgt_send_pdev_mc_cp_stats failed");
goto end;
}
end:
get_station_stats_cb(&info, last_req->cookie);

ファイルの表示

@@ -1160,6 +1160,7 @@ struct wlan_hdd_link_info {
* @is_dbam_configured:
* @deflink: Default link pointing to the 0th index of the linkinfo array
* @link_info: Data structure to hold link specific information
* @tx_pwr: connection tx power sent by firmware
*/
struct hdd_adapter {
uint32_t magic;
@@ -1355,6 +1356,7 @@ struct hdd_adapter {
#endif
struct wlan_hdd_link_info *deflink;
struct wlan_hdd_link_info link_info[WLAN_MAX_MLD];
int tx_pwr;
};
#define WLAN_HDD_GET_STATION_CTX_PTR(adapter) \

ファイルの表示

@@ -3194,20 +3194,39 @@ int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
return errno;
}
static void wlan_hdd_get_tx_power(struct hdd_adapter *adapter, int *dbm)
#ifdef FEATURE_CLUB_LL_STATS_AND_GET_STATION
static int wlan_hdd_get_tx_power(struct hdd_adapter *adapter, int *dbm)
{
if (hdd_validate_adapter(adapter)) {
hdd_err("Invalid adapter");
return -EINVAL;
}
/* TX_POWER is sent by STATION_STATS by firmware and
* is copied into the adapter. So, return the cached value.
*/
*dbm = adapter->tx_pwr;
hdd_nofl_debug("cached tx_power: %d", *dbm);
return 0;
}
#else
static int wlan_hdd_get_tx_power(struct hdd_adapter *adapter, int *dbm)
{
struct wlan_objmgr_vdev *vdev;
int ret;
vdev = hdd_objmgr_get_vdev_by_user(adapter, WLAN_OSIF_POWER_ID);
if (!vdev) {
hdd_info("vdev is NULL");
return;
return -EINVAL;
}
wlan_cfg80211_mc_cp_stats_get_tx_power(vdev, dbm);
ret = wlan_cfg80211_mc_cp_stats_get_tx_power(vdev, dbm);
hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
hdd_debug("power: %d", *dbm);
return ret;
}
#endif
#ifdef FEATURE_ANI_LEVEL_REQUEST
static void hdd_get_ani_level_cb(struct wmi_host_ani_level_event *ani,
@@ -3398,10 +3417,7 @@ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
TRACE_CODE_HDD_CFG80211_GET_TXPOWER,
adapter->deflink->vdev_id, adapter->device_mode);
wlan_hdd_get_tx_power(adapter, dbm);
hdd_debug("power: %d", *dbm);
return 0;
return wlan_hdd_get_tx_power(adapter, dbm);
}
int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,

ファイルの表示

@@ -270,6 +270,7 @@ static int copy_station_stats_to_adapter(struct hdd_adapter *adapter,
stats->peer_adv_stats->rx_bytes;
adapter->hdd_stats.peer_stats.fcs_count =
stats->peer_adv_stats->fcs_count;
adapter->tx_pwr = stats->pdev_stats->max_pwr;
dynamic_cfg = mlme_get_dynamic_vdev_config(vdev);
if (!dynamic_cfg) {
@@ -2076,7 +2077,7 @@ static void cache_station_stats_cb(struct stats_event *ev, void *cookie)
wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_DISPLAY_TXRX_STATS;
if (!ev->vdev_summary_stats || !ev->vdev_chain_rssi ||
!ev->peer_adv_stats) {
!ev->peer_adv_stats || !ev->pdev_stats) {
hdd_debug("Invalid stats");
return;
}
@@ -7648,16 +7649,23 @@ int wlan_hdd_get_station_stats(struct hdd_adapter *adapter)
stats = wlan_cfg80211_mc_cp_stats_get_station_stats(vdev, &ret);
if (ret || !stats) {
wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
hdd_err("Invalid stats");
goto out;
}
if (!stats->vdev_summary_stats || !stats->vdev_chain_rssi ||
!stats->peer_adv_stats || !stats->pdev_stats) {
hdd_err("Invalid stats");
ret = -EINVAL;
goto out;
}
/* update get stats cached time stamp */
hdd_update_station_stats_cached_timestamp(adapter);
copy_station_stats_to_adapter(adapter, stats);
wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
out:
wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_STATS_ID);
return ret;
}