Browse Source

qcacld-3.0: Send Roam Diag event logs through netlink

Roam Diag logs are sent through the vendor event to the supplicant.

Modify the Roam Scan start and Roam Candidate log flow through
the diag event to the supplicant in order to maintain single
logging infrastructure.

Change-Id: Idd85b46f72a481aa99e243c81952010d2779afaf
CRs-Fixed: 3218639
VIJAY RAJ 2 years ago
parent
commit
8d4332bc1b

+ 306 - 2
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c

@@ -5522,8 +5522,9 @@ send_evt:
 	return status;
 }
 
-#if defined(WLAN_FEATURE_CONNECTIVITY_LOGGING) && \
-    defined(WLAN_FEATURE_ROAM_OFFLOAD)
+#if (defined(CONNECTIVITY_DIAG_EVENT) || \
+	defined(WLAN_FEATURE_CONNECTIVITY_LOGGING)) && \
+	defined(WLAN_FEATURE_ROAM_OFFLOAD)
 static
 bool wlan_is_valid_frequency(uint32_t freq, uint32_t band_capability,
 			     uint32_t band_mask)
@@ -5542,7 +5543,310 @@ bool wlan_is_valid_frequency(uint32_t freq, uint32_t band_capability,
 
 	return true;
 }
+#endif
+
+#if defined(CONNECTIVITY_DIAG_EVENT) && \
+	defined(WLAN_FEATURE_ROAM_OFFLOAD)
+
+static void populate_diag_cmn(struct wlan_connectivity_log_diag_cmn *cmn,
+			      uint8_t vdev_id, uint64_t fw_timestamp,
+			      struct qdf_mac_addr *bssid)
+{
+	cmn->vdev_id = vdev_id;
+	cmn->timestamp_us = qdf_get_time_of_the_day_us();
+	cmn->ktime_us =  qdf_ktime_to_us(qdf_ktime_get());
+	cmn->fw_timestamp = fw_timestamp * 1000;
+
+	if (!bssid)
+		return;
+
+	qdf_mem_copy(cmn->bssid, bssid->bytes, QDF_MAC_ADDR_SIZE);
+}
+
+void cm_roam_scan_info_event(struct wlan_objmgr_psoc *psoc,
+			     struct wmi_roam_scan_data *scan, uint8_t vdev_id)
+{
+	int i;
+	struct wmi_roam_candidate_info *ap = scan->ap;
+	uint32_t chan_freq[NUM_CHANNELS];
+	uint8_t count = 0, status, num_chan;
+	uint32_t band_capability = 0, band_mask = 0;
+	bool is_full_scan;
+	struct wlan_objmgr_vdev *vdev = NULL;
+
+	WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event,
+				 struct wlan_diag_roam_scan_done);
+
+	qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event));
+
+	populate_diag_cmn(&wlan_diag_event.diag_cmn, vdev_id,
+			  (uint64_t)scan->ap->timestamp, &ap->bssid);
+
+	wlan_diag_event.version = DIAG_SCAN_DONE_VERSION;
+
+	/*
+	 * scan->num_ap includes current connected AP also
+	 * so subtract 1 from the count to get total candidate APs
+	 */
+
+	if (scan->num_ap)
+		wlan_diag_event.cand_ap_count = scan->num_ap - 1;
+
+	is_full_scan = scan->type & scan->present;
+
+	if (is_full_scan) {
+		status = mlme_get_fw_scan_channels(psoc, chan_freq, &num_chan);
+		if (QDF_IS_STATUS_ERROR(status))
+			goto out;
+
+		status = wlan_mlme_get_band_capability(psoc, &band_capability);
+		if (QDF_IS_STATUS_ERROR(status))
+			goto out;
+
+		vdev =
+		wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						     WLAN_MLME_OBJMGR_ID);
+		if (!vdev)
+			goto out;
+
+		band_mask = policy_mgr_get_connected_vdev_band_mask(vdev);
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
+
+		for (i = 0; i < num_chan; i++) {
+			if (!wlan_is_valid_frequency(chan_freq[i],
+						     band_capability,
+						     band_mask))
+				continue;
+
+			wlan_diag_event.scan_freq[count] = chan_freq[i];
+			count++;
+		}
+
+		wlan_diag_event.num_scanned_freq = count;
+	} else {
+		if (scan->num_chan > MAX_ROAM_SCAN_CHAN)
+			scan->num_chan = MAX_ROAM_SCAN_CHAN;
+
+		wlan_diag_event.num_scanned_freq = scan->num_chan;
+		for (i = 0; i < scan->num_chan; i++)
+			wlan_diag_event.scan_freq[i] = scan->chan_freq[i];
+	}
+
+	wlan_diag_event.btcoex_active = scan->is_btcoex_active;
+
+out:
+	WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event,
+				    EVENT_WLAN_ROAM_SCAN_DONE);
+}
+
+void cm_roam_trigger_info_event(struct wmi_roam_trigger_info *data,
+				struct wmi_roam_scan_data *scan_data,
+				uint8_t vdev_id, bool is_full_scan)
+{
+	uint8_t i;
+
+	WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event,
+				 struct wlan_diag_roam_scan_start);
+
+	qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event));
+
+	populate_diag_cmn(&wlan_diag_event.diag_cmn, vdev_id,
+			  (uint64_t)data->timestamp, NULL);
+
+	wlan_diag_event.trigger_reason = data->trigger_reason;
+	wlan_diag_event.trigger_sub_reason = data->trigger_sub_reason;
+
+	wlan_diag_event.version = DIAG_ROAM_SCAN_START_VERSION;
+
+	/*
+	 * Get the current AP rssi & CU load from the
+	 * wmi_roam_ap_info tlv in roam scan results
+	 */
+	if (scan_data->present) {
+		for (i = 0; i < scan_data->num_ap; i++) {
+			if (i >= MAX_ROAM_CANDIDATE_AP)
+				break;
+
+			if (scan_data->ap[i].type ==
+			    WLAN_ROAM_SCAN_CURRENT_AP) {
+				wlan_diag_event.rssi =
+						(-1) * scan_data->ap[i].rssi;
+				wlan_diag_event.cu =
+						scan_data->ap[i].cu_load;
+				break;
+			}
+		}
+	}
+
+	if (data->trigger_reason == ROAM_TRIGGER_REASON_PERIODIC ||
+	    data->trigger_reason == ROAM_TRIGGER_REASON_LOW_RSSI)
+		wlan_diag_event.rssi_thresh =
+					(-1) * data->rssi_trig_data.threshold;
+
+	wlan_diag_event.is_full_scan = is_full_scan;
+
+	WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event,
+				    EVENT_WLAN_ROAM_SCAN_START);
+}
+
+#define ETP_MAX_VALUE 10000000
+
+void cm_roam_candidate_info_event(struct wmi_roam_candidate_info *ap,
+				  uint8_t cand_ap_idx)
+{
+	uint32_t etp;
+
+	WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event,
+				 struct wlan_diag_roam_candidate_info);
+
+	qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event));
+
+	populate_diag_cmn(&wlan_diag_event.diag_cmn, 0, (uint64_t)ap->timestamp,
+			  &ap->bssid);
+
+	wlan_diag_event.is_current_ap = (ap->type == 1);
+	if (wlan_diag_event.is_current_ap)
+		wlan_diag_event.subtype =
+					WLAN_CONN_DIAG_ROAM_SCORE_CUR_AP_EVENT;
+	else
+		wlan_diag_event.subtype =
+					WLAN_CONN_DIAG_ROAM_SCORE_CAND_AP_EVENT;
+
+	wlan_diag_event.version = DIAG_ROAM_CAND_VERSION;
+	wlan_diag_event.rssi = (-1) * ap->rssi;
+	wlan_diag_event.cu_load = ap->cu_load;
+	wlan_diag_event.total_score = ap->total_score;
+
+	etp = ap->etp * 1000;
+
+	if (etp > ETP_MAX_VALUE)
+		wlan_diag_event.etp = ETP_MAX_VALUE;
+	else
+		wlan_diag_event.etp = etp;
+
+	wlan_diag_event.idx = cand_ap_idx;
+	wlan_diag_event.freq = ap->freq;
+
+	WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event,
+				    EVENT_WLAN_ROAM_CAND_INFO);
+}
+
+#define WLAN_ROAM_SCAN_TYPE_PARTIAL_SCAN 0
+#define WLAN_ROAM_SCAN_TYPE_FULL_SCAN 1
+
+void cm_roam_result_info_event(struct wlan_objmgr_psoc *psoc,
+			       struct wmi_roam_trigger_info *trigger,
+			       struct wmi_roam_result *res,
+			       struct wmi_roam_scan_data *scan_data,
+			       uint8_t vdev_id)
+{
+	struct qdf_mac_addr bssid = {0};
+	uint8_t i;
+	bool ap_found_in_roam_scan = false, bmiss_skip_full_scan = false;
+	bool roam_abort = (res->fail_reason == ROAM_FAIL_REASON_SYNC ||
+			   res->fail_reason == ROAM_FAIL_REASON_DISCONNECT ||
+			   res->fail_reason == ROAM_FAIL_REASON_HOST ||
+			   res->fail_reason ==
+					ROAM_FAIL_REASON_INTERNAL_ABORT ||
+			   res->fail_reason ==
+				ROAM_FAIL_REASON_UNABLE_TO_START_ROAM_HO);
+	bool is_full_scan = (scan_data->present &&
+			scan_data->type == WLAN_ROAM_SCAN_TYPE_FULL_SCAN);
+
+	WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event,
+				 struct wlan_diag_roam_result);
+
+	qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event));
+
+	populate_diag_cmn(&wlan_diag_event.diag_cmn, vdev_id,
+			  (uint64_t)res->timestamp, NULL);
+
+	for (i = 0; i < scan_data->num_ap && scan_data->present; i++) {
+		if (i >= MAX_ROAM_CANDIDATE_AP)
+			break;
+
+		if (scan_data->ap[i].type == WLAN_ROAM_SCAN_ROAMED_AP ||
+		    scan_data->ap[i].type == WLAN_ROAM_SCAN_CANDIDATE_AP) {
+			ap_found_in_roam_scan = true;
+			break;
+		}
+	}
+
+	wlan_diag_event.version = DIAG_ROAM_RESULT_VERSION;
+	wlan_diag_event.roam_fail_reason = res->fail_reason;
+	/*
+	 * Print ROAM if:
+	 * 1. Roaming is successful to AP
+	 * 2. Atleast one candidate AP found during scan
+	 *
+	 * Print NO_ROAM only if:
+	 * 1. No candidate AP found(eventhough other APs are found in scan)
+	 */
+	wlan_diag_event.is_roam_successful = (res->status == 0) ||
+		(ap_found_in_roam_scan &&
+		 res->fail_reason != ROAM_FAIL_REASON_NO_CAND_AP_FOUND);
+
+	for (i = 0; i < scan_data->num_ap; i++) {
+		if (i >= MAX_ROAM_CANDIDATE_AP)
+			break;
+
+		if (res->status == 0 &&
+		    scan_data->ap[i].type == WLAN_ROAM_SCAN_ROAMED_AP) {
+			qdf_mem_copy(wlan_diag_event.diag_cmn.bssid,
+				     scan_data->ap[i].bssid.bytes,
+				     QDF_MAC_ADDR_SIZE);
+			break;
+		} else if (scan_data->ap[i].type ==
+			   WLAN_ROAM_SCAN_CURRENT_AP) {
+			qdf_mem_copy(wlan_diag_event.diag_cmn.bssid,
+				     scan_data->ap[i].bssid.bytes,
+				     QDF_MAC_ADDR_SIZE);
+			bssid = scan_data->ap[i].bssid;
+			break;
+		}
+	}
+
+	WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_ROAM_RESULT);
+	qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event));
+
+	if (roam_abort) {
+		populate_diag_cmn(&wlan_diag_event.diag_cmn, vdev_id,
+				  (uint64_t)res->timestamp, NULL);
+
+		wlan_diag_event.roam_fail_reason = res->fail_reason;
+
+		WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event,
+					    EVENT_WLAN_ROAM_CANCEL);
+	}
+
+	/*
+	 * When roam trigger reason is Beacon Miss, 2 roam scan
+	 * stats TLV will be received with reason as BMISS.
+	 * 1. First TLV is for partial roam scan data and
+	 * 2. Second TLV is for the full scan data when there is no candidate
+	 * found in the partial scan.
+	 * When bmiss_skip_full_scan flag is disabled, prints for 1 & 2 will be
+	 * seen.
+	 * when bmiss_skip_full_scan flag is enabled, only print for 1st TLV
+	 * will be seen.
+	 *
+	 * 1. BMISS_DISCONN event should be triggered only once for BMISS roam
+	 * trigger if roam result is failure after full scan TLV is received and
+	 * bmiss_skip_full_scan is disabled.
+	 *
+	 * 2. But if bmiss_skip_full_scan is enabled, then trigger
+	 * BMISS_DISCONN event after partial scan TLV is received
+	 */
+	wlan_mlme_get_bmiss_skip_full_scan_value(psoc, &bmiss_skip_full_scan);
+	if (trigger->trigger_reason == ROAM_TRIGGER_REASON_BMISS &&
+	    !wlan_diag_event.is_roam_successful &&
+	    ((!bmiss_skip_full_scan && is_full_scan) ||
+	     (bmiss_skip_full_scan && !is_full_scan)))
+		cm_roam_beacon_loss_disconnect_event(psoc, bssid, vdev_id);
+}
 
+#elif defined(WLAN_FEATURE_CONNECTIVITY_LOGGING) && \
+	defined(WLAN_FEATURE_ROAM_OFFLOAD)
 void cm_roam_scan_info_event(struct wlan_objmgr_psoc *psoc,
 			     struct wmi_roam_scan_data *scan, uint8_t vdev_id)
 {

+ 53 - 1
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h

@@ -29,7 +29,59 @@
 #include "qdf_str.h"
 #include "wlan_cm_roam_public_struct.h"
 
-#if defined(WLAN_FEATURE_CONNECTIVITY_LOGGING) && \
+#if defined(CONNECTIVITY_DIAG_EVENT) && \
+	defined(WLAN_FEATURE_ROAM_OFFLOAD)
+/**
+ * cm_roam_scan_info_event() - send scan info to userspace
+ * @psoc: psoc common object
+ * @scan: roam scan data
+ * @vdev_id: vdev id
+ *
+ * Return: None
+ */
+void cm_roam_scan_info_event(struct wlan_objmgr_psoc *psoc,
+			     struct wmi_roam_scan_data *scan, uint8_t vdev_id);
+
+/**
+ * cm_roam_trigger_info_event() - send trigger info to userspace
+ * @data: roam trigger data
+ * @scan_data: Roam scan data
+ * @vdev_id: vdev id
+ * @is_full_scan: is full scan or partial scan
+ *
+ * Return: None
+ */
+void cm_roam_trigger_info_event(struct wmi_roam_trigger_info *data,
+				struct wmi_roam_scan_data *scan_data,
+				uint8_t vdev_id, bool is_full_scan);
+
+/**
+ * cm_roam_candidate_info_event() - send trigger info to userspace
+ * @ap: roam candidate info
+ * @cand_ap_idx: Candidate AP index
+ *
+ * Return: void
+ */
+void cm_roam_candidate_info_event(struct wmi_roam_candidate_info *ap,
+				  uint8_t cand_ap_idx);
+
+/**
+ * cm_roam_result_info_event() - send scan results info to userspace
+ * @psoc: Pointer to PSOC object
+ * @trigger: Roam trigger data
+ * @res: roam result data
+ * @scan_data: Roam scan info
+ * @vdev_id: vdev id
+ *
+ * Return: void
+ */
+void cm_roam_result_info_event(struct wlan_objmgr_psoc *psoc,
+			       struct wmi_roam_trigger_info *trigger,
+			       struct wmi_roam_result *res,
+			       struct wmi_roam_scan_data *scan_data,
+			       uint8_t vdev_id);
+
+#elif defined(WLAN_FEATURE_CONNECTIVITY_LOGGING) && \
     defined(WLAN_FEATURE_ROAM_OFFLOAD)
 /**
  * cm_roam_scan_info_event() - send scan info to userspace