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
このコミットが含まれているのは:
@@ -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;
|
||||
}
|
||||
|
新しいイシューから参照
ユーザーをブロックする