msm: ipa3: Initial version of minidump support in IPA

Initial version of minidump support in IPA driver.

Change-Id: I73e98fd647dd487dda90049f5b0c5609f558aa92
Signed-off-by: Ashok Vuyyuru <quic_avuyyuru@quicinc.com>
diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c
index e7452ba..1e71d46 100644
--- a/drivers/platform/msm/gsi/gsi.c
+++ b/drivers/platform/msm/gsi/gsi.c
@@ -25,6 +25,7 @@
 #include <linux/wait.h>
 #include <linux/delay.h>
 #include <linux/version.h>
+#include <soc/qcom/minidump.h>
 
 #define CREATE_TRACE_POINTS
 #include "gsi_trace.h"
@@ -5829,6 +5830,25 @@
 	return 0;
 }
 
+#if IS_ENABLED(CONFIG_QCOM_VA_MINIDUMP)
+static int qcom_va_md_gsi_notif_handler(struct notifier_block *this,
+				unsigned long event, void *ptr)
+{
+	struct va_md_entry entry;
+
+	strlcpy(entry.owner, "gsi_mini", sizeof(entry.owner));
+	entry.vaddr = (unsigned long)gsi_ctx;
+	entry.size = sizeof(struct gsi_ctx);
+	qcom_va_md_add_region(&entry);
+	return NOTIFY_OK;
+}
+
+static struct notifier_block qcom_va_md_gsi_notif_blk = {
+        .notifier_call = qcom_va_md_gsi_notif_handler,
+        .priority = INT_MAX,
+};
+#endif
+
 static int msm_gsi_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -5861,6 +5881,15 @@
 	init_completion(&gsi_ctx->gen_ee_cmd_compl);
 	gsi_debugfs_init();
 
+#if IS_ENABLED(CONFIG_QCOM_VA_MINIDUMP)
+	result = qcom_va_md_register("gsi_mini", &qcom_va_md_gsi_notif_blk);
+
+	if(result)
+		GSIERR("gsi mini qcom_va_md_register failed = %d\n", result);
+	else
+		GSIDBG("gsi mini qcom_va_md_register success\n");
+#endif
+
 	return 0;
 }
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/dump/ipa4.5/ipa_reg_dump.c b/drivers/platform/msm/ipa/ipa_v3/dump/ipa4.5/ipa_reg_dump.c
index f38bd47..cd28af8 100644
--- a/drivers/platform/msm/ipa/ipa_v3/dump/ipa4.5/ipa_reg_dump.c
+++ b/drivers/platform/msm/ipa/ipa_v3/dump/ipa4.5/ipa_reg_dump.c
@@ -1839,7 +1839,9 @@
 int ipa_reg_save_init(u32 value)
 {
 	u32 i, num_regs = ARRAY_SIZE(ipa_regs_to_save_array);
-
+#if IS_ENABLED(CONFIG_QCOM_VA_MINIDUMP)
+	struct ipa_minidump_data *mini_dump;
+#endif
 	if (!ipa3_ctx->do_register_collection_on_crash)
 		return 0;
 
@@ -1927,7 +1929,16 @@
 			goto alloc_fail2;
 		}
 	}
-
+#if IS_ENABLED(CONFIG_QCOM_VA_MINIDUMP)
+	/*Adding ipa_reg_save pointer to minidump list*/
+	mini_dump = (struct ipa_minidump_data *)kzalloc(sizeof(struct ipa_minidump_data), GFP_KERNEL);
+	if (mini_dump != NULL) {
+		strlcpy(mini_dump->data.owner, "ipa_reg_save", sizeof(mini_dump->data.owner));
+		mini_dump->data.vaddr = (unsigned long)&ipa_reg_save;
+		mini_dump->data.size = sizeof(ipa_reg_save);
+		list_add(&mini_dump->entry, &ipa3_ctx->minidump_list_head);
+	}
+#endif
 	return 0;
 
 alloc_fail2:
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 967f68a..13e8bdf 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -7870,6 +7870,9 @@
 	struct idr *idr;
 	bool reg = false;
 	enum ipa_ip_type ip;
+#if IS_ENABLED(CONFIG_QCOM_VA_MINIDUMP)
+	struct ipa_minidump_data *mini_dump;
+#endif
 
 	if (ipa3_ctx == NULL) {
 		IPADBG("IPA driver haven't initialized\n");
@@ -8241,7 +8244,16 @@
 		IPADBG("Fail to init spearhead ipa lnx module");
 
 	pr_info("IPA driver initialization was successful.\n");
-
+#if IS_ENABLED(CONFIG_QCOM_VA_MINIDUMP)
+	/*Adding ipa3_ctx pointer to minidump list*/
+	mini_dump = (struct ipa_minidump_data *)kzalloc(sizeof(struct ipa_minidump_data), GFP_KERNEL);
+	if (mini_dump != NULL) {
+		strlcpy(mini_dump->data.owner, "ipa3_ctx", sizeof(mini_dump->data.owner));
+		mini_dump->data.vaddr = (unsigned long)(ipa3_ctx);
+		mini_dump->data.size = sizeof(struct ipa3_context);
+		list_add(&mini_dump->entry, &ipa3_ctx->minidump_list_head);
+	}
+#endif
 	return 0;
 
 fail_teth_bridge_driver_init:
@@ -9030,6 +9042,26 @@
 	return IPA_TX_WRAPPER_CACHE_MAX_THRESHOLD;
 }
 
+#if IS_ENABLED(CONFIG_QCOM_VA_MINIDUMP)
+static int qcom_va_md_ipa_notif_handler(struct notifier_block *this,
+					unsigned long event, void *ptr)
+{
+	struct ipa_minidump_data *testptr;
+	struct ipa_minidump_data *ptr_next;
+
+	list_for_each_entry_safe(testptr, ptr_next, &ipa3_ctx->minidump_list_head, entry) {
+		qcom_va_md_add_region(&testptr->data);
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block qcom_va_md_ipa_notif_blk = {
+	.notifier_call = qcom_va_md_ipa_notif_handler,
+	.priority = INT_MAX,
+};
+#endif
+
 /**
  * ipa3_pre_init() - Initialize the IPA Driver.
  * This part contains all initialization which doesn't require IPA HW, such
@@ -9410,6 +9442,8 @@
 		}
 	}
 
+	INIT_LIST_HEAD(&ipa3_ctx->minidump_list_head);
+
 	/*
 	 * Setup access for register collection/dump on crash
 	 */
@@ -9717,6 +9751,14 @@
 	ipa3_ctx->is_modem_up = false;
 	ipa3_ctx->mhi_ctrl_state = IPA_MHI_CTRL_NOT_SETUP;
 
+#if IS_ENABLED(CONFIG_QCOM_VA_MINIDUMP)
+	result = qcom_va_md_register("ipa_mini", &qcom_va_md_ipa_notif_blk);
+
+	if(result)
+		IPAERR("ipa mini qcom_va_md_register failed = %d\n", result);
+	else
+		IPADBG("ipa mini qcom_va_md_register success\n");
+#endif
 	return 0;
 
 fail_rmnet_ll_init:
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 9b67cfe..1cb8f38 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -42,6 +42,7 @@
 #include <linux/rmnet_ipa_fd_ioctl.h>
 #include <linux/ipa_fmwk.h>
 #include "ipa_uc_holb_monitor.h"
+#include <soc/qcom/minidump.h>
 
 #define IPA_DEV_NAME_MAX_LEN 15
 #define DRV_NAME "ipa"
@@ -2092,6 +2093,13 @@
 };
 #endif
 
+#if IS_ENABLED(CONFIG_QCOM_VA_MINIDUMP)
+struct ipa_minidump_data {
+	struct list_head entry;
+	struct va_md_entry data;
+};
+#endif
+
 /**
  * struct ipa3_context - IPA context
  * @cdev: cdev context
@@ -2466,6 +2474,7 @@
 	u32 ipa_max_napi_sort_page_thrshld;
 	u32 page_wq_reschd_time;
 	bool coal_ipv4_id_ignore;
+	struct list_head minidump_list_head;
 };
 
 struct ipa3_plat_drv_res {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c
index f1e00cc..c934f70 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c
@@ -612,6 +612,9 @@
 {
 	int i, j;
 	struct clk_scaling_db *clk_scaling;
+#if IS_ENABLED(CONFIG_QCOM_VA_MINIDUMP)
+	struct ipa_minidump_data *mini_dump;
+#endif
 
 	if (params == NULL) {
 		IPA_PM_ERR("Invalid Params\n");
@@ -692,6 +695,17 @@
 	}
 	IPA_PM_DBG("initialization success");
 
+#if IS_ENABLED(CONFIG_QCOM_VA_MINIDUMP)
+	/*Adding ipa3_ctx pointer to minidump list*/
+	mini_dump = (struct ipa_minidump_data *)kzalloc(sizeof(struct ipa_minidump_data), GFP_KERNEL);
+	if (mini_dump != NULL) {
+		strlcpy(mini_dump->data.owner, "ipa_pm_ctx", sizeof(mini_dump->data.owner));
+		mini_dump->data.vaddr = (unsigned long)(ipa_pm_ctx);
+		mini_dump->data.size = sizeof(*ipa_pm_ctx);
+		list_add(&mini_dump->entry, &ipa3_ctx->minidump_list_head);
+	}
+#endif
+
 	return 0;
 }