qcacmn: Add unit test framework to validate WLAN suspend/resume features

WLAN suspend/resume feature has tight dependency on APPS platform
suspend/resume support. On new targets APPS suspend/resume is not
supported until target is feature complete. In absence of APPS
suspend/resume support testing WLAN offload features become
difficult. Add unit test framework to test WLAN suspend/resume
features using private IOCTL command by simulating APPS
suspend/resume behaviour.

Trigger WLAN suspend:
iwpriv wlan0 wlan_suspend 0 0

To resume WLAN run a ping test from access point side and very 1st
ping request unicast packet should trigger wake up.

If FW is not waking up APPS then use below command to do a manual
wake up:

Trigger WLAN resume:
iwpriv wlan0 wlan_resume 0 0

This framework is only for SNOC platform.

Change-Id: I177a0047f460aa2a305a9e4e46fbfaa94a81dced
CRs-Fixed: 1042205
diff --git a/hif/inc/hif.h b/hif/inc/hif.h
index b6db21d..d30de2d 100644
--- a/hif/inc/hif.h
+++ b/hif/inc/hif.h
@@ -615,6 +615,11 @@
 int32_t hif_get_nss_wifiol_bypass_nw_process(struct hif_opaque_softc *osc);
 #endif
 
+#ifdef WLAN_SUSPEND_RESUME_TEST
+typedef void (*hdd_fake_resume_callback)(uint32_t val);
+void hif_fake_apps_suspend(hdd_fake_resume_callback callback);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/hif/src/ce/ce_tasklet.c b/hif/src/ce/ce_tasklet.c
index f393f3f..27bfba1 100644
--- a/hif/src/ce/ce_tasklet.c
+++ b/hif/src/ce/ce_tasklet.c
@@ -243,6 +243,61 @@
 	qdf_atomic_set(&scn->active_tasklet_cnt, 0);
 }
 
+#ifdef WLAN_SUSPEND_RESUME_TEST
+static bool g_hif_apps_fake_suspended;
+static hdd_fake_resume_callback hdd_fake_aps_resume;
+
+static void hif_wlan_resume_work_handler(struct work_struct *work)
+{
+	hdd_fake_aps_resume(0);
+}
+
+static DECLARE_WORK(hif_resume_work, hif_wlan_resume_work_handler);
+
+/**
+ * hif_fake_apps_suspend(): Suspend WLAN
+ *
+ * Set the fake suspend flag such that hif knows that it will need
+ * to fake the aps resume process using the hdd_fake_aps_resume
+ *
+ * Return: none
+ */
+void hif_fake_apps_suspend(hdd_fake_resume_callback callback)
+{
+	hdd_fake_aps_resume = callback;
+	g_hif_apps_fake_suspended = true;
+}
+
+/**
+ * hif_fake_aps_resume(): check if WLAN resume is needed
+ *
+ * Return: true if a fake apps resume has been been triggered
+ *         returns false if regular interrupt processing is needed
+ */
+static bool hif_fake_aps_resume(void)
+{
+	if (g_hif_apps_fake_suspended) {
+		g_hif_apps_fake_suspended = false;
+		schedule_work(&hif_resume_work);
+		return true;
+	} else {
+		return false;
+	}
+}
+
+#else
+
+/**
+ * hif_fake_aps_resume(): check if WLAN resume is needed
+ *
+ * Return: always false if WLAN_SUSPEND_RESUME_TEST is not defined
+ */
+static bool hif_fake_aps_resume(void)
+{
+	return false;
+}
+#endif /* End of WLAN_SUSPEND_RESUME_TEST */
+
 /**
  * hif_snoc_interrupt_handler() - hif_snoc_interrupt_handler
  * @irq: irq coming from kernel
@@ -341,6 +396,13 @@
 	qdf_atomic_inc(&scn->active_tasklet_cnt);
 	hif_record_ce_desc_event(scn, ce_id, HIF_IRQ_EVENT, NULL, NULL, 0);
 	hif_ce_increment_interrupt_count(hif_ce_state, ce_id);
+
+	if (unlikely(hif_fake_aps_resume())) {
+		HIF_ERROR("received resume interrupt");
+		hif_irq_enable(scn, ce_id);
+		return IRQ_HANDLED;
+	}
+
 	if (hif_napi_enabled(hif_hdl, ce_id))
 		hif_napi_schedule(hif_hdl, ce_id);
 	else