Jelajahi Sumber

qcacmn: Add target_if/wmi implementation of get_stations_stats

Add changes to support get station stats from within the cp stats
component.

Change-Id: I936ea8e18e519f257ae2d57b384a5a39f4582aed
CRs-Fixed: 2210313
Naveen Rawat 7 tahun lalu
induk
melakukan
97a913abb7

+ 153 - 1
target_if/cp_stats/src/target_if_mc_cp_stats.c

@@ -56,6 +56,10 @@ static void target_if_cp_stats_free_stats_event(struct stats_event *ev)
 	ev->peer_stats = NULL;
 	qdf_mem_free(ev->cca_stats);
 	ev->cca_stats = NULL;
+	qdf_mem_free(ev->vdev_summary_stats);
+	ev->vdev_summary_stats = NULL;
+	qdf_mem_free(ev->vdev_chain_rssi);
+	ev->vdev_chain_rssi = NULL;
 }
 
 static QDF_STATUS target_if_cp_stats_extract_pdev_stats(
@@ -159,6 +163,136 @@ static QDF_STATUS target_if_cp_stats_extract_cca_stats(
 	return QDF_STATUS_SUCCESS;
 }
 
+static QDF_STATUS target_if_cp_stats_extract_vdev_summary_stats(
+					struct wmi_unified *wmi_hdl,
+					wmi_host_stats_event *stats_param,
+					struct stats_event *ev, uint8_t *data)
+{
+	uint32_t i, j;
+	QDF_STATUS status;
+	int32_t bcn_snr, dat_snr;
+	wmi_host_vdev_stats vdev_stats;
+
+	ev->num_summary_stats = stats_param->num_vdev_stats;
+	if (!ev->num_summary_stats)
+		return QDF_STATUS_SUCCESS;
+
+	ev->vdev_summary_stats = qdf_mem_malloc(sizeof(*ev->vdev_summary_stats)
+					* ev->num_summary_stats);
+
+	if (!ev->vdev_summary_stats) {
+		cp_stats_err("malloc failed");
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	for (i = 0; i < ev->num_summary_stats; i++) {
+		status = wmi_extract_vdev_stats(wmi_hdl, data, i, &vdev_stats);
+		if (QDF_IS_STATUS_ERROR(status))
+			continue;
+
+		bcn_snr = vdev_stats.vdev_snr.bcn_snr;
+		dat_snr = vdev_stats.vdev_snr.dat_snr;
+		ev->vdev_summary_stats[i].vdev_id = vdev_stats.vdev_id;
+
+		for (j = 0; j < 4; j++) {
+			ev->vdev_summary_stats[i].stats.tx_frm_cnt[j]
+					= vdev_stats.tx_frm_cnt[j];
+			ev->vdev_summary_stats[i].stats.fail_cnt[j]
+					= vdev_stats.fail_cnt[j];
+			ev->vdev_summary_stats[i].stats.multiple_retry_cnt[j]
+					= vdev_stats.multiple_retry_cnt[j];
+		}
+
+		ev->vdev_summary_stats[i].stats.rx_frm_cnt =
+						vdev_stats.rx_frm_cnt;
+		ev->vdev_summary_stats[i].stats.rx_error_cnt =
+						vdev_stats.rx_err_cnt;
+		ev->vdev_summary_stats[i].stats.rx_discard_cnt =
+						vdev_stats.rx_discard_cnt;
+		ev->vdev_summary_stats[i].stats.ack_fail_cnt =
+						vdev_stats.ack_fail_cnt;
+		ev->vdev_summary_stats[i].stats.rts_succ_cnt =
+						vdev_stats.rts_succ_cnt;
+		ev->vdev_summary_stats[i].stats.rts_fail_cnt =
+						vdev_stats.rts_fail_cnt;
+		/* Update SNR and RSSI in SummaryStats */
+		if (TGT_IS_VALID_SNR(bcn_snr)) {
+			ev->vdev_summary_stats[i].stats.snr = bcn_snr;
+			ev->vdev_summary_stats[i].stats.rssi =
+						bcn_snr + TGT_NOISE_FLOOR_DBM;
+		} else if (TGT_IS_VALID_SNR(dat_snr)) {
+			ev->vdev_summary_stats[i].stats.snr = dat_snr;
+			ev->vdev_summary_stats[i].stats.rssi =
+						dat_snr + TGT_NOISE_FLOOR_DBM;
+		} else {
+			ev->vdev_summary_stats[i].stats.snr = TGT_INVALID_SNR;
+			ev->vdev_summary_stats[i].stats.rssi = 0;
+		}
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+
+static QDF_STATUS target_if_cp_stats_extract_vdev_chain_rssi_stats(
+					struct wmi_unified *wmi_hdl,
+					wmi_host_stats_event *stats_param,
+					struct stats_event *ev, uint8_t *data)
+{
+	uint32_t i;
+	QDF_STATUS status;
+	int32_t bcn_snr, dat_snr;
+	struct wmi_host_per_chain_rssi_stats rssi_stats;
+
+	ev->num_chain_rssi_stats = stats_param->num_rssi_stats;
+	if (!ev->num_chain_rssi_stats)
+		return QDF_STATUS_SUCCESS;
+
+	ev->vdev_chain_rssi = qdf_mem_malloc(sizeof(*ev->vdev_chain_rssi) *
+						ev->num_chain_rssi_stats);
+	if (!ev->vdev_chain_rssi) {
+		cp_stats_err("malloc failed");
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	for (i = 0; i < ev->num_chain_rssi_stats; i++) {
+		status = wmi_extract_per_chain_rssi_stats(wmi_hdl, data, i,
+							  &rssi_stats);
+		if (QDF_IS_STATUS_ERROR(status))
+			continue;
+
+		for (i = 0; i < MAX_NUM_CHAINS; i++) {
+			dat_snr = rssi_stats.rssi_avg_data[i];
+			bcn_snr = rssi_stats.rssi_avg_beacon[i];
+			cp_stats_err("Chain %d SNR bcn: %d data: %d", i,
+				     bcn_snr, dat_snr);
+			if (TGT_IS_VALID_SNR(bcn_snr))
+				ev->vdev_chain_rssi[i].chain_rssi[i] = bcn_snr;
+			else if (TGT_IS_VALID_SNR(dat_snr))
+				ev->vdev_chain_rssi[i].chain_rssi[i] = dat_snr;
+			else
+				/*
+				 * Firmware sends invalid snr till it sees
+				 * Beacon/Data after connection since after
+				 * vdev up fw resets the snr to invalid. In this
+				 * duartion Host will return an invalid rssi
+				 * value.
+				 */
+				ev->vdev_chain_rssi[i].chain_rssi[i] =
+							TGT_INVALID_SNR;
+			/*
+			 * Get the absolute rssi value from the current rssi
+			 * value the snr value is hardcoded into 0 in the
+			 * qcacld-new/CORE stack
+			 */
+			ev->vdev_chain_rssi[i].chain_rssi[i] +=
+							TGT_NOISE_FLOOR_DBM;
+		}
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
 static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl,
 						   struct stats_event *ev,
 						   uint8_t *data)
@@ -168,7 +302,7 @@ static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl,
 
 	status = wmi_extract_stats_param(wmi_hdl, data, &stats_param);
 	if (QDF_IS_STATUS_ERROR(status)) {
-		cp_stats_debug("stats param extract failed: %d", status);
+		cp_stats_err("stats param extract failed: %d", status);
 		return status;
 	}
 	cp_stats_debug("num: pdev: %d, vdev: %d, peer: %d, rssi: %d",
@@ -190,6 +324,18 @@ static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl,
 	if (QDF_IS_STATUS_ERROR(status))
 		return status;
 
+	status = target_if_cp_stats_extract_vdev_summary_stats(wmi_hdl,
+							       &stats_param,
+							       ev, data);
+	if (QDF_IS_STATUS_ERROR(status))
+		return status;
+
+	status = target_if_cp_stats_extract_vdev_chain_rssi_stats(wmi_hdl,
+								  &stats_param,
+								  ev, data);
+	if (QDF_IS_STATUS_ERROR(status))
+		return status;
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -373,6 +519,12 @@ static uint32_t get_stats_id(enum stats_req_type type)
 		return WMI_REQUEST_PDEV_STAT;
 	case TYPE_PEER_STATS:
 		return WMI_REQUEST_PEER_STAT;
+	case TYPE_STATION_STATS:
+		return (WMI_REQUEST_AP_STAT   |
+			WMI_REQUEST_PEER_STAT |
+			WMI_REQUEST_VDEV_STAT |
+			WMI_REQUEST_PDEV_STAT |
+			WMI_REQUEST_RSSI_PER_CHAIN_STAT);
 	}
 	return 0;
 }

+ 3 - 0
wmi/inc/wmi_unified_api.h

@@ -1705,6 +1705,9 @@ QDF_STATUS wmi_extract_atf_token_info_ev(void *wmi_hdl, void *evt_buf,
 QDF_STATUS wmi_extract_vdev_stats(void *wmi_hdl, void *evt_buf,
 		uint32_t index, wmi_host_vdev_stats *vdev_stats);
 
+QDF_STATUS wmi_extract_per_chain_rssi_stats(void *wmi_hdl, void *evt_buf,
+	uint32_t index, struct wmi_host_per_chain_rssi_stats *rssi_stats);
+
 QDF_STATUS wmi_extract_vdev_extd_stats(void *wmi_hdl, void *evt_buf,
 		uint32_t index, wmi_host_vdev_extd_stats *vdev_extd_stats);
 

+ 21 - 0
wmi/inc/wmi_unified_param.h

@@ -5162,6 +5162,12 @@ typedef struct {
  *	*/
 #define WMI_HOST_WLAN_MAX_AC  4
 
+/* The WMI_HOST_MAX_CHAINS macro cannot be changed without breaking WMI
+ * compatibility.
+ * The maximum value of number of chains
+ */
+#define WMI_HOST_MAX_CHAINS   8
+
 /**
  * struct wmi_host_vdev_stats - vdev stats structure
  * @vdev_id: unique id identifying the VDEV, generated by the caller
@@ -5263,6 +5269,21 @@ struct wmi_host_vdev_nac_rssi_event {
 	uint32_t rssi_seq_num;
 };
 
+
+/**
+ * struct wmi_host_per_chain_rssi_stats - VDEV nac rssi stats
+ * @vdev_id: unique id identifying the VDEV, generated by the caller
+ * @rssi_avg_beacon: per chain avg rssi for beacon
+ * @rssi_avg_data: per chain avg rssi for data
+ * @peer_macaddr: peer macaddr
+ */
+struct wmi_host_per_chain_rssi_stats {
+	uint32_t vdev_id;
+	int32_t rssi_avg_beacon[WMI_HOST_MAX_CHAINS];
+	int32_t rssi_avg_data[WMI_HOST_MAX_CHAINS];
+	wmi_host_mac_addr peer_macaddr;
+};
+
 /**
  * struct wmi_host_peer_stats - peer stats
  * @peer_macaddr: peer MAC address

+ 4 - 0
wmi/inc/wmi_unified_priv.h

@@ -1290,6 +1290,10 @@ QDF_STATUS (*extract_pdev_ext_stats)(wmi_unified_t wmi_handle, void *evt_buf,
 QDF_STATUS (*extract_vdev_stats)(wmi_unified_t wmi_handle, void *evt_buf,
 			 uint32_t index, wmi_host_vdev_stats *vdev_stats);
 
+QDF_STATUS (*extract_per_chain_rssi_stats)(wmi_unified_t wmi_handle,
+			void *evt_buf, uint32_t index,
+			struct wmi_host_per_chain_rssi_stats *rssi_stats);
+
 QDF_STATUS (*extract_peer_stats)(wmi_unified_t wmi_handle, void *evt_buf,
 			 uint32_t index, wmi_host_peer_stats *peer_stats);
 

+ 21 - 0
wmi/src/wmi_unified_api.c

@@ -6210,6 +6210,27 @@ QDF_STATUS wmi_extract_vdev_stats(void *wmi_hdl, void *evt_buf,
 	return QDF_STATUS_E_FAILURE;
 }
 
+/**
+ * wmi_extract_per_chain_rssi_stats() - extract rssi stats from event
+ * @wmi_handle: wmi handle
+ * @param evt_buf: pointer to event buffer
+ * @param index: Index into rssi stats
+ * @param rssi_stats: Pointer to hold rssi stats
+ *
+ * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
+ */
+QDF_STATUS wmi_extract_per_chain_rssi_stats(void *wmi_hdl, void *evt_buf,
+	uint32_t index, struct wmi_host_per_chain_rssi_stats *rssi_stats)
+{
+	wmi_unified_t wmi_handle = (wmi_unified_t) wmi_hdl;
+
+	if (wmi_handle->ops->extract_per_chain_rssi_stats)
+		return wmi_handle->ops->extract_per_chain_rssi_stats(wmi_handle,
+			evt_buf, index, rssi_stats);
+
+	return QDF_STATUS_E_FAILURE;
+}
+
 /**
  * wmi_extract_rtt_hdr() - extract rtt header from event
  * @wmi_handle: wmi handle

+ 52 - 0
wmi/src/wmi_unified_tlv.c

@@ -19516,6 +19516,57 @@ static QDF_STATUS extract_vdev_stats_tlv(wmi_unified_t wmi_handle,
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * extract_per_chain_rssi_stats_tlv() - api to extract rssi stats from event
+ * buffer
+ * @wmi_handle: wmi handle
+ * @evt_buf: pointer to event buffer
+ * @index: Index into vdev stats
+ * @rssi_stats: Pointer to hold rssi stats
+ *
+ * Return: QDF_STATUS_SUCCESS for success or error code
+ */
+static QDF_STATUS extract_per_chain_rssi_stats_tlv(wmi_unified_t wmi_handle,
+			void *evt_buf, uint32_t index,
+			struct wmi_host_per_chain_rssi_stats *rssi_stats)
+{
+	uint8_t *data;
+	wmi_rssi_stats *fw_rssi_stats;
+	wmi_per_chain_rssi_stats *rssi_event;
+	WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
+
+	if (!evt_buf) {
+		WMI_LOGE("evt_buf is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf;
+	rssi_event = param_buf->chain_stats;
+
+	if (index >= rssi_event->num_per_chain_rssi_stats) {
+		WMI_LOGE("invalid index");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	data = ((uint8_t *)(&rssi_event[1])) + WMI_TLV_HDR_SIZE;
+	fw_rssi_stats = &((wmi_rssi_stats *)data)[index];
+
+	rssi_stats->vdev_id = fw_rssi_stats->vdev_id;
+	qdf_mem_copy(rssi_stats->rssi_avg_beacon,
+		     fw_rssi_stats->rssi_avg_beacon,
+		     sizeof(fw_rssi_stats->rssi_avg_beacon));
+	qdf_mem_copy(rssi_stats->rssi_avg_data,
+		     fw_rssi_stats->rssi_avg_data,
+		     sizeof(fw_rssi_stats->rssi_avg_data));
+	qdf_mem_copy(&rssi_stats->peer_macaddr,
+		     &fw_rssi_stats->peer_macaddr,
+		     sizeof(fw_rssi_stats->peer_macaddr));
+
+	return QDF_STATUS_SUCCESS;
+}
+
+
+
 /**
  * extract_bcn_stats_tlv() - extract bcn stats from event
  * @wmi_handle: wmi handle
@@ -22805,6 +22856,7 @@ struct wmi_ops tlv_ops =  {
 	.extract_unit_test = extract_unit_test_tlv,
 	.extract_pdev_ext_stats = extract_pdev_ext_stats_tlv,
 	.extract_vdev_stats = extract_vdev_stats_tlv,
+	.extract_per_chain_rssi_stats = extract_per_chain_rssi_stats_tlv,
 	.extract_peer_stats = extract_peer_stats_tlv,
 	.extract_bcn_stats = extract_bcn_stats_tlv,
 	.extract_bcnflt_stats = extract_bcnflt_stats_tlv,