|
@@ -107,8 +107,220 @@ static void tgt_mc_cp_stats_extract_tx_power(struct wlan_objmgr_psoc *psoc,
|
|
|
end:
|
|
|
if (vdev)
|
|
|
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,
|
|
@@ -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))
|
|
|
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;
|
|
|
}
|
|
@@ -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;
|
|
|
|
|
|
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");
|
|
|
return QDF_STATUS_E_NULL_VALUE;
|
|
|
}
|