Browse Source

qcacmn: Add support to log latest CE descriptor history

Add support to log latest CE descriptor history which helps
to identify CE scheduling/reaping delays when full debug
history dump is not available.

Change-Id: I44a5c86a3e1dd4861bfd2e77b3f772d5d53bcedf
CRs-Fixed: 3225155
Karthik Kantamneni 3 years ago
parent
commit
50c8489faf
5 changed files with 119 additions and 1 deletions
  1. 9 0
      hif/inc/hif.h
  2. 65 1
      hif/src/ce/ce_service.c
  3. 2 0
      hif/src/ce/ce_service_legacy.c
  4. 23 0
      hif/src/ce/ce_service_srng.c
  5. 20 0
      hif/src/hif_main.h

+ 9 - 0
hif/inc/hif.h

@@ -633,6 +633,15 @@ static inline void hif_event_history_deinit(struct hif_opaque_softc *hif_ctx,
 }
 }
 #endif /* WLAN_FEATURE_DP_EVENT_HISTORY */
 #endif /* WLAN_FEATURE_DP_EVENT_HISTORY */
 
 
+void hif_display_ctrl_traffic_pipes_state(struct hif_opaque_softc *hif_ctx);
+
+#if defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF)
+void hif_display_latest_desc_hist(struct hif_opaque_softc *hif_ctx);
+#else
+static
+inline void hif_display_latest_desc_hist(struct hif_opaque_softc *hif_ctx) {}
+#endif
+
 /**
 /**
  * enum HIF_DEVICE_POWER_CHANGE_TYPE: Device Power change type
  * enum HIF_DEVICE_POWER_CHANGE_TYPE: Device Power change type
  *
  *

+ 65 - 1
hif/src/ce/ce_service.c

@@ -1,6 +1,6 @@
 /*
 /*
  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * any purpose with or without fee is hereby granted, provided that the
@@ -168,6 +168,68 @@ void hif_ce_desc_record_rx_paddr(struct hif_softc *scn,
 }
 }
 #endif /* HIF_RECORD_RX_PADDR */
 #endif /* HIF_RECORD_RX_PADDR */
 
 
+void hif_display_latest_desc_hist(struct hif_opaque_softc *hif_ctx)
+{
+	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
+	struct ce_desc_hist *ce_hist;
+	struct latest_evt_history *evt;
+	int i;
+
+	if (!scn)
+		return;
+
+	ce_hist = &scn->hif_ce_desc_hist;
+
+	for (i = 0; i < HIF_CE_MAX_LATEST_HIST; i++) {
+		if (!ce_hist->enable[i + HIF_CE_MAX_LATEST_HIST])
+			continue;
+
+		evt = &ce_hist->latest_evt[i];
+		hif_info_high("CE_id:%d cpu_id:%d irq_entry:0x%llx tasklet_entry:0x%llx tasklet_resched:0x%llx tasklet_exit:0x%llx ce_work:0x%llx hp:%x tp:%x",
+			      (i + HIF_CE_MAX_LATEST_HIST), evt->cpu_id,
+			      evt->irq_entry_ts, evt->bh_entry_ts,
+			      evt->bh_resched_ts, evt->bh_exit_ts,
+			      evt->bh_work_ts, evt->ring_hp, evt->ring_tp);
+	}
+}
+
+void hif_record_latest_evt(struct ce_desc_hist *ce_hist,
+			   uint8_t type,
+			   int ce_id, uint64_t time,
+			   uint32_t hp, uint32_t tp)
+{
+	struct latest_evt_history *latest_evt;
+
+	if (ce_id != 2 && ce_id != 3)
+		return;
+
+	latest_evt = &ce_hist->latest_evt[ce_id - HIF_CE_MAX_LATEST_HIST];
+
+	switch (type) {
+	case HIF_IRQ_EVENT:
+		latest_evt->irq_entry_ts = time;
+		latest_evt->cpu_id = qdf_get_cpu();
+		break;
+	case HIF_CE_TASKLET_ENTRY:
+		latest_evt->bh_entry_ts = time;
+		break;
+	case HIF_CE_TASKLET_RESCHEDULE:
+		latest_evt->bh_resched_ts = time;
+		break;
+	case HIF_CE_TASKLET_EXIT:
+		latest_evt->bh_exit_ts = time;
+		break;
+	case HIF_TX_DESC_COMPLETION:
+	case HIF_CE_DEST_STATUS_RING_REAP:
+		latest_evt->bh_work_ts = time;
+		latest_evt->ring_hp = hp;
+		latest_evt->ring_tp = tp;
+		break;
+	default:
+		break;
+	}
+}
+
 /**
 /**
  * hif_record_ce_desc_event() - record ce descriptor events
  * hif_record_ce_desc_event() - record ce descriptor events
  * @scn: hif_softc
  * @scn: hif_softc
@@ -227,6 +289,8 @@ void hif_record_ce_desc_event(struct hif_softc *scn, int ce_id,
 
 
 	if (ce_hist->data_enable[ce_id])
 	if (ce_hist->data_enable[ce_id])
 		hif_ce_desc_data_record(event, len);
 		hif_ce_desc_data_record(event, len);
+
+	hif_record_latest_evt(ce_hist, type, ce_id, event->time, 0, 0);
 }
 }
 qdf_export_symbol(hif_record_ce_desc_event);
 qdf_export_symbol(hif_record_ce_desc_event);
 
 

+ 2 - 0
hif/src/ce/ce_service_legacy.c

@@ -1264,6 +1264,8 @@ static bool ce_check_int_watermark(struct CE_state *CE_state,
 	return false;
 	return false;
 }
 }
 
 
+void hif_display_ctrl_traffic_pipes_state(struct hif_opaque_softc *hif_ctx) { }
+
 #ifdef HIF_CE_LOG_INFO
 #ifdef HIF_CE_LOG_INFO
 /**
 /**
  * ce_get_index_info_legacy(): Get CE index info
  * ce_get_index_info_legacy(): Get CE index info

+ 23 - 0
hif/src/ce/ce_service_srng.c

@@ -78,6 +78,26 @@
 			(uint32_t)(((dma_addr) >> 32) & 0xFF);\
 			(uint32_t)(((dma_addr) >> 32) & 0xFF);\
 	} while (0)
 	} while (0)
 
 
+void hif_display_ctrl_traffic_pipes_state(struct hif_opaque_softc *hif_ctx)
+{
+	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
+	struct CE_state *CE_state;
+	uint32_t hp = 0, tp = 0;
+
+	CE_state = scn->ce_id_to_state[2];
+	hal_get_sw_hptp(scn->hal_soc,
+			CE_state->status_ring->srng_ctx,
+			&tp, &hp);
+	hif_info_high("CE-2 Dest status ring current snapshot HP:%u TP:%u",
+		      hp, tp);
+
+	hp = 0;
+	tp = 0;
+	CE_state = scn->ce_id_to_state[3];
+	hal_get_sw_hptp(scn->hal_soc, CE_state->src_ring->srng_ctx, &tp, &hp);
+	hif_info_high("CE-3 Source ring current snapshot HP:%u TP:%u", hp, tp);
+}
+
 #if defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF)
 #if defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF)
 void hif_record_ce_srng_desc_event(struct hif_softc *scn, int ce_id,
 void hif_record_ce_srng_desc_event(struct hif_softc *scn, int ce_id,
 				   enum hif_ce_event_type type,
 				   enum hif_ce_event_type type,
@@ -131,6 +151,9 @@ void hif_record_ce_srng_desc_event(struct hif_softc *scn, int ce_id,
 
 
 	if (ce_hist->data_enable[ce_id])
 	if (ce_hist->data_enable[ce_id])
 		hif_ce_desc_data_record(event, len);
 		hif_ce_desc_data_record(event, len);
+
+	hif_record_latest_evt(ce_hist, type, ce_id, event->time,
+			      event->current_hp, event->current_tp);
 }
 }
 #endif /* HIF_CONFIG_SLUB_DEBUG_ON || HIF_CE_DEBUG_DATA_BUF */
 #endif /* HIF_CONFIG_SLUB_DEBUG_ON || HIF_CE_DEBUG_DATA_BUF */
 
 

+ 20 - 0
hif/src/hif_main.h

@@ -182,6 +182,20 @@ struct hif_latency_detect {
  * for defined here
  * for defined here
  */
  */
 #if defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF)
 #if defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF)
+
+#define HIF_CE_MAX_LATEST_HIST 2
+
+struct latest_evt_history {
+	uint64_t irq_entry_ts;
+	uint64_t bh_entry_ts;
+	uint64_t bh_resched_ts;
+	uint64_t bh_exit_ts;
+	uint64_t bh_work_ts;
+	int cpu_id;
+	uint32_t ring_hp;
+	uint32_t ring_tp;
+};
+
 struct ce_desc_hist {
 struct ce_desc_hist {
 	qdf_atomic_t history_index[CE_COUNT_MAX];
 	qdf_atomic_t history_index[CE_COUNT_MAX];
 	uint8_t ce_id_hist_map[CE_COUNT_MAX];
 	uint8_t ce_id_hist_map[CE_COUNT_MAX];
@@ -191,7 +205,13 @@ struct ce_desc_hist {
 	uint32_t hist_index;
 	uint32_t hist_index;
 	uint32_t hist_id;
 	uint32_t hist_id;
 	void *hist_ev[CE_COUNT_MAX];
 	void *hist_ev[CE_COUNT_MAX];
+	struct latest_evt_history latest_evt[HIF_CE_MAX_LATEST_HIST];
 };
 };
+
+void hif_record_latest_evt(struct ce_desc_hist *ce_hist,
+			   uint8_t type,
+			   int ce_id, uint64_t time,
+			   uint32_t hp, uint32_t tp);
 #endif /*defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF)*/
 #endif /*defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF)*/
 
 
 /**
 /**