qcacld-3.0: API to report congestion

API to report congestion to userspace.

Change-Id: I324ae6701dace590daaa2c3f80412d6633cbf8f0
CRs-Fixed: 2766432
此提交包含在:
Min Liu
2020-08-31 18:43:18 +08:00
提交者 snandini
父節點 f1a04e6d05
當前提交 47d4029c67
共有 10 個檔案被更改,包括 612 行新增2 行删除

查看文件

@@ -56,6 +56,7 @@
* @TYPE_PEER_STATS: peer stats was requested
* @TYPE_MIB_STATS: MIB stats was requested
* @TYPE_PEER_STATS_INFO_EXT: peer stats info ext was requested
* @TYPE_CONGESTION_STATS: congestion stats was requested
*/
enum stats_req_type {
TYPE_CONNECTION_TX_POWER = 0,
@@ -63,6 +64,7 @@ enum stats_req_type {
TYPE_PEER_STATS,
TYPE_MIB_STATS,
TYPE_PEER_STATS_INFO_EXT,
TYPE_CONGESTION_STATS,
TYPE_MAX,
};
@@ -174,7 +176,8 @@ struct stats_event;
* struct request_info: details of each request
* @cookie: identifier for os_if request
* @u: unified data type for callback to process tx power/peer rssi/
* station stats/mib stats request when response comes.
* station stats/mib stats/peer stats request when response comes and
* notification callback when congestion is detected.
* @vdev_id: vdev_id of request
* @pdev_id: pdev_id of request
* @peer_mac_addr: peer mac address
@@ -190,6 +193,7 @@ struct request_info {
void *cookie);
void (*get_peer_stats_cb)(struct stats_event *ev,
void *cookie);
void (*congestion_notif_cb)(uint8_t congestion);
} u;
uint32_t vdev_id;
uint32_t pdev_id;
@@ -232,10 +236,20 @@ struct psoc_mc_cp_stats {
/**
* struct pdev_mc_cp_stats: pdev specific stats
* @max_pwr: max tx power for vdev
* @max_pwr: max tx power for pdev
* @congestion: percentage of congestion = (busy_time / total_time) * 100
* @congestion_threshold: threshold for congestion precentage of pdev
* @rx_clear_count: accumulative rx clear count (busy time) of pdev
* @cycle_count: accumulative cycle count (total time) of pdev
*/
struct pdev_mc_cp_stats {
int32_t max_pwr;
#ifdef WLAN_FEATURE_MEDIUM_ASSESS
uint8_t congestion;
uint8_t congestion_threshold;
uint32_t rx_clear_count;
uint32_t cycle_count;
#endif
};
/**

查看文件

@@ -163,6 +163,43 @@ QDF_STATUS ucfg_mc_cp_stats_send_stats_request(struct wlan_objmgr_vdev *vdev,
QDF_STATUS ucfg_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev,
int *dbm);
#ifdef WLAN_FEATURE_MEDIUM_ASSESS
/**
* ucfg_mc_cp_stats_reset_congestion_counter() - API to reset congestion
* counter
* @vdev: pointer to vdev object
*
* Return: status of operation
*/
QDF_STATUS
ucfg_mc_cp_stats_reset_congestion_counter(struct wlan_objmgr_vdev *vdev);
/**
* ucfg_mc_cp_stats_set_congestion_threshold() - API to configure congestion
* threshold
* @vdev: pointer to vdev object
* @threshold: congestion threshold
*
* Return: status of operation
*/
QDF_STATUS
ucfg_mc_cp_stats_set_congestion_threshold(struct wlan_objmgr_vdev *vdev,
uint8_t threshold);
#else
static inline QDF_STATUS
ucfg_mc_cp_stats_reset_congestion_counter(struct wlan_objmgr_vdev *vdev)
{
return QDF_STATUS_SUCCESS;
}
static inline QDF_STATUS
ucfg_mc_cp_stats_set_congestion_threshold(struct wlan_objmgr_vdev *vdev,
uint8_t threshold)
{
return QDF_STATUS_SUCCESS;
}
#endif
/**
* ucfg_mc_cp_stats_is_req_pending() - API to tell if given request is pending
* @psoc: pointer to psoc object

查看文件

@@ -615,6 +615,108 @@ tgt_mc_cp_stats_extract_peer_stats_info_ext(struct wlan_objmgr_psoc *psoc,
}
}
#ifdef WLAN_FEATURE_MEDIUM_ASSESS
static void
tgt_mc_cp_stats_extract_congestion_stats(struct wlan_objmgr_psoc *psoc,
struct stats_event *ev)
{
QDF_STATUS status;
struct request_info last_req = {0};
struct wlan_objmgr_pdev *pdev;
struct pdev_mc_cp_stats *pdev_mc_stats, *fw_pdev_stats;
struct pdev_cp_stats *pdev_cp_stats_priv;
uint32_t rx_clear_count_delta, cycle_count_delta;
uint8_t congestion = 0;
bool is_congested = false;
if (!ev->pdev_stats) {
cp_stats_debug("no pdev_stats");
return;
}
status = ucfg_mc_cp_stats_get_pending_req(psoc,
TYPE_CONGESTION_STATS,
&last_req);
if (QDF_IS_STATUS_ERROR(status)) {
cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
return;
}
/* Check if stats for the specific pdev is present */
if (last_req.pdev_id >= ev->num_pdev_stats) {
cp_stats_err("no stat for pdev %d ", last_req.pdev_id);
return;
}
pdev = wlan_objmgr_get_pdev_by_id(psoc, last_req.pdev_id,
WLAN_CP_STATS_ID);
if (!pdev) {
cp_stats_err("pdev is null");
return;
}
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 out;
}
wlan_cp_stats_pdev_obj_lock(pdev_cp_stats_priv);
pdev_mc_stats = pdev_cp_stats_priv->pdev_stats;
fw_pdev_stats = &ev->pdev_stats[last_req.pdev_id];
/*
* Skip calculating deltas and congestion for the first received event
* since enabled
*/
if (pdev_mc_stats->cycle_count || pdev_mc_stats->rx_clear_count) {
if (fw_pdev_stats->rx_clear_count >=
pdev_mc_stats->rx_clear_count) {
rx_clear_count_delta = fw_pdev_stats->rx_clear_count -
pdev_mc_stats->rx_clear_count;
} else {
/* Wrap around case */
rx_clear_count_delta = U32_MAX -
pdev_mc_stats->rx_clear_count;
rx_clear_count_delta += fw_pdev_stats->rx_clear_count;
}
if (fw_pdev_stats->cycle_count >= pdev_mc_stats->cycle_count) {
cycle_count_delta = fw_pdev_stats->cycle_count -
pdev_mc_stats->cycle_count;
} else {
/* Wrap around case */
cycle_count_delta = U32_MAX -
pdev_mc_stats->cycle_count;
cycle_count_delta += fw_pdev_stats->cycle_count;
}
if (cycle_count_delta)
pdev_mc_stats->congestion = rx_clear_count_delta * 100 /
cycle_count_delta;
else
cp_stats_err("cycle_count not increased %d",
fw_pdev_stats->cycle_count);
}
pdev_mc_stats->rx_clear_count = fw_pdev_stats->rx_clear_count;
pdev_mc_stats->cycle_count = fw_pdev_stats->cycle_count;
if (pdev_mc_stats->congestion >= pdev_mc_stats->congestion_threshold) {
is_congested = true;
congestion = pdev_mc_stats->congestion;
}
wlan_cp_stats_pdev_obj_unlock(pdev_cp_stats_priv);
if (last_req.u.congestion_notif_cb && is_congested)
last_req.u.congestion_notif_cb(congestion);
out:
wlan_objmgr_pdev_release_ref(pdev, WLAN_CP_STATS_ID);
}
#else
static void
tgt_mc_cp_stats_extract_congestion_stats(struct wlan_objmgr_psoc *psoc,
struct stats_event *ev)
{
}
#endif
static void tgt_mc_cp_stats_extract_cca_stats(struct wlan_objmgr_psoc *psoc,
struct stats_event *ev)
{
@@ -996,6 +1098,9 @@ QDF_STATUS tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc *psoc,
if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_PEER_STATS_INFO_EXT))
tgt_mc_cp_stats_extract_peer_stats_info_ext(psoc, ev);
if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_CONGESTION_STATS))
tgt_mc_cp_stats_extract_congestion_stats(psoc, ev);
tgt_mc_cp_stats_extract_cca_stats(psoc, ev);
tgt_mc_cp_send_lost_link_stats(psoc, ev);

查看文件

@@ -725,6 +725,55 @@ QDF_STATUS ucfg_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev,
return QDF_STATUS_SUCCESS;
}
#ifdef WLAN_FEATURE_MEDIUM_ASSESS
QDF_STATUS
ucfg_mc_cp_stats_reset_congestion_counter(struct wlan_objmgr_vdev *vdev)
{
struct wlan_objmgr_pdev *pdev;
struct pdev_mc_cp_stats *pdev_mc_stats;
struct pdev_cp_stats *pdev_cp_stats_priv;
pdev = wlan_vdev_get_pdev(vdev);
pdev_cp_stats_priv = wlan_cp_stats_get_pdev_stats_obj(pdev);
if (!pdev_cp_stats_priv) {
cp_stats_err("pdev cp stats object is null");
return QDF_STATUS_E_NULL_VALUE;
}
wlan_cp_stats_pdev_obj_lock(pdev_cp_stats_priv);
pdev_mc_stats = pdev_cp_stats_priv->pdev_stats;
pdev_mc_stats->congestion = 0;
pdev_mc_stats->rx_clear_count = 0;
pdev_mc_stats->cycle_count = 0;
wlan_cp_stats_pdev_obj_unlock(pdev_cp_stats_priv);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
ucfg_mc_cp_stats_set_congestion_threshold(struct wlan_objmgr_vdev *vdev,
uint8_t threshold)
{
struct wlan_objmgr_pdev *pdev;
struct pdev_mc_cp_stats *pdev_mc_stats;
struct pdev_cp_stats *pdev_cp_stats_priv;
pdev = wlan_vdev_get_pdev(vdev);
pdev_cp_stats_priv = wlan_cp_stats_get_pdev_stats_obj(pdev);
if (!pdev_cp_stats_priv) {
cp_stats_err("pdev cp stats object is null");
return QDF_STATUS_E_NULL_VALUE;
}
wlan_cp_stats_pdev_obj_lock(pdev_cp_stats_priv);
pdev_mc_stats = pdev_cp_stats_priv->pdev_stats;
pdev_mc_stats->congestion_threshold = threshold;
wlan_cp_stats_pdev_obj_unlock(pdev_cp_stats_priv);
return QDF_STATUS_SUCCESS;
}
#endif
bool ucfg_mc_cp_stats_is_req_pending(struct wlan_objmgr_psoc *psoc,
enum stats_req_type type)
{