qcacmn: Add umac implementation of getting peer rssi
Add changes to support get peer rssi from within cp_stats component. Change-Id: I68c9c7e23dd14b515a71080b1b5fe3af15651ef9 CRs-Fixed: 2222777
This commit is contained in:
@@ -105,6 +105,18 @@ typedef __qdf_wait_queue_head_t qdf_wait_queue_head_t;
|
|||||||
*/
|
*/
|
||||||
#define QDF_MIN(_x, _y) (((_x) < (_y)) ? (_x) : (_y))
|
#define QDF_MIN(_x, _y) (((_x) < (_y)) ? (_x) : (_y))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QDF_IS_ADDR_BROADCAST - is mac address broadcast mac address
|
||||||
|
* @_a: pointer to mac address
|
||||||
|
*/
|
||||||
|
#define QDF_IS_ADDR_BROADCAST(_a) \
|
||||||
|
((_a)[0] == 0xff && \
|
||||||
|
(_a)[1] == 0xff && \
|
||||||
|
(_a)[2] == 0xff && \
|
||||||
|
(_a)[3] == 0xff && \
|
||||||
|
(_a)[4] == 0xff && \
|
||||||
|
(_a)[5] == 0xff)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qdf_status_to_os_return - returns the status to OS.
|
* qdf_status_to_os_return - returns the status to OS.
|
||||||
* @status: enum QDF_STATUS
|
* @status: enum QDF_STATUS
|
||||||
|
@@ -41,14 +41,16 @@
|
|||||||
#include "qdf_event.h"
|
#include "qdf_event.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum stats_req_type: enum indicating bit position of various stats type in
|
* enum stats_req_type - enum indicating bit position of various stats type in
|
||||||
* request map
|
* request map
|
||||||
* @TYPE_CONNECTION_TX_POWER: tx power was requested
|
* @TYPE_CONNECTION_TX_POWER: tx power was requested
|
||||||
* @TYPE_STATION_STATS: station stats was requested
|
* @TYPE_STATION_STATS: station stats was requested
|
||||||
|
* @TYPE_PEER_STATS: peer stats was requested
|
||||||
*/
|
*/
|
||||||
enum stats_req_type {
|
enum stats_req_type {
|
||||||
TYPE_CONNECTION_TX_POWER = 0,
|
TYPE_CONNECTION_TX_POWER = 0,
|
||||||
TYPE_STATION_STATS,
|
TYPE_STATION_STATS,
|
||||||
|
TYPE_PEER_STATS,
|
||||||
TYPE_MAX,
|
TYPE_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -92,6 +94,8 @@ struct wake_lock_stats {
|
|||||||
uint32_t scan_11d;
|
uint32_t scan_11d;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct stats_event;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct request_info: details of each request
|
* struct request_info: details of each request
|
||||||
* @cookie: identifier for os_if request
|
* @cookie: identifier for os_if request
|
||||||
@@ -104,6 +108,7 @@ struct request_info {
|
|||||||
void *cookie;
|
void *cookie;
|
||||||
union {
|
union {
|
||||||
void (*get_tx_power_cb)(int tx_power, void *cookie);
|
void (*get_tx_power_cb)(int tx_power, void *cookie);
|
||||||
|
void (*get_peer_rssi_cb)(struct stats_event *ev, void *cookie);
|
||||||
} u;
|
} u;
|
||||||
uint32_t vdev_id;
|
uint32_t vdev_id;
|
||||||
uint32_t pdev_id;
|
uint32_t pdev_id;
|
||||||
@@ -146,14 +151,32 @@ struct vdev_mc_cp_stats {
|
|||||||
struct wake_lock_stats wow_stats;
|
struct wake_lock_stats wow_stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct peer_mc_cp_stats - peer specific stats
|
||||||
|
* @tx_rate: tx rate
|
||||||
|
* @rx_rate: rx rate
|
||||||
|
* @peer_rssi: rssi
|
||||||
|
* @peer_macaddr: mac address
|
||||||
|
*/
|
||||||
|
struct peer_mc_cp_stats {
|
||||||
|
uint32_t tx_rate;
|
||||||
|
uint32_t rx_rate;
|
||||||
|
uint32_t peer_rssi;
|
||||||
|
uint8_t peer_macaddr[WLAN_MACADDR_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct stats_event - parameters populated by stats event
|
* struct stats_event - parameters populated by stats event
|
||||||
* @num_pdev_stats: number of pdev stats
|
* @num_pdev_stats: num pdev stats
|
||||||
* @pdev_stats: array of per pdev stats (index = pdev_id)
|
* @pdev_stats: if populated array indicating pdev stats (index = pdev_id)
|
||||||
|
* @num_peer_stats: num peer stats
|
||||||
|
* @peer_stats: if populated array indicating peer stats
|
||||||
*/
|
*/
|
||||||
struct stats_event {
|
struct stats_event {
|
||||||
uint32_t num_pdev_stats;
|
uint32_t num_pdev_stats;
|
||||||
struct pdev_mc_cp_stats *pdev_stats;
|
struct pdev_mc_cp_stats *pdev_stats;
|
||||||
|
uint32_t num_peer_stats;
|
||||||
|
struct peer_mc_cp_stats *peer_stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CONFIG_MCL */
|
#endif /* CONFIG_MCL */
|
||||||
|
@@ -177,4 +177,4 @@ QDF_STATUS ucfg_mc_cp_stats_get_pending_req(struct wlan_objmgr_psoc *psoc,
|
|||||||
struct request_info *info);
|
struct request_info *info);
|
||||||
|
|
||||||
#endif /* QCA_SUPPORT_CP_STATS */
|
#endif /* QCA_SUPPORT_CP_STATS */
|
||||||
#endif /* __WLAN_CP_STATS_UCFG_API_H__ */
|
#endif /* __WLAN_CP_STATS_MC_UCFG_API_H__ */
|
||||||
|
@@ -107,8 +107,220 @@ static void tgt_mc_cp_stats_extract_tx_power(struct wlan_objmgr_psoc *psoc,
|
|||||||
end:
|
end:
|
||||||
if (vdev)
|
if (vdev)
|
||||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
|
wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
|
||||||
qdf_mem_free(ev->pdev_stats);
|
}
|
||||||
ev->pdev_stats = NULL;
|
|
||||||
|
static void peer_rssi_iterator(struct wlan_objmgr_pdev *pdev,
|
||||||
|
void *peer, void *arg)
|
||||||
|
{
|
||||||
|
struct stats_event *ev;
|
||||||
|
struct peer_mc_cp_stats *peer_mc_stats;
|
||||||
|
struct peer_cp_stats *peer_cp_stats_priv;
|
||||||
|
|
||||||
|
if (WLAN_PEER_SELF == wlan_peer_get_peer_type(peer)) {
|
||||||
|
cp_stats_err("ignore self peer: %pM",
|
||||||
|
wlan_peer_get_macaddr(peer));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
|
||||||
|
if (!peer_cp_stats_priv) {
|
||||||
|
cp_stats_err("peer cp stats object is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
|
||||||
|
peer_mc_stats = peer_cp_stats_priv->peer_stats;
|
||||||
|
ev = arg;
|
||||||
|
ev->peer_stats[ev->num_peer_stats] = *peer_mc_stats;
|
||||||
|
ev->num_peer_stats++;
|
||||||
|
wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tgt_mc_cp_stats_prepare_raw_peer_rssi(struct wlan_objmgr_psoc *psoc,
|
||||||
|
struct request_info *last_req)
|
||||||
|
{
|
||||||
|
uint8_t *mac_addr;
|
||||||
|
uint16_t peer_count;
|
||||||
|
struct stats_event ev = {0};
|
||||||
|
struct wlan_objmgr_pdev *pdev;
|
||||||
|
struct wlan_objmgr_vdev *vdev;
|
||||||
|
struct wlan_objmgr_peer *peer = NULL;
|
||||||
|
struct peer_mc_cp_stats *peer_mc_stats;
|
||||||
|
struct peer_cp_stats *peer_cp_stats_priv;
|
||||||
|
void (*get_peer_rssi_cb)(struct stats_event *ev, void *cookie);
|
||||||
|
|
||||||
|
get_peer_rssi_cb = last_req->u.get_peer_rssi_cb;
|
||||||
|
if (!get_peer_rssi_cb) {
|
||||||
|
cp_stats_err("get_peer_rssi_cb is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
mac_addr = last_req->peer_mac_addr;
|
||||||
|
if (QDF_IS_ADDR_BROADCAST(mac_addr)) {
|
||||||
|
pdev = wlan_vdev_get_pdev(vdev);
|
||||||
|
peer_count = wlan_pdev_get_peer_count(pdev);
|
||||||
|
ev.peer_stats = qdf_mem_malloc(sizeof(*ev.peer_stats) *
|
||||||
|
peer_count);
|
||||||
|
if (!ev.peer_stats) {
|
||||||
|
cp_stats_err("malloc failed");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_PEER_OP,
|
||||||
|
peer_rssi_iterator, &ev,
|
||||||
|
true, WLAN_CP_STATS_ID);
|
||||||
|
} else {
|
||||||
|
peer = wlan_objmgr_get_peer(psoc, mac_addr, WLAN_CP_STATS_ID);
|
||||||
|
if (!peer) {
|
||||||
|
cp_stats_err("peer[%pM] is null", mac_addr);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
|
||||||
|
if (!peer_cp_stats_priv) {
|
||||||
|
cp_stats_err("peer cp stats object is null");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ev.peer_stats = qdf_mem_malloc(sizeof(*ev.peer_stats));
|
||||||
|
if (!ev.peer_stats) {
|
||||||
|
cp_stats_err("malloc failed");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ev.num_peer_stats = 1;
|
||||||
|
wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
|
||||||
|
peer_mc_stats = peer_cp_stats_priv->peer_stats;
|
||||||
|
*ev.peer_stats = *peer_mc_stats;
|
||||||
|
wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
get_peer_rssi_cb(&ev, last_req->cookie);
|
||||||
|
return;
|
||||||
|
end:
|
||||||
|
if (vdev)
|
||||||
|
wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
|
||||||
|
if (peer)
|
||||||
|
wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
|
||||||
|
ucfg_mc_cp_stats_free_stats_event(&ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QDF_STATUS
|
||||||
|
tgt_mc_cp_stats_update_peer_stats(struct wlan_objmgr_psoc *psoc,
|
||||||
|
struct peer_mc_cp_stats *peer_stats)
|
||||||
|
{
|
||||||
|
uint8_t *peer_mac_addr;
|
||||||
|
struct wlan_objmgr_peer *peer;
|
||||||
|
struct peer_mc_cp_stats *peer_mc_stats;
|
||||||
|
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||||
|
struct peer_cp_stats *peer_cp_stats_priv;
|
||||||
|
|
||||||
|
if (!peer_stats)
|
||||||
|
return QDF_STATUS_E_INVAL;
|
||||||
|
|
||||||
|
peer_mac_addr = peer_stats->peer_macaddr;
|
||||||
|
peer = wlan_objmgr_get_peer(psoc, peer_mac_addr,
|
||||||
|
WLAN_CP_STATS_ID);
|
||||||
|
if (!peer) {
|
||||||
|
cp_stats_err("peer is null");
|
||||||
|
return QDF_STATUS_E_EXISTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
|
||||||
|
if (!peer_cp_stats_priv) {
|
||||||
|
cp_stats_err("peer_cp_stats_priv is null");
|
||||||
|
status = QDF_STATUS_E_EXISTS;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
|
||||||
|
peer_mc_stats = peer_cp_stats_priv->peer_stats;
|
||||||
|
qdf_mem_copy(peer_mc_stats->peer_macaddr,
|
||||||
|
peer_stats->peer_macaddr,
|
||||||
|
WLAN_MACADDR_LEN);
|
||||||
|
if (peer_stats->tx_rate)
|
||||||
|
peer_mc_stats->tx_rate = peer_stats->tx_rate;
|
||||||
|
if (peer_stats->rx_rate)
|
||||||
|
peer_mc_stats->rx_rate = peer_stats->rx_rate;
|
||||||
|
if (peer_stats->peer_rssi)
|
||||||
|
peer_mc_stats->peer_rssi = peer_stats->peer_rssi;
|
||||||
|
|
||||||
|
cp_stats_debug("peer_mac=%pM, tx_rate=%u, rx_rate=%u, peer_rssi=%u",
|
||||||
|
peer_mc_stats->peer_macaddr, peer_mc_stats->tx_rate,
|
||||||
|
peer_mc_stats->rx_rate, peer_mc_stats->peer_rssi);
|
||||||
|
wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (peer)
|
||||||
|
wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tgt_mc_cp_stats_extract_peer_stats(struct wlan_objmgr_psoc *psoc,
|
||||||
|
struct stats_event *ev,
|
||||||
|
bool is_station_stats)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
QDF_STATUS status;
|
||||||
|
struct request_info last_req = {0};
|
||||||
|
uint32_t selected;
|
||||||
|
|
||||||
|
if (!ev->peer_stats) {
|
||||||
|
cp_stats_err("no peer stats");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_station_stats)
|
||||||
|
status = ucfg_mc_cp_stats_get_pending_req(psoc,
|
||||||
|
TYPE_STATION_STATS,
|
||||||
|
&last_req);
|
||||||
|
else
|
||||||
|
status = ucfg_mc_cp_stats_get_pending_req(psoc,
|
||||||
|
TYPE_PEER_STATS,
|
||||||
|
&last_req);
|
||||||
|
|
||||||
|
if (QDF_IS_STATUS_ERROR(status)) {
|
||||||
|
cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
selected = ev->num_peer_stats;
|
||||||
|
for (i = 0; i < ev->num_peer_stats; i++) {
|
||||||
|
status = tgt_mc_cp_stats_update_peer_stats(psoc,
|
||||||
|
&ev->peer_stats[i]);
|
||||||
|
if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
|
||||||
|
!qdf_mem_cmp(ev->peer_stats[i].peer_macaddr,
|
||||||
|
last_req.peer_mac_addr,
|
||||||
|
WLAN_MACADDR_LEN)) {
|
||||||
|
/* mac is specified, but failed to update the peer */
|
||||||
|
if (QDF_IS_STATUS_ERROR(status))
|
||||||
|
return;
|
||||||
|
|
||||||
|
selected = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no matched peer */
|
||||||
|
if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
|
||||||
|
selected == ev->num_peer_stats) {
|
||||||
|
cp_stats_err("peer not found stats");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_station_stats)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tgt_mc_cp_stats_prepare_raw_peer_rssi(psoc, &last_req);
|
||||||
|
ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_PEER_STATS);
|
||||||
}
|
}
|
||||||
|
|
||||||
QDF_STATUS tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc *psoc,
|
QDF_STATUS tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc *psoc,
|
||||||
@@ -117,6 +329,8 @@ QDF_STATUS tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc *psoc,
|
|||||||
if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_CONNECTION_TX_POWER))
|
if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_CONNECTION_TX_POWER))
|
||||||
tgt_mc_cp_stats_extract_tx_power(psoc, ev, false);
|
tgt_mc_cp_stats_extract_tx_power(psoc, ev, false);
|
||||||
|
|
||||||
|
if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_PEER_STATS))
|
||||||
|
tgt_mc_cp_stats_extract_peer_stats(psoc, ev, false);
|
||||||
|
|
||||||
return QDF_STATUS_SUCCESS;
|
return QDF_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -144,7 +358,7 @@ QDF_STATUS tgt_send_mc_cp_stats_req(struct wlan_objmgr_psoc *psoc,
|
|||||||
struct wlan_lmac_if_cp_stats_tx_ops *tx_ops;
|
struct wlan_lmac_if_cp_stats_tx_ops *tx_ops;
|
||||||
|
|
||||||
tx_ops = target_if_cp_stats_get_tx_ops(psoc);
|
tx_ops = target_if_cp_stats_get_tx_ops(psoc);
|
||||||
if (!tx_ops) {
|
if (!tx_ops || !tx_ops->send_req_stats) {
|
||||||
cp_stats_err("could not get tx_ops");
|
cp_stats_err("could not get tx_ops");
|
||||||
return QDF_STATUS_E_NULL_VALUE;
|
return QDF_STATUS_E_NULL_VALUE;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user