static int handle_indication_req(void *req_h, void *req)
{
	struct ipa_indication_reg_req_msg_v01 *indication_req;
	struct ipa_indication_reg_resp_msg_v01 resp;
	struct ipa_master_driver_init_complt_ind_msg_v01 ind;
	int rc;

	indication_req = (struct ipa_indication_reg_req_msg_v01 *)req;
	IPAWANDBG("Received INDICATION Request\n");

	memset(&resp, 0, sizeof(struct ipa_indication_reg_resp_msg_v01));
	resp.resp.result = IPA_QMI_RESULT_SUCCESS_V01;
	rc = qmi_send_resp_from_cb(ipa_svc_handle, curr_conn, req_h,
			&ipa_indication_reg_resp_desc, &resp, sizeof(resp));
	qmi_indication_fin = true;
	/* check if need sending indication to modem */
	if (qmi_modem_init_fin)	{
		IPAWANDBG("send indication to modem (%d)\n",
		qmi_modem_init_fin);
		memset(&ind, 0, sizeof(struct
				ipa_master_driver_init_complt_ind_msg_v01));
		ind.master_driver_init_status.result =
			IPA_QMI_RESULT_SUCCESS_V01;
		rc = qmi_send_ind_from_cb(ipa_svc_handle, curr_conn,
			&ipa_master_driver_complete_indication_desc,
			&ind,
			sizeof(ind));
	} else {
		IPAWANERR("not send indication\n");
	}
	return rc;
}
/* sending filter-install-request to modem*/
int qmi_filter_request_send(struct ipa_install_fltr_rule_req_msg_v01 *req)
{
	struct ipa_install_fltr_rule_resp_msg_v01 resp;
	struct msg_desc req_desc, resp_desc;
	int rc;

	/* check if the filter rules from IPACM is valid */
	if (req->filter_spec_list_len == 0) {
		IPAWANDBG("IPACM pass zero rules to Q6\n");
	} else {
		IPAWANDBG("IPACM pass %d rules to Q6\n",
		req->filter_spec_list_len);
	}

	req_desc.max_msg_len = QMI_IPA_INSTALL_FILTER_RULE_REQ_MAX_MSG_LEN_V01;
	req_desc.msg_id = QMI_IPA_INSTALL_FILTER_RULE_REQ_V01;
	req_desc.ei_array = ipa_install_fltr_rule_req_msg_data_v01_ei;

	memset(&resp, 0, sizeof(struct ipa_install_fltr_rule_resp_msg_v01));
	resp_desc.max_msg_len =
		QMI_IPA_INSTALL_FILTER_RULE_RESP_MAX_MSG_LEN_V01;
	resp_desc.msg_id = QMI_IPA_INSTALL_FILTER_RULE_RESP_V01;
	resp_desc.ei_array = ipa_install_fltr_rule_resp_msg_data_v01_ei;

	rc = qmi_send_req_wait(ipa_q6_clnt, &req_desc,
			req,
			sizeof(struct ipa_install_fltr_rule_req_msg_v01),
			&resp_desc, &resp, sizeof(resp),
			QMI_SEND_REQ_TIMEOUT_MS);
	return ipa_check_qmi_response(rc,
		QMI_IPA_INSTALL_FILTER_RULE_REQ_V01, resp.resp.result,
		resp.resp.error, "ipa_install_filter");
}
static void ipa_q6_clnt_ind_cb(struct qmi_handle *handle, unsigned int msg_id,
			       void *msg, unsigned int msg_len,
			       void *ind_cb_priv)
{
	struct ipa_data_usage_quota_reached_ind_msg_v01 qmi_ind;
	struct msg_desc qmi_ind_desc;
	int rc = 0;

	if (handle != ipa_q6_clnt) {
		IPAWANERR("Wrong client\n");
		return;
	}

	if (QMI_IPA_DATA_USAGE_QUOTA_REACHED_IND_V01 == msg_id) {
		memset(&qmi_ind, 0, sizeof(
			struct ipa_data_usage_quota_reached_ind_msg_v01));
		qmi_ind_desc.max_msg_len =
			QMI_IPA_DATA_USAGE_QUOTA_REACHED_IND_MAX_MSG_LEN_V01;
		qmi_ind_desc.msg_id = QMI_IPA_DATA_USAGE_QUOTA_REACHED_IND_V01;
		qmi_ind_desc.ei_array =
			ipa_data_usage_quota_reached_ind_msg_data_v01_ei;

		rc = qmi_kernel_decode(&qmi_ind_desc, &qmi_ind, msg, msg_len);
		if (rc < 0) {
			IPAWANERR("Error decoding msg_id %d\n", msg_id);
			return;
		}
		IPAWANDBG("Quota reached indication on qmux(%d) Mbytes(%lu)\n",
			  qmi_ind.apn.mux_id,
			  (long unsigned int) qmi_ind.apn.num_Mbytes);
		ipa_broadcast_quota_reach_ind(qmi_ind.apn.mux_id);
	}
}
static int handle_filter_installed_notify_req(void *req_h, void *req)
{
	struct ipa_fltr_installed_notif_resp_msg_v01 resp;
	int rc = 0;

	memset(&resp, 0, sizeof(struct ipa_fltr_installed_notif_resp_msg_v01));
	IPAWANDBG("Received filter_install_notify Request\n");
	resp.resp.result = IPA_QMI_RESULT_SUCCESS_V01;

	rc = qmi_send_resp_from_cb(ipa_svc_handle, curr_conn, req_h,
			&ipa_filter_installed_notif_resp_desc,
			&resp, sizeof(resp));

	IPAWANDBG("Responsed filter_install_notify Request\n");
	return rc;
}
static int ipa_check_qmi_response(int rc,
				  int req_id,
				  enum ipa_qmi_result_type_v01 result,
				  enum ipa_qmi_error_type_v01 error,
				  char *resp_type)
{
	if (rc < 0) {
		if (rc == -ETIMEDOUT && ipa_rmnet_ctx.ipa_rmnet_ssr) {
			IPAWANERR(
			"Timeout for qmi request id %d\n", req_id);
			return rc;
		}
		if (rc == -ENETRESET) {
			IPAWANERR(
			"SSR while waiting for qmi request id %d\n", req_id);
			return rc;
		}
		IPAWANERR("Error sending qmi request id %d, rc = %d\n",
			req_id, rc);
		return rc;
	}
	if (result != IPA_QMI_RESULT_SUCCESS_V01 &&
	    ipa_rmnet_ctx.ipa_rmnet_ssr) {
		IPAWANERR(
		"Got bad response %d from request id %d (error %d)\n",
		req_id, result, error);
		return result;
	}
	IPAWANDBG("Received %s successfully\n", resp_type);
	return 0;
}
static int handle_install_filter_rule_req(void *req_h, void *req)
{
	struct ipa_install_fltr_rule_req_msg_v01 *rule_req;
	struct ipa_install_fltr_rule_resp_msg_v01 resp;
	uint32_t rule_hdl[MAX_NUM_Q6_RULE];
	int rc = 0, i;

	rule_req = (struct ipa_install_fltr_rule_req_msg_v01 *)req;
	memset(rule_hdl, 0, sizeof(rule_hdl));
	memset(&resp, 0, sizeof(struct ipa_install_fltr_rule_resp_msg_v01));
	IPAWANDBG("Received install filter Request\n");

	rc = copy_ul_filter_rule_to_ipa((struct
		ipa_install_fltr_rule_req_msg_v01*)req, rule_hdl);
	if (rc)
		IPAWANERR("copy UL rules from modem is failed\n");

	resp.resp.result = IPA_QMI_RESULT_SUCCESS_V01;
	if (rule_req->filter_spec_list_valid == true) {
		resp.filter_handle_list_valid = true;
		if (rule_req->filter_spec_list_len > MAX_NUM_Q6_RULE) {
			resp.filter_handle_list_len = MAX_NUM_Q6_RULE;
			IPAWANERR("installed (%d) max Q6-UL rules ",
			MAX_NUM_Q6_RULE);
			IPAWANERR("but modem gives total (%d)\n",
			rule_req->filter_spec_list_len);
		} else {
			resp.filter_handle_list_len =
				rule_req->filter_spec_list_len;
		}
	} else {
		resp.filter_handle_list_valid = false;
	}

	/* construct UL filter rules response to Modem*/
	for (i = 0; i < resp.filter_handle_list_len; i++) {
		resp.filter_handle_list[i].filter_spec_identifier =
			rule_req->filter_spec_list[i].filter_spec_identifier;
		resp.filter_handle_list[i].filter_handle = rule_hdl[i];
	}

	rc = qmi_send_resp_from_cb(ipa_svc_handle, curr_conn, req_h,
			&ipa_install_fltr_rule_resp_desc, &resp, sizeof(resp));

	IPAWANDBG("Replied to install filter request\n");
	return rc;
}
static int handle_ipa_config_req(void *req_h, void *req)
{
	struct ipa_config_resp_msg_v01 resp;
	int rc;

	memset(&resp, 0, sizeof(struct ipa_config_resp_msg_v01));
	resp.resp.result = IPA_QMI_RESULT_SUCCESS_V01;
	IPAWANDBG("Received IPA CONFIG Request\n");
	rc = ipa_mhi_handle_ipa_config_req(
		(struct ipa_config_req_msg_v01 *)req);
	if (rc) {
		IPAERR("ipa_mhi_handle_ipa_config_req failed %d\n", rc);
		resp.resp.result = IPA_QMI_RESULT_FAILURE_V01;
	}
	rc = qmi_send_resp_from_cb(ipa_svc_handle, curr_conn, req_h,
		&ipa_config_resp_desc,
		&resp, sizeof(resp));
	IPAWANDBG("Responsed IPA CONFIG Request\n");
	return rc;
}
static void ipa_a5_svc_recv_msg(struct work_struct *work)
{
	int rc;

	do {
		IPAWANDBG("Notified about a Receive Event");
		rc = qmi_recv_msg(ipa_svc_handle);
	} while (rc == 0);
	if (rc != -ENOMSG)
		IPAWANERR("Error receiving message\n");
}
static void ipa_q6_clnt_notify(struct qmi_handle *handle,
			     enum qmi_event_type event, void *notify_priv)
{
	switch (event) {
	case QMI_RECV_MSG:
		IPAWANDBG("client qmi recv message called");
		queue_delayed_work(ipa_clnt_resp_workqueue,
				   &work_recv_msg_client, 0);
		break;
	default:
		break;
	}
}
int wan_ioctl_init(void)
{
	unsigned int wan_ioctl_major = 0;
	int ret;
	struct device *dev;

	device = MKDEV(wan_ioctl_major, 0);

	ret = alloc_chrdev_region(&device, 0, dev_num, DRIVER_NAME);
	if (ret) {
		IPAWANERR(":device_alloc err.\n");
		goto dev_alloc_err;
	}
	wan_ioctl_major = MAJOR(device);

	class = class_create(THIS_MODULE, DRIVER_NAME);
	if (IS_ERR(class)) {
		IPAWANERR(":class_create err.\n");
		goto class_err;
	}

	dev = device_create(class, NULL, device,
		NULL, DRIVER_NAME);
	if (IS_ERR(dev)) {
		IPAWANERR(":device_create err.\n");
		goto device_err;
	}

	cdev_init(&wan_ioctl_cdev, &fops);
	ret = cdev_add(&wan_ioctl_cdev, device, dev_num);
	if (ret) {
		IPAWANERR(":cdev_add err.\n");
		goto cdev_add_err;
	}

	process_ioctl = 1;

	IPAWANDBG("IPA %s major(%d) initial ok :>>>>\n",
	DRIVER_NAME, wan_ioctl_major);
	return 0;

cdev_add_err:
	device_destroy(class, device);
device_err:
	class_destroy(class);
class_err:
	unregister_chrdev_region(device, dev_num);
dev_alloc_err:
	return -ENODEV;
}
int qmi_disable_force_clear_datapath_send(
	struct ipa_disable_force_clear_datapath_req_msg_v01 *req)
{
	struct ipa_disable_force_clear_datapath_resp_msg_v01 resp;
	struct msg_desc req_desc, resp_desc;
	int rc = 0;


	if (!req) {
		IPAWANERR("invalid params\n");
		return -EINVAL;
	}

	req_desc.max_msg_len =
		QMI_IPA_DISABLE_FORCE_CLEAR_DATAPATH_REQ_MAX_MSG_LEN_V01;
	req_desc.msg_id = QMI_IPA_DISABLE_FORCE_CLEAR_DATAPATH_REQ_V01;
	req_desc.ei_array =
		ipa_disable_force_clear_datapath_req_msg_data_v01_ei;

	memset(&resp, 0, sizeof(struct ipa_fltr_installed_notif_resp_msg_v01));
	resp_desc.max_msg_len =
		QMI_IPA_DISABLE_FORCE_CLEAR_DATAPATH_RESP_MAX_MSG_LEN_V01;
	resp_desc.msg_id = QMI_IPA_DISABLE_FORCE_CLEAR_DATAPATH_RESP_V01;
	resp_desc.ei_array =
		ipa_disable_force_clear_datapath_resp_msg_data_v01_ei;

	rc = qmi_send_req_wait(ipa_q6_clnt,
			&req_desc,
			req,
			sizeof(*req),
			&resp_desc, &resp, sizeof(resp), 0);
	if (rc < 0) {
		IPAWANERR("send req failed %d\n", rc);
		return rc;
	}
	if (resp.resp.result != IPA_QMI_RESULT_SUCCESS_V01) {
		IPAWANERR("filter_notify failed %d\n",
			resp.resp.result);
		return resp.resp.result;
	}
	IPAWANDBG("SUCCESS\n");
	return rc;
}
int wan_ioctl_init(void)
{
	unsigned int wan_ioctl_major = 0;
	dev_t device = MKDEV(wan_ioctl_major, 0);
	int alloc_ret = 0;
	int cdev_ret = 0;
	struct class *class;
	struct device *dev;

	alloc_ret = alloc_chrdev_region(&device, 0, dev_num, DRIVER_NAME);
	if (alloc_ret) {
		IPAWANERR(":device_alloc err.\n");
		goto error;
	}
	wan_ioctl_major = MAJOR(device);

	class = class_create(THIS_MODULE, DRIVER_NAME);
	dev = device_create(class, NULL, device,
		NULL, DRIVER_NAME);
	if (IS_ERR(dev)) {
		IPAWANERR(":device_create err.\n");
		goto error;
	}

	cdev_init(&wan_ioctl_cdev, &fops);
	cdev_ret = cdev_add(&wan_ioctl_cdev, device, dev_num);
	if (cdev_ret) {
		IPAWANERR(":cdev_add err.\n");
		goto error;
	}

	IPAWANDBG("IPA %s major(%d) initial ok :>>>>\n",
	DRIVER_NAME, wan_ioctl_major);
	return 0;
error:
	if (cdev_ret == 0)
		cdev_del(&wan_ioctl_cdev);
	if (alloc_ret == 0)
		unregister_chrdev_region(device, dev_num);
	return -ENODEV;
}
static long wan_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	int retval = 0;
	u32 pyld_sz;
	u8 *param = NULL;

	IPAWANDBG("device %s got ioctl events :>>>\n",
		DRIVER_NAME);
	switch (cmd) {
	case WAN_IOC_ADD_FLT_RULE:
		IPAWANDBG("device %s got WAN_IOC_ADD_FLT_RULE :>>>\n",
		DRIVER_NAME);
		pyld_sz = sizeof(struct ipa_install_fltr_rule_req_msg_v01);
		param = kzalloc(pyld_sz, GFP_KERNEL);
		if (!param) {
			retval = -ENOMEM;
			break;
		}
		if (copy_from_user(param, (u8 *)arg, pyld_sz)) {
			retval = -EFAULT;
			break;
		}
		if (qmi_filter_request_send(
			(struct ipa_install_fltr_rule_req_msg_v01 *)param)) {
			IPAWANDBG("IPACM->Q6 add filter rule failed\n");
			retval = -EFAULT;
			break;
		}
		if (copy_to_user((u8 *)arg, param, pyld_sz)) {
			retval = -EFAULT;
			break;
		}
		break;

	case WAN_IOC_ADD_FLT_RULE_INDEX:
	    IPAWANDBG("device %s got WAN_IOC_ADD_FLT_RULE_INDEX :>>>\n",
		DRIVER_NAME);
		pyld_sz = sizeof(struct ipa_fltr_installed_notif_req_msg_v01);
		param = kzalloc(pyld_sz, GFP_KERNEL);
		if (!param) {
			retval = -ENOMEM;
			break;
		}
		if (copy_from_user(param, (u8 *)arg, pyld_sz)) {
			retval = -EFAULT;
			break;
		}
		if (qmi_filter_notify_send(
		(struct ipa_fltr_installed_notif_req_msg_v01 *)param)) {
			IPAWANDBG("IPACM->Q6 rule index fail\n");
			retval = -EFAULT;
			break;
		}
		if (copy_to_user((u8 *)arg, param, pyld_sz)) {
			retval = -EFAULT;
			break;
		}
		break;
	default:
		retval = -ENOTTY;
	}
	kfree(param);
	return retval;
}
static int wan_ioctl_open(struct inode *inode, struct file *filp)
{
	IPAWANDBG("\n IPA A7 wan_ioctl open OK :>>>> ");
	return 0;
}
static void ipa_q6_clnt_svc_arrive(struct work_struct *work)
{
	int rc;
	struct ipa_master_driver_init_complt_ind_msg_v01 ind;

	/* Create a Local client port for QMI communication */
	ipa_q6_clnt = qmi_handle_create(ipa_q6_clnt_notify, NULL);
	if (!ipa_q6_clnt) {
		IPAWANERR("QMI client handle alloc failed\n");
		return;
	}

	IPAWANDBG("Lookup server name, get client-hdl(%p)\n",
		ipa_q6_clnt);
	rc = qmi_connect_to_service(ipa_q6_clnt,
			IPA_Q6_SERVICE_SVC_ID,
			IPA_Q6_SVC_VERS,
			IPA_Q6_SERVICE_INS_ID);
	if (rc < 0) {
		IPAWANERR("Server not found\n");
		qmi_handle_destroy(ipa_q6_clnt);
		ipa_q6_clnt = NULL;
		return;
	}

	rc = qmi_register_ind_cb(ipa_q6_clnt, ipa_q6_clnt_ind_cb, NULL);
	if (rc < 0)
		IPAWANERR("Unable to register for indications\n");

	ipa_q6_clnt_reset = 0;
	IPAWANDBG("Q6 QMI service available now\n");
	/* Initialize modem IPA-driver */
	IPAWANDBG("send qmi_init_modem_send_sync_msg to modem\n");
	rc = qmi_init_modem_send_sync_msg();
	if (rc == -ENETRESET) {
		IPAWANERR("qmi_init_modem_send_sync_msg failed due to SSR!\n");
		/* Cleanup will take place when ipa_wwan_remove is called */
		return;
	}
	if (rc != 0) {
		IPAWANERR("qmi_init_modem_send_sync_msg failed\n");
		/*
		 * This is a very unexpected scenario, which requires a kernel
		 * panic in order to force dumps for QMI/Q6 side analysis.
		 */
		BUG();
		return;
	}
	qmi_modem_init_fin = true;
	ipa_proxy_clk_unvote();
	/* is_load_uc=FALSE indicates that SSR has occured */
	ipa_q6_handshake_complete(!is_load_uc);
	IPAWANDBG("complete, qmi_modem_init_fin : %d\n",
		qmi_modem_init_fin);

	if (qmi_indication_fin)	{
		IPAWANDBG("send indication to modem (%d)\n",
		qmi_indication_fin);
		memset(&ind, 0, sizeof(struct
				ipa_master_driver_init_complt_ind_msg_v01));
		ind.master_driver_init_status.result =
			IPA_QMI_RESULT_SUCCESS_V01;
		rc = qmi_send_ind(ipa_svc_handle, curr_conn,
			&ipa_master_driver_complete_indication_desc,
			&ind,
			sizeof(ind));
		IPAWANDBG("ipa_qmi_service_client good\n");
	} else {
		IPAWANERR("not send indication (%d)\n",
		qmi_indication_fin);
	}
}
static long wan_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	int retval = 0;
	u32 pyld_sz;
	u8 *param = NULL;

	IPAWANDBG("device %s got ioctl events :>>>\n",
		DRIVER_NAME);

	if (!process_ioctl) {
		IPAWANDBG("modem is in SSR, ignoring ioctl\n");
		return -EAGAIN;
	}

	switch (cmd) {
	case WAN_IOC_ADD_FLT_RULE:
		IPAWANDBG("device %s got WAN_IOC_ADD_FLT_RULE :>>>\n",
		DRIVER_NAME);
		pyld_sz = sizeof(struct ipa_install_fltr_rule_req_msg_v01);
		param = kzalloc(pyld_sz, GFP_KERNEL);
		if (!param) {
			retval = -ENOMEM;
			break;
		}
		if (copy_from_user(param, (u8 *)arg, pyld_sz)) {
			retval = -EFAULT;
			break;
		}
		if (qmi_filter_request_send(
			(struct ipa_install_fltr_rule_req_msg_v01 *)param)) {
			IPAWANDBG("IPACM->Q6 add filter rule failed\n");
			retval = -EFAULT;
			break;
		}
		if (copy_to_user((u8 *)arg, param, pyld_sz)) {
			retval = -EFAULT;
			break;
		}
		break;

	case WAN_IOC_ADD_FLT_RULE_INDEX:
		IPAWANDBG("device %s got WAN_IOC_ADD_FLT_RULE_INDEX :>>>\n",
		DRIVER_NAME);
		pyld_sz = sizeof(struct ipa_fltr_installed_notif_req_msg_v01);
		param = kzalloc(pyld_sz, GFP_KERNEL);
		if (!param) {
			retval = -ENOMEM;
			break;
		}
		if (copy_from_user(param, (u8 *)arg, pyld_sz)) {
			retval = -EFAULT;
			break;
		}
		if (qmi_filter_notify_send(
		(struct ipa_fltr_installed_notif_req_msg_v01 *)param)) {
			IPAWANDBG("IPACM->Q6 rule index fail\n");
			retval = -EFAULT;
			break;
		}
		if (copy_to_user((u8 *)arg, param, pyld_sz)) {
			retval = -EFAULT;
			break;
		}
		break;

	case WAN_IOC_VOTE_FOR_BW_MBPS:
		IPAWANDBG("device %s got WAN_IOC_VOTE_FOR_BW_MBPS :>>>\n",
		DRIVER_NAME);
		pyld_sz = sizeof(uint32_t);
		param = kzalloc(pyld_sz, GFP_KERNEL);
		if (!param) {
			retval = -ENOMEM;
			break;
		}
		if (copy_from_user(param, (u8 *)arg, pyld_sz)) {
			retval = -EFAULT;
			break;
		}
		if (vote_for_bus_bw((uint32_t *)param)) {
			IPAWANERR("Failed to vote for bus BW\n");
			retval = -EFAULT;
			break;
		}
		if (copy_to_user((u8 *)arg, param, pyld_sz)) {
			retval = -EFAULT;
			break;
		}
		break;

	case WAN_IOC_POLL_TETHERING_STATS:
		IPAWANDBG("device %s got WAN_IOCTL_POLL_TETHERING_STATS :>>>\n",
			  DRIVER_NAME);
		pyld_sz = sizeof(struct wan_ioctl_poll_tethering_stats);
		param = kzalloc(pyld_sz, GFP_KERNEL);
		if (!param) {
			retval = -ENOMEM;
			break;
		}
		if (copy_from_user(param, (u8 *)arg, pyld_sz)) {
			retval = -EFAULT;
			break;
		}
		if (rmnet_ipa_poll_tethering_stats(
		(struct wan_ioctl_poll_tethering_stats *)param)) {
			IPAWANERR("WAN_IOCTL_POLL_TETHERING_STATS failed\n");
			retval = -EFAULT;
			break;
		}
		if (copy_to_user((u8 *)arg, param, pyld_sz)) {
			retval = -EFAULT;
			break;
		}
		break;

	case WAN_IOC_SET_DATA_QUOTA:
		IPAWANDBG("device %s got WAN_IOCTL_SET_DATA_QUOTA :>>>\n",
			  DRIVER_NAME);
		pyld_sz = sizeof(struct wan_ioctl_set_data_quota);
		param = kzalloc(pyld_sz, GFP_KERNEL);
		if (!param) {
			retval = -ENOMEM;
			break;
		}
		if (copy_from_user(param, (u8 *)arg, pyld_sz)) {
			retval = -EFAULT;
			break;
		}
		if (rmnet_ipa_set_data_quota(
		(struct wan_ioctl_set_data_quota *)param)) {
			IPAWANERR("WAN_IOC_SET_DATA_QUOTA failed\n");
			retval = -EFAULT;
			break;
		}
		if (copy_to_user((u8 *)arg, param, pyld_sz)) {
			retval = -EFAULT;
			break;
		}
		break;

	default:
		retval = -ENOTTY;
	}
	kfree(param);
	return retval;
}
static int qmi_init_modem_send_sync_msg(void)
{
	struct ipa_init_modem_driver_req_msg_v01 req;
	struct ipa_init_modem_driver_resp_msg_v01 resp;
	struct msg_desc req_desc, resp_desc;
	int rc;
	u16 smem_restr_bytes = ipa_get_smem_restr_bytes();

	memset(&req, 0, sizeof(struct ipa_init_modem_driver_req_msg_v01));
	memset(&resp, 0, sizeof(struct ipa_init_modem_driver_resp_msg_v01));
	req.platform_type_valid = true;
	req.platform_type = ipa_wan_platform;
	req.hdr_tbl_info_valid = true;
	req.hdr_tbl_info.modem_offset_start =
		IPA_MEM_PART(modem_hdr_ofst) + smem_restr_bytes;
	req.hdr_tbl_info.modem_offset_end = IPA_MEM_PART(modem_hdr_ofst) +
		smem_restr_bytes + IPA_MEM_PART(modem_hdr_size) - 1;
	req.v4_route_tbl_info_valid = true;
	req.v4_route_tbl_info.route_tbl_start_addr = IPA_MEM_PART(v4_rt_ofst) +
		smem_restr_bytes;
	req.v4_route_tbl_info.num_indices = IPA_MEM_PART(v4_modem_rt_index_hi);
	req.v6_route_tbl_info_valid = true;
	req.v6_route_tbl_info.route_tbl_start_addr = IPA_MEM_PART(v6_rt_ofst) +
		smem_restr_bytes;
	req.v6_route_tbl_info.num_indices = IPA_MEM_PART(v6_modem_rt_index_hi);
	req.v4_filter_tbl_start_addr_valid = true;
	req.v4_filter_tbl_start_addr =
		IPA_MEM_PART(v4_flt_ofst) + smem_restr_bytes;
	req.v6_filter_tbl_start_addr_valid = true;
	req.v6_filter_tbl_start_addr =
		IPA_MEM_PART(v6_flt_ofst) + smem_restr_bytes;
	req.modem_mem_info_valid = true;
	req.modem_mem_info.block_start_addr =
		IPA_MEM_PART(modem_ofst) + smem_restr_bytes;
	req.modem_mem_info.size = IPA_MEM_PART(modem_size);
	req.ctrl_comm_dest_end_pt_valid = true;
	req.ctrl_comm_dest_end_pt =
		ipa_get_ep_mapping(IPA_CLIENT_APPS_WAN_CONS);
	req.hdr_proc_ctx_tbl_info_valid = true;
	req.hdr_proc_ctx_tbl_info.modem_offset_start =
		IPA_MEM_PART(modem_hdr_proc_ctx_ofst) + smem_restr_bytes;
	req.hdr_proc_ctx_tbl_info.modem_offset_end =
		IPA_MEM_PART(modem_hdr_proc_ctx_ofst) +
		IPA_MEM_PART(modem_hdr_proc_ctx_size) + smem_restr_bytes - 1;
	if (is_load_uc) {  /* First time boot */
		req.is_ssr_bootup_valid = false;
		req.is_ssr_bootup = 0;
	} else {  /* After SSR boot */
		req.is_ssr_bootup_valid = true;
		req.is_ssr_bootup = 1;
	}

	IPAWANDBG("platform_type %d\n", req.platform_type);
	IPAWANDBG("hdr_tbl_info.modem_offset_start %d\n",
			req.hdr_tbl_info.modem_offset_start);
	IPAWANDBG("hdr_tbl_info.modem_offset_end %d\n",
			req.hdr_tbl_info.modem_offset_end);
	IPAWANDBG("v4_route_tbl_info.route_tbl_start_addr %d\n",
			req.v4_route_tbl_info.route_tbl_start_addr);
	IPAWANDBG("v4_route_tbl_info.num_indices %d\n",
			req.v4_route_tbl_info.num_indices);
	IPAWANDBG("v6_route_tbl_info.route_tbl_start_addr %d\n",
			req.v6_route_tbl_info.route_tbl_start_addr);
	IPAWANDBG("v6_route_tbl_info.num_indices %d\n",
			req.v6_route_tbl_info.num_indices);
	IPAWANDBG("v4_filter_tbl_start_addr %d\n",
			req.v4_filter_tbl_start_addr);
	IPAWANDBG("v6_filter_tbl_start_addr %d\n",
			req.v6_filter_tbl_start_addr);
	IPAWANDBG("modem_mem_info.block_start_addr %d\n",
			req.modem_mem_info.block_start_addr);
	IPAWANDBG("modem_mem_info.size %d\n",
			req.modem_mem_info.size);
	IPAWANDBG("ctrl_comm_dest_end_pt %d\n",
			req.ctrl_comm_dest_end_pt);
	IPAWANDBG("is_ssr_bootup %d\n",
			req.is_ssr_bootup);

	req_desc.max_msg_len = QMI_IPA_INIT_MODEM_DRIVER_REQ_MAX_MSG_LEN_V01;
	req_desc.msg_id = QMI_IPA_INIT_MODEM_DRIVER_REQ_V01;
	req_desc.ei_array = ipa_init_modem_driver_req_msg_data_v01_ei;

	resp_desc.max_msg_len = QMI_IPA_INIT_MODEM_DRIVER_RESP_MAX_MSG_LEN_V01;
	resp_desc.msg_id = QMI_IPA_INIT_MODEM_DRIVER_RESP_V01;
	resp_desc.ei_array = ipa_init_modem_driver_resp_msg_data_v01_ei;

	pr_info("Sending QMI_IPA_INIT_MODEM_DRIVER_REQ_V01\n");
	rc = qmi_send_req_wait(ipa_q6_clnt, &req_desc, &req, sizeof(req),
			&resp_desc, &resp, sizeof(resp),
			QMI_SEND_REQ_TIMEOUT_MS);
	pr_info("QMI_IPA_INIT_MODEM_DRIVER_REQ_V01 response received\n");
	return ipa_check_qmi_response(rc,
		QMI_IPA_INIT_MODEM_DRIVER_REQ_V01, resp.resp.result,
		resp.resp.error, "ipa_init_modem_driver_resp_msg_v01");
}