Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 59b129d7 authored by Skylar Chang's avatar Skylar Chang
Browse files

msm: ipa3: add support on mhi-prime



Add the support for mhi-prime to not
start ipa-qmi service on AP-side and
register mhi prime pipes in IPA.

Change-Id: I87d588ca9b8880ef062c07ebf44ca4b790c139db
Signed-off-by: default avatarSkylar Chang <chiaweic@codeaurora.org>
parent 412cab4c
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -2496,6 +2496,8 @@ int ipa3_teth_bridge_disconnect(enum ipa_client_type client);

int ipa3_teth_bridge_connect(struct teth_bridge_connect_params *connect_params);

int ipa3_teth_bridge_get_pm_hdl(void);

/*
 * Tethering client info
 */
@@ -2972,4 +2974,6 @@ static inline int ipa_mpm_panic_handler(char *buf, int size)

#endif /* CONFIG_IPA3_MHI_PRIME_MANAGER */

/* query ipa APQ mode*/
bool ipa3_is_apq(void);
#endif /* _IPA3_I_H_ */
+353 −17
Original line number Diff line number Diff line
@@ -57,6 +57,40 @@ struct ipa_msg_desc {
	struct qmi_elem_info *ei_array;
};

static struct ipa_mhi_prime_aggr_info_req_msg_v01 aggr_req = {
	.aggr_info_valid = 1,
	.aggr_info_len = 5,
	.aggr_info[0] = {
		.ic_type = DATA_IC_TYPE_MHI_PRIME_V01,
		.ep_type = DATA_EP_DESC_TYPE_DPL_PROD_V01,
		.bytes_count = 16,
	},
	.aggr_info[1] = {
		.ic_type = DATA_IC_TYPE_MHI_PRIME_V01,
		.ep_type = DATA_EP_DESC_TYPE_TETH_CONS_V01,
		.bytes_count = 24,
		.aggr_type = DATA_AGGR_TYPE_QMAPv5_V01,
	},
	.aggr_info[2] = {
		.ic_type = DATA_IC_TYPE_MHI_PRIME_V01,
		.ep_type = DATA_EP_DESC_TYPE_TETH_PROD_V01,
		.bytes_count = 16,
		.aggr_type = DATA_AGGR_TYPE_QMAPv5_V01,
	},
	.aggr_info[3] = {
		.ic_type = DATA_IC_TYPE_MHI_PRIME_V01,
		.ep_type = DATA_EP_DESC_TYPE_TETH_RMNET_CONS_V01,
		.bytes_count = 31,
		.aggr_type = DATA_AGGR_TYPE_QMAPv5_V01,
	},
	.aggr_info[4] = {
		.ic_type = DATA_IC_TYPE_MHI_PRIME_V01,
		.ep_type = DATA_EP_DESC_TYPE_TETH_RMNET_PROD_V01,
		.bytes_count = 31,
		.aggr_type = DATA_AGGR_TYPE_QMAPv5_V01,
	},
};

/* QMI A5 service */

static void ipa3_handle_indication_req(struct qmi_handle *qmi_handle,
@@ -798,6 +832,244 @@ int ipa3_qmi_filter_request_ex_send(
		resp.resp.error, "ipa_install_filter");
}

/* sending add offload-connection-request to modem*/
int ipa3_qmi_add_offload_request_send(
	struct ipa_add_offload_connection_req_msg_v01 *req)
{
	struct ipa_add_offload_connection_resp_msg_v01 resp;
	struct ipa_msg_desc req_desc, resp_desc;
	int rc = 0;
	int i, j;
	uint32_t id;

	/* check if modem up */
	if (!ipa3_qmi_modem_init_fin ||
		!ipa_q6_clnt) {
		IPAWANDBG("modem QMI haven't up yet\n");
		return -EINVAL;
	}

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

	/* currently set total max to 64 */
	if (req->filter_spec_ex2_list_len +
		ipa3_qmi_ctx->num_ipa_offload_connection
		>= QMI_IPA_MAX_FILTERS_V01) {
		IPAWANDBG(
		"cur(%d), req(%d), exceed limit (%d)\n",
			ipa3_qmi_ctx->num_ipa_offload_connection,
			req->filter_spec_ex2_list_len,
			QMI_IPA_MAX_FILTERS_V01);
		return -EINVAL;
	}

	for (i = 0; i < req->filter_spec_ex2_list_len; i++) {
		if ((req->filter_spec_ex2_list[i].ip_type !=
			QMI_IPA_IP_TYPE_V4_V01) &&
			(req->filter_spec_ex2_list[i].ip_type !=
			QMI_IPA_IP_TYPE_V6_V01))
			return -EINVAL;
		if (req->filter_spec_ex2_list[i].is_mux_id_valid == false)
			return -EINVAL;
		if ((req->filter_spec_ex2_list[i].filter_action <=
			QMI_IPA_FILTER_ACTION_INVALID_V01) ||
			(req->filter_spec_ex2_list[i].filter_action >
			QMI_IPA_FILTER_ACTION_EXCEPTION_V01))
			return -EINVAL;
	}

	req_desc.max_msg_len =
		IPA_ADD_OFFLOAD_CONNECTION_REQ_MSG_V01_MAX_MSG_LEN;
	req_desc.msg_id = QMI_IPA_ADD_OFFLOAD_CONNECTION_REQ_V01;
	req_desc.ei_array = ipa_add_offload_connection_req_msg_v01_ei;

	memset(&resp, 0, sizeof(struct
		ipa_add_offload_connection_resp_msg_v01));
	resp_desc.max_msg_len =
		IPA_ADD_OFFLOAD_CONNECTION_RESP_MSG_V01_MAX_MSG_LEN;
	resp_desc.msg_id = QMI_IPA_ADD_OFFLOAD_CONNECTION_RESP_V01;
	resp_desc.ei_array = ipa_add_offload_connection_resp_msg_v01_ei;

	rc = ipa3_qmi_send_req_wait(ipa_q6_clnt,
		&req_desc, req,
		&resp_desc, &resp,
		QMI_SEND_REQ_TIMEOUT_MS);

	if (rc < 0) {
		IPAWANERR("QMI send Req %d failed, rc= %d\n",
			QMI_IPA_ADD_OFFLOAD_CONNECTION_REQ_V01,
			rc);
		return rc;
	}

	rc = ipa3_check_qmi_response(rc,
		QMI_IPA_ADD_OFFLOAD_CONNECTION_REQ_V01, resp.resp.result,
		resp.resp.error, "ipa_add_offload_connection");

	if (rc) {
		IPAWANERR("QMI get Response %d failed, rc= %d\n",
			QMI_IPA_ADD_OFFLOAD_CONNECTION_REQ_V01,
			rc);
		return rc;
	}

	/* Check & copy rule-handle */
	if (!resp.filter_handle_list_valid) {
		IPAWANERR("QMI resp invalid %d failed\n",
			resp.filter_handle_list_valid);
		return -ERANGE;
	}

	if (resp.filter_handle_list_len !=
		req->filter_spec_ex2_list_len) {
		IPAWANERR("QMI resp invalid size %d req %d\n",
			resp.filter_handle_list_len,
			req->filter_spec_ex2_list_len);
		return -ERANGE;
	}

	mutex_lock(&ipa3_qmi_lock);
	for (i = 0; i < req->filter_spec_ex2_list_len; i++) {
		id = resp.filter_handle_list[i].filter_spec_identifier;
		/* check rule-id matched or not */
		if (req->filter_spec_ex2_list[i].rule_id !=
			id) {
			IPAWANERR("QMI error (%d)st-(%d) rule-id (%d)\n",
				i,
				id,
				req->filter_spec_ex2_list[i].rule_id);
			mutex_unlock(&ipa3_qmi_lock);
			return -EINVAL;
		}
		/* find free spot*/
		for (j = 0; j < QMI_IPA_MAX_FILTERS_V01; j++) {
			if (ipa3_qmi_ctx->ipa_offload_cache[j].valid == false)
				break;
		}

		if (j == QMI_IPA_MAX_FILTERS_V01) {
			IPAWANERR("can't find free spot for rule-id %d\n",
				id);
			mutex_unlock(&ipa3_qmi_lock);
			return -EINVAL;
		}

		/* save rule-id handle to cache */
		ipa3_qmi_ctx->ipa_offload_cache[j].rule_id =
			resp.filter_handle_list[i].filter_spec_identifier;
		ipa3_qmi_ctx->ipa_offload_cache[j].rule_hdl =
			resp.filter_handle_list[i].filter_handle;
		ipa3_qmi_ctx->ipa_offload_cache[j].valid = true;
		ipa3_qmi_ctx->ipa_offload_cache[j].ip_type =
			req->filter_spec_ex2_list[i].ip_type;
		ipa3_qmi_ctx->num_ipa_offload_connection++;
	}
	mutex_unlock(&ipa3_qmi_lock);
	IPAWANDBG("Update cached conntrack entries (%d)\n",
		ipa3_qmi_ctx->num_ipa_offload_connection);
	return rc;
}

/* sending rmv offload-connection-request to modem*/
int ipa3_qmi_rmv_offload_request_send(
	struct ipa_remove_offload_connection_req_msg_v01 *req)
{
	struct ipa_remove_offload_connection_resp_msg_v01 resp;
	struct ipa_msg_desc req_desc, resp_desc;
	int rc = 0;
	int i, j;
	uint32_t id;

	/* check if modem up */
	if (!ipa3_qmi_modem_init_fin ||
		!ipa_q6_clnt) {
		IPAWANDBG("modem QMI haven't up yet\n");
		return -EINVAL;
	}

	/* check if the # of handles from IPACM is valid */
	if (req->filter_handle_list_len == 0) {
		IPAWANDBG("IPACM deleted zero rules !\n");
		return -EINVAL;
	}

	IPAWANDBG("IPACM pass (%d) rules handles to Q6, cur (%d)\n",
	req->filter_handle_list_len,
	ipa3_qmi_ctx->num_ipa_offload_connection);

	/*  max as num_ipa_offload_connection */
	if (req->filter_handle_list_len >=
		ipa3_qmi_ctx->num_ipa_offload_connection) {
		IPAWANDBG(
		"cur(%d), req_rmv(%d)\n",
			ipa3_qmi_ctx->num_ipa_offload_connection,
			req->filter_handle_list_len);
		return -EINVAL;
	}

	mutex_lock(&ipa3_qmi_lock);
	for (i = 0; i < req->filter_handle_list_len; i++) {
		/* check if rule-id match */
		id =
			req->filter_handle_list[i].filter_spec_identifier;
		for (j = 0; j < QMI_IPA_MAX_FILTERS_V01; j++) {
			if ((ipa3_qmi_ctx->ipa_offload_cache[j].valid) &&
				(ipa3_qmi_ctx->ipa_offload_cache[j].rule_id ==
				id))
				break;
		}
		if (j == QMI_IPA_MAX_FILTERS_V01) {
			IPAWANERR("can't find rule-id %d\n",
				id);
			mutex_unlock(&ipa3_qmi_lock);
			return -EINVAL;
		}

		/* fill up the filter_handle */
		req->filter_handle_list[i].filter_handle =
			ipa3_qmi_ctx->ipa_offload_cache[j].rule_hdl;
		ipa3_qmi_ctx->ipa_offload_cache[j].valid == false;
		ipa3_qmi_ctx->num_ipa_offload_connection--;
	}
	mutex_unlock(&ipa3_qmi_lock);

	req_desc.max_msg_len =
		IPA_REMOVE_OFFLOAD_CONNECTION_REQ_MSG_V01_MAX_MSG_LEN;
	req_desc.msg_id = QMI_IPA_REMOVE_OFFLOAD_CONNECTION_REQ_V01;
	req_desc.ei_array = ipa_remove_offload_connection_req_msg_v01_ei;

	memset(&resp, 0, sizeof(struct
		ipa_remove_offload_connection_resp_msg_v01));
	resp_desc.max_msg_len =
		IPA_REMOVE_OFFLOAD_CONNECTION_RESP_MSG_V01_MAX_MSG_LEN;
	resp_desc.msg_id = QMI_IPA_REMOVE_OFFLOAD_CONNECTION_RESP_V01;
	resp_desc.ei_array = ipa_remove_offload_connection_resp_msg_v01_ei;

	rc = ipa3_qmi_send_req_wait(ipa_q6_clnt,
		&req_desc, req,
		&resp_desc, &resp,
		QMI_SEND_REQ_TIMEOUT_MS);

	if (rc < 0) {
		IPAWANERR("QMI send Req %d failed, rc= %d\n",
			QMI_IPA_REMOVE_OFFLOAD_CONNECTION_REQ_V01,
			rc);
		return rc;
	}
	IPAWANDBG("left cached conntrack entries (%d)\n",
		ipa3_qmi_ctx->num_ipa_offload_connection);

	return ipa3_check_qmi_response(rc,
		QMI_IPA_REMOVE_OFFLOAD_CONNECTION_REQ_V01, resp.resp.result,
		resp.resp.error, "ipa_rmv_offload_connection");
}

/* sending ul-filter-install-request to modem*/
int ipa3_qmi_ul_filter_request_send(
	struct ipa_configure_ul_firewall_rules_req_msg_v01 *req)
@@ -1159,7 +1431,9 @@ static void ipa3_q6_clnt_svc_arrive(struct work_struct *work)

	IPAWANDBG("Q6 QMI service available now\n");
	if (ipa3_ctx->platform_type == IPA_PLAT_TYPE_APQ) {
		IPAWANDBG("Dun send QMI msg to modem\n");
		ipa3_qmi_modem_init_fin = true;
		IPAWANDBG("QMI-client complete, ipa3_qmi_modem_init_fin : %d\n",
			ipa3_qmi_modem_init_fin);
		return;
	}

@@ -1169,7 +1443,7 @@ static void ipa3_q6_clnt_svc_arrive(struct work_struct *work)
	if ((rc == -ENETRESET) || (rc == -ENODEV)) {
		IPAWANERR(
		"ipa3_qmi_init_modem_send_sync_msg failed due to SSR!\n");
		/* Cleanup will take place when ipa3_wwan_remove is called */
		/* Cleanup when ipa3_wwan_remove is called */
		vfree(ipa_q6_clnt);
		ipa_q6_clnt = NULL;
		return;
@@ -1179,12 +1453,12 @@ static void ipa3_q6_clnt_svc_arrive(struct work_struct *work)
		IPAWANERR("ipa3_qmi_init_modem_send_sync_msg failed\n");
		/*
		 * Hardware not responding.
		* This is a very unexpected scenario, which requires a kernel
		* panic in order to force dumps for QMI/Q6 side analysis.
		 * This is a very unexpected scenario
		 * which requires a kernel panic in
		 * order to force dumps for QMI/Q6 side analysis.
		 */
		BUG();
	}

	ipa3_qmi_modem_init_fin = true;

	if ((ipa3_modem_init_cmplt == true) &&
@@ -1375,19 +1649,26 @@ static void ipa3_qmi_service_init_worker(struct work_struct *work)
{
	int rc;

	/* Initialize QMI-service*/
	IPAWANDBG("IPA A7 QMI init OK :>>>>\n");

	/* start the QMI msg cache */
	ipa3_qmi_ctx = vzalloc(sizeof(*ipa3_qmi_ctx));
	if (!ipa3_qmi_ctx) {
		IPAWANERR("Failed to allocate the memory to ipa3_qmi_ctx\n");
		IPAWANERR("Failed to allocate ipa3_qmi_ctx\n");
		return;
	}

	if (ipa3_is_apq()) {
		/* Only start QMI-client */
		IPAWANDBG("Only start IPA A7 QMI client\n");
		goto qmi_client_start;
	}

	/* Initialize QMI-service*/
	IPAWANDBG("IPA A7 QMI init OK :>>>>\n");

	ipa3_qmi_ctx->modem_cfg_emb_pipe_flt =
		ipa3_get_modem_cfg_emb_pipe_flt();

	ipa3_qmi_ctx->num_ipa_offload_connection = 0;
	ipa3_svc_handle = vzalloc(sizeof(*ipa3_svc_handle));

	if (!ipa3_svc_handle)
@@ -1414,6 +1695,7 @@ static void ipa3_qmi_service_init_worker(struct work_struct *work)
		goto deregister_qmi_srv;
	}

qmi_client_start:
	/* Initialize QMI-client */
	ipa_clnt_req_workqueue = create_singlethread_workqueue("clnt_req");
	if (!ipa_clnt_req_workqueue) {
@@ -1460,14 +1742,17 @@ static void ipa3_qmi_service_init_worker(struct work_struct *work)
	destroy_workqueue(ipa_clnt_req_workqueue);
	ipa_clnt_req_workqueue = NULL;
deregister_qmi_srv:
	if (!ipa3_is_apq())
		qmi_handle_release(ipa3_svc_handle);
destroy_qmi_handle:
	vfree(ipa3_qmi_ctx);
destroy_ipa_A7_svc_wq:
	if (!ipa3_is_apq()) {
		vfree(ipa3_svc_handle);
	ipa3_qmi_ctx = NULL;
		ipa3_svc_handle = NULL;
	}
	ipa3_qmi_ctx = NULL;
}

int ipa3_qmi_service_init(uint32_t wan_platform_type)
{
@@ -1671,6 +1956,57 @@ int ipa3_qmi_set_data_quota(struct ipa_set_data_usage_quota_req_msg_v01 *req)
		resp.resp.error, "ipa_set_data_usage_quota_req_msg_v01");
}

int ipa3_qmi_set_aggr_info(enum ipa_aggr_enum_type_v01 aggr_enum_type)
{
	struct ipa_mhi_prime_aggr_info_resp_msg_v01 resp;
	struct ipa_msg_desc req_desc, resp_desc;
	int rc;

	IPAWANDBG("sending aggr_info_request\n");

	/* replace to right qmap format */
	aggr_req.aggr_info[1].aggr_type = aggr_enum_type;
	aggr_req.aggr_info[2].aggr_type = aggr_enum_type;
	aggr_req.aggr_info[2].pkt_count = 1; /*disable aggregation */
	aggr_req.aggr_info[3].aggr_type = aggr_enum_type;
	aggr_req.aggr_info[4].aggr_type = aggr_enum_type;

	memset(&resp, 0, sizeof(struct ipa_mhi_prime_aggr_info_resp_msg_v01));

	req_desc.max_msg_len = IPA_MHI_PRIME_AGGR_INFO_REQ_MSG_V01_MAX_MSG_LEN;
	req_desc.msg_id = QMI_IPA_MHI_PRIME_AGGR_INFO_REQ_V01;
	req_desc.ei_array = ipa_mhi_prime_aggr_info_req_msg_v01_ei;

	resp_desc.max_msg_len =
		IPA_MHI_PRIME_AGGR_INFO_RESP_MSG_V01_MAX_MSG_LEN;
	resp_desc.msg_id = QMI_IPA_MHI_PRIME_AGGR_INFO_RESP_V01;
	resp_desc.ei_array = ipa_mhi_prime_aggr_info_resp_msg_v01_ei;

	IPAWANDBG("Sending QMI_IPA_MHI_PRIME_AGGR_INFO_REQ_V01(%d)\n",
		aggr_enum_type);
	if (unlikely(!ipa_q6_clnt)) {
		IPAWANERR(" ipa_q6_clnt not initialized\n");
		return -ETIMEDOUT;
	}
	rc = ipa3_qmi_send_req_wait(ipa_q6_clnt,
		&req_desc, &aggr_req,
		&resp_desc, &resp,
		QMI_SEND_STATS_REQ_TIMEOUT_MS);

	if (rc < 0) {
		IPAWANERR("QMI send Req %d failed, rc= %d\n",
			QMI_IPA_SET_DATA_USAGE_QUOTA_REQ_V01,
			rc);
		return rc;
	}

	IPAWANDBG_LOW("QMI_IPA_MHI_PRIME_AGGR_INFO_RESP_V01 received\n");

	return ipa3_check_qmi_response(rc,
		QMI_IPA_SET_DATA_USAGE_QUOTA_REQ_V01, resp.resp.result,
		resp.resp.error, "ipa_mhi_prime_aggr_info_req_msg_v01");
}

int ipa3_qmi_stop_data_qouta(void)
{
	struct ipa_stop_data_usage_quota_req_msg_v01 req;
+49 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#define IPA_DFLT_WAN_RT_TBL_NAME "ipa_dflt_wan_rt"
#define MAX_NUM_Q6_RULE 35
#define MAX_NUM_QMI_RULE_CACHE 10
#define MAX_NUM_QMI_MPM_AGGR_CACHE 3
#define DEV_NAME "ipa-wan"
#define SUBSYS_LOCAL_MODEM "modem"
#define SUBSYS_REMOTE_MODEM "esoc0"
@@ -83,6 +84,13 @@

extern struct ipa3_qmi_context *ipa3_qmi_ctx;

struct ipa_offload_connection_val {
	enum ipa_ip_type_enum_v01 ip_type;
	bool valid;
	uint32_t rule_id;
	uint32_t  rule_hdl;
};

struct ipa3_qmi_context {
	struct ipa_ioc_ext_intf_prop q6_ul_filter_rule[MAX_NUM_Q6_RULE];
	u32 q6_ul_filter_rule_hdl[MAX_NUM_Q6_RULE];
@@ -99,9 +107,15 @@ struct ipa3_qmi_context {
	struct ipa_configure_ul_firewall_rules_req_msg_v01
		ipa_configure_ul_firewall_rules_req_msg_cache
			[MAX_NUM_QMI_RULE_CACHE];
	struct ipa_mhi_prime_aggr_info_req_msg_v01
		ipa_mhi_prime_aggr_info_req_msg_cache
			[MAX_NUM_QMI_MPM_AGGR_CACHE];
	bool modem_cfg_emb_pipe_flt;
	struct sockaddr_qrtr client_sq;
	struct sockaddr_qrtr server_sq;
	int num_ipa_offload_connection;
	struct ipa_offload_connection_val
		ipa_offload_cache[QMI_IPA_MAX_FILTERS_V01];
};

struct ipa3_rmnet_mux_val {
@@ -196,6 +210,14 @@ extern struct qmi_elem_info ipa_mhi_clk_vote_resp_msg_v01_ei[];
extern struct qmi_elem_info ipa_mhi_cleanup_req_msg_v01_ei[];
extern struct qmi_elem_info ipa_mhi_cleanup_resp_msg_v01_ei[];

extern struct qmi_elem_info ipa_endp_desc_indication_msg_v01_ei[];
extern struct qmi_elem_info ipa_mhi_prime_aggr_info_req_msg_v01_ei[];
extern struct qmi_elem_info ipa_mhi_prime_aggr_info_resp_msg_v01_ei[];
extern struct qmi_elem_info ipa_add_offload_connection_req_msg_v01_ei[];
extern struct qmi_elem_info ipa_add_offload_connection_resp_msg_v01_ei[];
extern struct qmi_elem_info ipa_remove_offload_connection_req_msg_v01_ei[];
extern struct qmi_elem_info ipa_remove_offload_connection_resp_msg_v01_ei[];

/**
 * struct ipa3_rmnet_context - IPA rmnet context
 * @ipa_rmnet_ssr: support modem SSR
@@ -223,6 +245,12 @@ int ipa3_qmi_filter_request_send(
int ipa3_qmi_filter_request_ex_send(
	struct ipa_install_fltr_rule_req_ex_msg_v01 *req);

int ipa3_qmi_add_offload_request_send(
	struct ipa_add_offload_connection_req_msg_v01 *req);

int ipa3_qmi_rmv_offload_request_send(
	struct ipa_remove_offload_connection_req_msg_v01 *req);

int ipa3_qmi_ul_filter_request_send(
	struct ipa_configure_ul_firewall_rules_req_msg_v01 *req);

@@ -294,6 +322,9 @@ int ipa3_qmi_get_network_stats(struct ipa_get_apn_data_stats_req_msg_v01 *req,

int ipa3_qmi_set_data_quota(struct ipa_set_data_usage_quota_req_msg_v01 *req);

int ipa3_qmi_set_aggr_info(
	enum ipa_aggr_enum_type_v01 aggr_enum_type);

int ipa3_qmi_stop_data_qouta(void);

void ipa3_q6_handshake_complete(bool ssr_bootup);
@@ -334,6 +365,18 @@ static inline int ipa3_qmi_filter_request_send(
	return -EPERM;
}

static inline int ipa3_qmi_add_offload_request_send(
	struct ipa_add_offload_connection_req_msg_v01 *req)
{
	return -EPERM;
}

static inline int ipa3_qmi_rmv_offload_request_send(
	struct ipa_rmv_offload_connection_req_msg_v01 *req)
{
	return -EPERM;
}

static inline int ipa3_qmi_ul_filter_request_send(
	struct ipa_configure_ul_firewall_rules_req_msg_v01 *req)
{
@@ -467,6 +510,12 @@ static inline int ipa3_qmi_get_per_client_packet_stats(
	return -EPERM;
}

static inline int ipa3_qmi_set_aggr_info(
	enum ipa_aggr_enum_type_v01 aggr_enum_type)
{
	return -EPERM;
}

static inline void ipa3_qmi_init(void)
{

+14 −0
Original line number Diff line number Diff line
@@ -7942,6 +7942,20 @@ void ipa3_read_mailbox_17(enum uc_state state)
	}
}

/**
 * ipa3_is_apq() - indicate apq platform or not
 *
 * Return value: true if apq, false if not apq platform
 *
 */
bool ipa3_is_apq(void)
{
	if (ipa3_ctx->platform_type == IPA_PLAT_TYPE_APQ)
		return true;
	else
		return false;
}

/**
 * ipa3_disable_prefetch() - disable\enable tx prefetch
 *
+115 −35
Original line number Diff line number Diff line
@@ -169,6 +169,8 @@ struct rmnet_ipa3_context {
		[IPACM_MAX_CLIENT_DEVICE_TYPES];
	bool dl_csum_offload_enabled;
	atomic_t ap_suspend;
	bool ipa_config_is_apq;
	bool ipa_mhi_aggr_formet_set;
};

static struct rmnet_ipa3_context *rmnet_ipa3_ctx;
@@ -339,9 +341,11 @@ static int ipa3_add_qmap_hdr(uint32_t mux_id, uint32_t *hdr_hdl)
	 strlcpy(hdr_entry->name, hdr_name,
				IPA_RESOURCE_NAME_MAX);

	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5 &&
		rmnet_ipa3_ctx->dl_csum_offload_enabled) {
		hdr_entry->hdr_len = IPA_DL_CHECKSUM_LENGTH; /* 8 bytes */
	if (rmnet_ipa3_ctx->dl_csum_offload_enabled) {
		if (rmnet_ipa3_ctx->ipa_config_is_apq ||
			ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) {
			hdr_entry->hdr_len =
				IPA_DL_CHECKSUM_LENGTH; /* 8 bytes */
			/* new DL QMAP header format */
			hdr_entry->hdr[0] = 0x40;
			hdr_entry->hdr[1] = (uint8_t) mux_id;
@@ -349,12 +353,18 @@ static int ipa3_add_qmap_hdr(uint32_t mux_id, uint32_t *hdr_hdl)
			hdr_entry->hdr[3] = 0;
			hdr_entry->hdr[4] = 0x4;
			/*
		 * Need to set csum required/valid bit on which will be replaced
		 * by HW if checksum is incorrect after validation
			 * Need to set csum required/valid bit on
			 * which will be replaced by HW if checksum
			 * is incorrect after validation
			 */
			hdr_entry->hdr[5] = 0x80;
			hdr_entry->hdr[6] = 0;
			hdr_entry->hdr[7] = 0;
		} else {
			hdr_entry->hdr_len =
				IPA_QMAP_HEADER_LENGTH; /* 4 bytes */
			hdr_entry->hdr[1] = (uint8_t) mux_id;
		}
	} else {
		hdr_entry->hdr_len = IPA_QMAP_HEADER_LENGTH; /* 4 bytes */
		hdr_entry->hdr[1] = (uint8_t) mux_id;
@@ -896,12 +906,18 @@ static int ipa3_wwan_register_to_ipa(int index)
	tx_properties.prop = tx_ioc_properties;
	tx_ipv4_property = &tx_properties.prop[0];
	tx_ipv4_property->ip = IPA_IP_v4;
	if (rmnet_ipa3_ctx->ipa_config_is_apq)
		tx_ipv4_property->dst_pipe = IPA_CLIENT_MHI_PRIME_TETH_CONS;
	else
		tx_ipv4_property->dst_pipe = IPA_CLIENT_APPS_WAN_CONS;
	snprintf(tx_ipv4_property->hdr_name, IPA_RESOURCE_NAME_MAX, "%s%d",
		 A2_MUX_HDR_NAME_V4_PREF,
		 rmnet_ipa3_ctx->mux_channel[index].mux_id);
	tx_ipv6_property = &tx_properties.prop[1];
	tx_ipv6_property->ip = IPA_IP_v6;
	if (rmnet_ipa3_ctx->ipa_config_is_apq)
		tx_ipv6_property->dst_pipe = IPA_CLIENT_MHI_PRIME_TETH_CONS;
	else
		tx_ipv6_property->dst_pipe = IPA_CLIENT_APPS_WAN_CONS;
	/* no need use A2_MUX_HDR_NAME_V6_PREF, same header */
	snprintf(tx_ipv6_property->hdr_name, IPA_RESOURCE_NAME_MAX, "%s%d",
@@ -916,6 +932,9 @@ static int ipa3_wwan_register_to_ipa(int index)
	rx_ipv4_property->attrib.meta_data =
		rmnet_ipa3_ctx->mux_channel[index].mux_id << WWAN_METADATA_SHFT;
	rx_ipv4_property->attrib.meta_data_mask = WWAN_METADATA_MASK;
	if (rmnet_ipa3_ctx->ipa_config_is_apq)
		rx_ipv4_property->src_pipe = IPA_CLIENT_MHI_PRIME_TETH_PROD;
	else
		rx_ipv4_property->src_pipe = IPA_CLIENT_APPS_WAN_PROD;
	rx_ipv6_property = &rx_properties.prop[1];
	rx_ipv6_property->ip = IPA_IP_v6;
@@ -923,16 +942,47 @@ static int ipa3_wwan_register_to_ipa(int index)
	rx_ipv6_property->attrib.meta_data =
		rmnet_ipa3_ctx->mux_channel[index].mux_id << WWAN_METADATA_SHFT;
	rx_ipv6_property->attrib.meta_data_mask = WWAN_METADATA_MASK;
	if (rmnet_ipa3_ctx->ipa_config_is_apq)
		rx_ipv6_property->src_pipe = IPA_CLIENT_MHI_PRIME_TETH_PROD;
	else
		rx_ipv6_property->src_pipe = IPA_CLIENT_APPS_WAN_PROD;
	rx_properties.num_props = 2;

	if (rmnet_ipa3_ctx->ipa_config_is_apq) {
		/* provide mux-id to ipacm in apq platform*/
		pyld_sz = sizeof(struct ipa_ioc_ext_intf_prop);
		ext_ioc_properties = kmalloc(pyld_sz, GFP_KERNEL);
		if (!ext_ioc_properties)
			return -ENOMEM;

		ext_properties.prop = ext_ioc_properties;
		ext_properties.num_props = 1;
		ext_properties.prop[0].mux_id =
			rmnet_ipa3_ctx->mux_channel[index].mux_id;
		ext_properties.prop[0].ip = IPA_IP_MAX;
		IPAWANDBG("ip: %d mux:%d\n",
			ext_properties.prop[0].ip,
			ext_properties.prop[0].mux_id);
		ret = ipa3_register_intf_ext(
			rmnet_ipa3_ctx->mux_channel[index].vchannel_name,
			&tx_properties,
			&rx_properties,
			&ext_properties);
		if (ret) {
			IPAWANERR("[%d]ipa3_register_intf failed %d\n",
				index,
				ret);
			goto fail;
		}
		goto end;
	}
	/* non apq case */
	pyld_sz = rmnet_ipa3_ctx->num_q6_rules *
	sizeof(struct ipa_ioc_ext_intf_prop);
	ext_ioc_properties = kmalloc(pyld_sz, GFP_KERNEL);
	if (!ext_ioc_properties)
		return -ENOMEM;


	ext_properties.prop = ext_ioc_properties;
	ext_properties.excp_pipe_valid = true;
	ext_properties.excp_pipe = IPA_CLIENT_APPS_WAN_CONS;
@@ -957,9 +1007,11 @@ static int ipa3_wwan_register_to_ipa(int index)
		&ext_properties);
	if (ret) {
		IPAWANERR("[%s]:ipa3_register_intf failed %d\n",
			rmnet_ipa3_ctx->mux_channel[index].vchannel_name, ret);
			rmnet_ipa3_ctx->mux_channel[index].vchannel_name,
				ret);
		goto fail;
	}
end:
	rmnet_ipa3_ctx->mux_channel[index].ul_flt_reg = true;
fail:
	kfree(ext_ioc_properties);
@@ -1154,7 +1206,7 @@ static int ipa3_wwan_xmit(struct sk_buff *skb, struct net_device *dev)
	struct ipa3_wwan_private *wwan_ptr = netdev_priv(dev);
	unsigned long flags;

	if (ipa3_ctx->platform_type == IPA_PLAT_TYPE_APQ) {
	if (rmnet_ipa3_ctx->ipa_config_is_apq) {
		IPAWANERR_RL("IPA embedded data on APQ platform\n");
		dev_kfree_skb_any(skb);
		dev->stats.tx_dropped++;
@@ -1502,7 +1554,24 @@ static int handle3_egress_format(struct net_device *dev,
	struct ipa_sys_connect_params *ipa_wan_ep_cfg;
	int ep_idx;

	IPAWANDBG("get RMNET_IOCTL_SET_EGRESS_DATA_FORMAT\n");
	IPAWANDBG("get RMNET_IOCTL_SET_EGRESS_DATA_FORMAT %x\n", e->u.data);

	/* in APQ platform, only get QMAP format */
	if (rmnet_ipa3_ctx->ipa_config_is_apq) {
		if ((e->u.data) & RMNET_IOCTL_EGRESS_FORMAT_CHECKSUM) {
			/* QMAPv5 */
			rmnet_ipa3_ctx->dl_csum_offload_enabled = false;
			/* send aggr_info_qmi */
			rc = ipa3_qmi_set_aggr_info(DATA_AGGR_TYPE_QMAP_V01);
		} else {
			/* QMAP */
			rmnet_ipa3_ctx->dl_csum_offload_enabled = false;
			/* send aggr_info_qmi */
			rc = ipa3_qmi_set_aggr_info(DATA_AGGR_TYPE_QMAP_V01);
		}
		rmnet_ipa3_ctx->ipa_mhi_aggr_formet_set = true;
		return rc;
	}

	ep_idx = ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_PROD);
	if (ep_idx == IPA_EP_NOT_ALLOCATED) {
@@ -1836,7 +1905,8 @@ static int ipa3_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
			/* check if UL filter rules coming*/
			v_name =
				ext_ioctl_data.u.rmnet_mux_val.vchannel_name;
			if (rmnet_ipa3_ctx->num_q6_rules != 0) {
			if (rmnet_ipa3_ctx->num_q6_rules != 0 ||
					(rmnet_ipa3_ctx->ipa_config_is_apq)) {
				mux_mutex_ptr =
					&rmnet_ipa3_ctx->add_mux_channel_lock;
				IPAWANERR_RL("dev(%s) register to IPA\n",
@@ -2144,12 +2214,17 @@ int ipa3_wwan_set_modem_perf_profile(int throughput)
{
	struct ipa_rm_perf_profile profile;
	int ret;
	int tether_bridge_handle = 0;

	if (ipa3_ctx->use_ipa_pm) {
		ret = ipa_pm_set_throughput(rmnet_ipa3_ctx->q6_pm_hdl,
		/* query rmnet-tethering handle */
		tether_bridge_handle = ipa3_teth_bridge_get_pm_hdl();
		if (tether_bridge_handle > 0) {
			/* only update with valid handle*/
			ret = ipa_pm_set_throughput(tether_bridge_handle,
				throughput);
		if (ret)
			return ret;
		}
		/* for TETH MODEM on softap/rndis */
		ret = ipa_pm_set_throughput(rmnet_ipa3_ctx->q6_teth_pm_hdl,
			throughput);
	} else {
@@ -2543,6 +2618,10 @@ static int ipa3_wwan_probe(struct platform_device *pdev)
	ret = get_ipa_rmnet_dts_configuration(pdev, &ipa3_rmnet_res);
	ipa3_rmnet_ctx.ipa_rmnet_ssr = ipa3_rmnet_res.ipa_rmnet_ssr;

	/* check if booting as mhi-prime */
	rmnet_ipa3_ctx->ipa_config_is_apq
		= ipa3_is_apq();

	ret = ipa3_init_q6_smem();
	if (ret) {
		IPAWANERR("ipa3_init_q6_smem failed\n");
@@ -2561,6 +2640,7 @@ static int ipa3_wwan_probe(struct platform_device *pdev)
	rmnet_ipa3_ctx->rmnet_index = 0;
	rmnet_ipa3_ctx->egress_set = false;
	rmnet_ipa3_ctx->a7_ul_flt_set = false;
	rmnet_ipa3_ctx->ipa_mhi_aggr_formet_set = false;
	for (i = 0; i < MAX_NUM_OF_MUX_CHANNEL; i++)
		memset(&rmnet_ipa3_ctx->mux_channel[i], 0,
				sizeof(struct ipa3_rmnet_mux_val));
@@ -2907,7 +2987,7 @@ static int ipa3_lcl_mdm_ssr_notifier_cb(struct notifier_block *this,
		return NOTIFY_DONE;
	}

	if (ipa3_ctx->platform_type == IPA_PLAT_TYPE_APQ) {
	if (rmnet_ipa3_ctx->ipa_config_is_apq) {
		IPAWANERR("Local modem SSR event=%lu on APQ platform\n",
			code);
		return NOTIFY_DONE;
@@ -2984,7 +3064,7 @@ static int ipa3_rmt_mdm_ssr_notifier_cb(struct notifier_block *this,
		return NOTIFY_DONE;
	}

	if (ipa3_ctx->platform_type != IPA_PLAT_TYPE_APQ) {
	if (!rmnet_ipa3_ctx->ipa_config_is_apq) {
		IPAWANERR("Remote mdm SSR event=%lu on non-APQ platform=%d\n",
			code, ipa3_ctx->platform_type);
		return NOTIFY_DONE;
@@ -4705,10 +4785,10 @@ static int __init ipa3_wwan_init(void)
		&ipa3_lcl_mdm_ssr_notifier);
	if (!IS_ERR(ssr_hdl))
		rmnet_ipa3_ctx->lcl_mdm_subsys_notify_handle = ssr_hdl;
	else if (ipa3_ctx->platform_type != IPA_PLAT_TYPE_APQ)
	else if (!rmnet_ipa3_ctx->ipa_config_is_apq)
		return (int)PTR_ERR(ssr_hdl);

	if (ipa3_ctx->platform_type == IPA_PLAT_TYPE_APQ) {
	if (rmnet_ipa3_ctx->ipa_config_is_apq) {
		/* Register for Remote Modem SSR */
		ssr_hdl = subsys_notif_register_notifier(SUBSYS_REMOTE_MODEM,
			&ipa3_rmt_mdm_ssr_notifier);
Loading