Browse Source

qcacmn: Wait for OOM worker thread completion before going to runtime

Currently out of memory worker thread completion wait is not present
before going to wlan suspend, this may lead to worked thread accessing
CE ring HP updates when wlan is in suspend state.

Avoid this by waiting for out of memory worker thread completion
before entering wlan suspend.

Change-Id: Id9d0ae9dc1de03f4e3d95bb6fac1c41ecbf7e202
CRs-Fixed: 3714467
Karthik Kantamneni 1 year ago
parent
commit
65641d0d22
3 changed files with 43 additions and 15 deletions
  1. 6 4
      hif/src/ce/ce_main.c
  2. 23 10
      hif/src/hif_main.c
  3. 14 1
      hif/src/hif_main.h

+ 6 - 4
hif/src/ce/ce_main.c

@@ -2185,6 +2185,8 @@ static void ce_oom_recovery(void *context)
 		&ce_softc->pipe_info[ce_state->id];
 
 	hif_post_recv_buffers_for_pipe(pipe_info);
+
+	qdf_atomic_dec(&scn->active_oom_work_cnt);
 }
 
 #ifdef HIF_CE_DEBUG_DATA_BUF
@@ -3856,14 +3858,13 @@ static void hif_post_recv_buffers_failure(struct HIF_CE_pipe_info *pipe_info,
 	 */
 	if (bufs_needed_tmp == CE_state->dest_ring->nentries - 1 ||
 	    (ce_srng_based(scn) &&
-	     bufs_needed_tmp == CE_state->dest_ring->nentries - 2))
+	     bufs_needed_tmp == CE_state->dest_ring->nentries - 2)) {
+		qdf_atomic_inc(&scn->active_oom_work_cnt);
 		qdf_sched_work(scn->qdf_dev, &CE_state->oom_allocation_work);
+	}
 
 }
 
-
-
-
 QDF_STATUS hif_post_recv_buffers_for_pipe(struct HIF_CE_pipe_info *pipe_info)
 {
 	struct CE_handle *ce_hdl;
@@ -4280,6 +4281,7 @@ static void hif_destroy_oom_work(struct hif_softc *scn)
 			qdf_destroy_work(scn->qdf_dev,
 					 &ce_state->oom_allocation_work);
 	}
+	qdf_atomic_set(&scn->active_oom_work_cnt, 0);
 }
 
 void hif_ce_stop(struct hif_softc *scn)

+ 23 - 10
hif/src/hif_main.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1281,6 +1281,7 @@ struct hif_opaque_softc *hif_open(qdf_device_t qdf_ctx,
 	scn->qdf_dev = qdf_ctx;
 	scn->hif_con_param = mode;
 	qdf_atomic_init(&scn->active_tasklet_cnt);
+	qdf_atomic_init(&scn->active_oom_work_cnt);
 
 	qdf_atomic_init(&scn->active_grp_tasklet_cnt);
 	qdf_atomic_init(&scn->link_suspended);
@@ -1423,21 +1424,33 @@ static inline int hif_get_num_pending_work(struct hif_softc *scn)
 QDF_STATUS hif_try_complete_tasks(struct hif_softc *scn)
 {
 	uint32_t task_drain_wait_cnt = 0;
-	int tasklet = 0, grp_tasklet = 0, work = 0;
+	int tasklet = 0, grp_tasklet = 0, work = 0, oom_work = 0;
 
 	while ((tasklet = hif_get_num_active_tasklets(scn)) ||
 	       (grp_tasklet = hif_get_num_active_grp_tasklets(scn)) ||
-	       (work = hif_get_num_pending_work(scn))) {
+	       (work = hif_get_num_pending_work(scn)) ||
+		(oom_work = hif_get_num_active_oom_work(scn))) {
 		if (++task_drain_wait_cnt > HIF_TASK_DRAIN_WAIT_CNT) {
-			hif_err("pending tasklets %d grp tasklets %d work %d",
-				tasklet, grp_tasklet, work);
-			QDF_DEBUG_PANIC("Complete tasks takes more than %u ms: tasklets %d grp tasklets %d work %d",
-					HIF_TASK_DRAIN_WAIT_CNT * 10,
-					tasklet, grp_tasklet, work);
+			hif_err("pending tasklets %d grp tasklets %d work %d oom work %d",
+				tasklet, grp_tasklet, work, oom_work);
+			/*
+			 * There is chance of OOM thread getting scheduled
+			 * continuously or execution get delayed during low
+			 * memory state. So avoid panic and prevent suspend
+			 * only if OOM thread is unable to complete pending
+			 * work.
+			 */
+			if ((!tasklet) && (!grp_tasklet) && (!work) && oom_work)
+				hif_err("OOM thread is still pending cannot complete the work");
+			else
+				QDF_DEBUG_PANIC("Complete tasks takes more than %u ms: tasklets %d grp tasklets %d work %d oom_work %d",
+						HIF_TASK_DRAIN_WAIT_CNT * 10,
+						tasklet, grp_tasklet, work,
+						oom_work);
 			return QDF_STATUS_E_FAULT;
 		}
-		hif_info("waiting for tasklets %d grp tasklets %d work %d",
-			 tasklet, grp_tasklet, work);
+		hif_info("waiting for tasklets %d grp tasklets %d work %d oom_work %d",
+			 tasklet, grp_tasklet, work, oom_work);
 		msleep(10);
 	}
 

+ 14 - 1
hif/src/hif_main.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -393,6 +393,7 @@ struct hif_softc {
 	struct ce_int_assignment *int_assignment;
 	atomic_t active_tasklet_cnt;
 	atomic_t active_grp_tasklet_cnt;
+	atomic_t active_oom_work_cnt;
 	atomic_t link_suspended;
 	void *vaddr_rri_on_ddr;
 	atomic_t active_wake_req_cnt;
@@ -575,6 +576,18 @@ static inline int hif_get_num_active_tasklets(struct hif_softc *scn)
 	return qdf_atomic_read(&scn->active_tasklet_cnt);
 }
 
+/**
+ * hif_get_num_active_oom_work() - get the number of active
+ *		oom work pending to be completed.
+ * @scn: HIF context
+ *
+ * Returns: the number of oom works which are active
+ */
+static inline int hif_get_num_active_oom_work(struct hif_softc *scn)
+{
+	return qdf_atomic_read(&scn->active_oom_work_cnt);
+}
+
 /*
  * Max waiting time during Runtime PM suspend to finish all
  * the tasks. This is in the multiple of 10ms.