qcacld-3.0: Add new data stall detection module in hdd

Add data stall detection module in hdd which handles data
stall reported by host or fw and take necessary recovery
steps based on the data stall type.

Change-Id: Idf6c43f55d1bc115a0c06b4c6ef766ff3ed09bee
CRs-Fixed: 2090643
diff --git a/Kbuild b/Kbuild
index ee29be3..0183dba 100644
--- a/Kbuild
+++ b/Kbuild
@@ -411,6 +411,7 @@
 
 HDD_OBJS := 	$(HDD_SRC_DIR)/wlan_hdd_assoc.o \
 		$(HDD_SRC_DIR)/wlan_hdd_cfg.o \
+		$(HDD_SRC_DIR)/wlan_hdd_data_stall_detection.o \
 		$(HDD_SRC_DIR)/wlan_hdd_driver_ops.o \
 		$(HDD_SRC_DIR)/wlan_hdd_ftm.o \
 		$(HDD_SRC_DIR)/wlan_hdd_hostapd.o \
diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c
index 5c8986e..854e4f1 100644
--- a/core/dp/txrx/ol_txrx.c
+++ b/core/dp/txrx/ol_txrx.c
@@ -5109,6 +5109,46 @@
 }
 #endif
 
+/**
+ * ol_register_data_stall_detect_cb() - register data stall callback
+ * @data_stall_detect_callback: data stall callback function
+ *
+ *
+ * Return: QDF_STATUS Enumeration
+ */
+static QDF_STATUS ol_register_data_stall_detect_cb(
+				data_stall_detect_cb data_stall_detect_callback)
+{
+	struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
+
+	if (pdev == NULL) {
+		ol_txrx_err("%s: pdev NULL!", __func__);
+		return QDF_STATUS_E_INVAL;
+	}
+	pdev->data_stall_detect_callback = data_stall_detect_callback;
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * ol_deregister_data_stall_detect_cb() - de-register data stall callback
+ * @data_stall_detect_callback: data stall callback function
+ *
+ *
+ * Return: QDF_STATUS Enumeration
+ */
+static QDF_STATUS ol_deregister_data_stall_detect_cb(
+				data_stall_detect_cb data_stall_detect_callback)
+{
+	struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
+
+	if (pdev == NULL) {
+		ol_txrx_err("%s: pdev NULL!", __func__);
+		return QDF_STATUS_E_INVAL;
+	}
+	pdev->data_stall_detect_callback = NULL;
+	return QDF_STATUS_SUCCESS;
+}
+
 void
 ol_txrx_dump_pkt(qdf_nbuf_t nbuf, uint32_t nbuf_paddr, int len)
 {
@@ -5448,6 +5488,8 @@
 	.tx_non_std = ol_tx_non_std,
 	.get_vdev_id = ol_txrx_get_vdev_id,
 	.set_wisa_mode = ol_txrx_set_wisa_mode,
+	.txrx_data_stall_cb_register = ol_register_data_stall_detect_cb,
+	.txrx_data_stall_cb_deregister = ol_deregister_data_stall_detect_cb,
 #ifdef FEATURE_RUNTIME_PM
 	.runtime_suspend = ol_txrx_runtime_suspend,
 	.runtime_resume = ol_txrx_runtime_resume,
diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h
index 5718932..8836e72 100644
--- a/core/dp/txrx/ol_txrx_types.h
+++ b/core/dp/txrx/ol_txrx_types.h
@@ -709,6 +709,7 @@
 		} callbacks[OL_TXRX_MGMT_NUM_TYPES];
 	} tx_mgmt;
 
+	data_stall_detect_cb data_stall_detect_callback;
 	/* packetdump callback functions */
 	tp_ol_packetdump_cb ol_tx_packetdump_cb;
 	tp_ol_packetdump_cb ol_rx_packetdump_cb;
diff --git a/core/hdd/inc/wlan_hdd_data_stall_detection.h b/core/hdd/inc/wlan_hdd_data_stall_detection.h
new file mode 100644
index 0000000..4104ba5
--- /dev/null
+++ b/core/hdd/inc/wlan_hdd_data_stall_detection.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __WLAN_HDD_DATA_STALL_DETECTION_H
+#define __WLAN_HDD_DATA_STALL_DETECTION_H
+
+/**
+ * DOC: wlan_hdd_data_stall_detection.h
+ *
+ * WLAN Host Device Driver data stall detection API specification
+ */
+
+/**
+ * hdd_register_data_stall_detect_cb() - register data stall callback
+ *
+ * Return: 0 for success or Error code for failure
+ */
+int hdd_register_data_stall_detect_cb(void);
+
+/**
+ * hdd_deregister_data_stall_detect_cb() - de-register data stall callback
+ *
+ * Return: 0 for success or Error code for failure
+ */
+int hdd_deregister_data_stall_detect_cb(void);
+#endif /* __WLAN_HDD_DATA_STALL_DETECTION_H */
diff --git a/core/hdd/src/wlan_hdd_data_stall_detection.c b/core/hdd/src/wlan_hdd_data_stall_detection.c
new file mode 100644
index 0000000..31dbd3f
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_data_stall_detection.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: wlan_hdd_data_stall_detection.c
+ *
+ * WLAN Host Device Driver Data Stall detection API implementation
+ */
+
+#include "wlan_hdd_data_stall_detection.h"
+#include "cdp_txrx_cmn.h"
+#include "cdp_txrx_misc.h"
+#include "ol_txrx_types.h"
+
+/**
+ * hdd_data_stall_process_cb() - Process data stall message
+ * @message: data stall message
+ *
+ * Process data stall message
+ *
+ * Return: void
+ */
+static void hdd_data_stall_process_cb(
+			struct data_stall_event_info *data_stall_info)
+{
+}
+
+int hdd_register_data_stall_detect_cb(void)
+{
+	QDF_STATUS status;
+	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
+
+	/* Register the data stall callback */
+	status = cdp_data_stall_cb_register(soc, hdd_data_stall_process_cb);
+	return qdf_status_to_os_return(status);
+}
+
+int hdd_deregister_data_stall_detect_cb(void)
+{
+	QDF_STATUS status;
+	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
+
+	/* De-Register the data stall callback */
+	status = cdp_data_stall_cb_deregister(soc, hdd_data_stall_process_cb);
+	return qdf_status_to_os_return(status);
+}
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index aa4a23d..5dc84dd 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -93,6 +93,7 @@
 #include "wlan_hdd_driver_ops.h"
 #include "epping_main.h"
 #include "wlan_hdd_memdump.h"
+#include "wlan_hdd_data_stall_detection.h"
 
 #include <wlan_hdd_ipa.h>
 #include "hif.h"
@@ -10025,6 +10026,12 @@
 	if (!QDF_IS_STATUS_SUCCESS(status))
 		hdd_err("set lost link info callback failed");
 
+	ret = hdd_register_data_stall_detect_cb();
+	if (ret) {
+		hdd_err("Register data stall detect detect callback failed.");
+		return ret;
+	}
+
 	wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
 
 	sme_register_set_connection_info_cb(hdd_ctx->hHal,
@@ -10057,6 +10064,7 @@
 void hdd_deregister_cb(struct hdd_context *hdd_ctx)
 {
 	QDF_STATUS status;
+	int ret;
 
 	ENTER();
 
@@ -10081,6 +10089,10 @@
 		hdd_err("Failed to de-register the fw mem dump callback: %d",
 			status);
 
+	ret = hdd_deregister_data_stall_detect_cb();
+	if (ret)
+		hdd_err("Failed to de-register data stall detect event callback");
+
 	sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
 	sme_deregister11d_scan_done_callback(hdd_ctx->hHal);