qcacld-3.0: API to report congestion
API to report congestion to userspace. Change-Id: I324ae6701dace590daaa2c3f80412d6633cbf8f0 CRs-Fixed: 2766432
此提交包含在:
@@ -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)
|
||||
{
|
||||
|
新增問題並參考
封鎖使用者