Răsfoiți Sursa

qcacmn: Schedule CE tasklet when resource runs out

If there is no resourse to send packet via HTC, then check if interrupts
are not processed from that CE for last 3 seconds. If so, schedule a
tasklet to reap available entries. Also if Queue has reached 1024 entries
within 3 seconds, then also schedule tasklet.

This change is added because there is a case where intermittently
completion interrupts are not received from CE3 and hence adding
this WAR in host to come out of this issue scenario.

Change-Id: I126cd5e678517127659237308f8f6b1313f8f422
CRs-Fixed: 3234943
Nandha Kishore Easwaran 3 ani în urmă
părinte
comite
93bf7e1fb1
5 a modificat fișierele cu 68 adăugiri și 1 ștergeri
  1. 1 0
      hif/inc/hif.h
  2. 33 0
      hif/src/ce/ce_main.c
  3. 6 0
      hif/src/ce/ce_main.h
  4. 24 0
      hif/src/ce/ce_tasklet.c
  5. 4 1
      htc/htc_send.c

+ 1 - 0
hif/inc/hif.h

@@ -1013,6 +1013,7 @@ QDF_STATUS hif_send_head(struct hif_opaque_softc *hif_ctx, uint8_t PipeID,
 				  qdf_nbuf_t wbuf, uint32_t data_attr);
 void hif_send_complete_check(struct hif_opaque_softc *hif_ctx, uint8_t PipeID,
 			     int force);
+void hif_schedule_ce_tasklet(struct hif_opaque_softc *hif_ctx, uint8_t PipeID);
 void hif_shut_down_device(struct hif_opaque_softc *hif_ctx);
 void hif_get_default_pipe(struct hif_opaque_softc *hif_ctx, uint8_t *ULPipe,
 			  uint8_t *DLPipe);

+ 33 - 0
hif/src/ce/ce_main.c

@@ -2855,6 +2855,39 @@ void hif_send_complete_check(struct hif_opaque_softc *hif_ctx, uint8_t pipe,
 #endif
 }
 
+#if defined(CE_TASKLET_SCHEDULE_ON_FULL) && defined(CE_TASKLET_DEBUG_ENABLE)
+#define CE_RING_FULL_THRESHOLD_TIME 3000000
+#define CE_RING_FULL_THRESHOLD 1024
+/* Ths function is called from htc_send path. If there is no resourse to send
+ * packet via HTC, then check if interrupts are not processed from that
+ * CE for last 3 seconds. If so, schedule a tasklet to reap available entries.
+ * Also if Queue has reached 1024 entries within 3 seconds, then also schedule
+ * tasklet.
+ */
+void hif_schedule_ce_tasklet(struct hif_opaque_softc *hif_ctx, uint8_t pipe)
+{
+	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_ctx);
+	uint64_t diff_time = qdf_get_log_timestamp_usecs() -
+			hif_state->stats.tasklet_sched_entry_ts[pipe];
+
+	hif_state->stats.ce_ring_full_count[pipe]++;
+
+	if (diff_time >= CE_RING_FULL_THRESHOLD_TIME ||
+	    hif_state->stats.ce_ring_full_count[pipe] >=
+	    CE_RING_FULL_THRESHOLD) {
+		hif_state->stats.ce_ring_full_count[pipe] = 0;
+		hif_state->stats.ce_manual_tasklet_schedule_count[pipe]++;
+		hif_state->stats.ce_last_manual_tasklet_schedule_ts[pipe] =
+			qdf_get_log_timestamp_usecs();
+		ce_dispatch_interrupt(pipe, &hif_state->tasklets[pipe]);
+	}
+}
+#else
+void hif_schedule_ce_tasklet(struct hif_opaque_softc *hif_ctx, uint8_t pipe)
+{
+}
+#endif
+
 uint16_t
 hif_get_free_queue_number(struct hif_opaque_softc *hif_ctx, uint8_t pipe)
 {

+ 6 - 0
hif/src/ce/ce_main.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2015-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -192,6 +193,11 @@ struct ce_stats {
 	uint64_t ce_tasklet_sched_bucket[CE_COUNT_MAX][CE_BUCKET_MAX];
 	uint64_t ce_tasklet_exec_last_update[CE_COUNT_MAX][CE_BUCKET_MAX];
 	uint64_t ce_tasklet_sched_last_update[CE_COUNT_MAX][CE_BUCKET_MAX];
+#ifdef CE_TASKLET_SCHEDULE_ON_FULL
+	uint32_t ce_ring_full_count[CE_COUNT_MAX];
+	uint32_t ce_manual_tasklet_schedule_count[CE_COUNT_MAX];
+	uint64_t ce_last_manual_tasklet_schedule_ts[CE_COUNT_MAX];
+#endif
 #endif
 };
 

+ 24 - 0
hif/src/ce/ce_tasklet.c

@@ -340,6 +340,28 @@ hif_ce_latency_stats(struct hif_softc *hif_ctx)
 }
 #endif /*CE_TASKLET_DEBUG_ENABLE*/
 
+#if defined(CE_TASKLET_DEBUG_ENABLE) && defined(CE_TASKLET_SCHEDULE_ON_FULL)
+/**
+ * hif_reset_ce_full_count() - Reset ce full count
+ * @scn: hif_softc
+ * @ce_id: ce_id
+ *
+ * Return: None
+ */
+static inline void
+hif_reset_ce_full_count(struct hif_softc *scn, uint8_t ce_id)
+{
+	struct HIF_CE_state *hif_ce_state = HIF_GET_CE_STATE(scn);
+
+	hif_ce_state->stats.ce_ring_full_count[ce_id] = 0;
+}
+#else
+static inline void
+hif_reset_ce_full_count(struct hif_softc *scn, uint8_t ce_id)
+{
+}
+#endif
+
 #ifdef HIF_DETECTION_LATENCY_ENABLE
 static inline
 void hif_latency_detect_tasklet_sched(
@@ -429,6 +451,7 @@ static void ce_tasklet(unsigned long data)
 		ce_tasklet_schedule(tasklet_entry);
 		hif_latency_detect_tasklet_sched(scn, tasklet_entry);
 
+		hif_reset_ce_full_count(scn, tasklet_entry->ce_id);
 		if (scn->ce_latency_stats) {
 			ce_tasklet_update_bucket(hif_ce_state,
 						 tasklet_entry->ce_id);
@@ -697,6 +720,7 @@ static inline bool hif_tasklet_schedule(struct hif_opaque_softc *hif_ctx,
 	hif_latency_detect_tasklet_sched(scn, tasklet_entry);
 	ce_tasklet_schedule(tasklet_entry);
 
+	hif_reset_ce_full_count(scn, tasklet_entry->ce_id);
 	if (scn->ce_latency_stats)
 		hif_record_tasklet_sched_entry_ts(scn, tasklet_entry->ce_id);
 

+ 4 - 1
htc/htc_send.c

@@ -1601,8 +1601,11 @@ static enum HTC_SEND_QUEUE_RESULT htc_try_send(HTC_TARGET *target,
 
 		if (pEndpoint->async_update &&
 			(!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) &&
-			(!tx_resources))
+			(!tx_resources)) {
+			hif_schedule_ce_tasklet(target->hif_dev,
+						pEndpoint->UL_PipeID);
 			break;
+		}
 
 		if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) {
 #if DEBUG_CREDIT