Преглед на файлове

msm: IPA: Adding ULSO feature.

This is a new feature starting from IPA 5.0.
ULSO - uplink segmentation offload implements
HW IP packets segmentation.

Change-Id: I1d0b70eeb323e4a52c582b5d5d0017817bd14944
Acked-by: Eliad Ben Yishay <[email protected]>
Signed-off-by: Amir Levy <[email protected]>
Amir Levy преди 4 години
родител
ревизия
1d3d561cdd

+ 3 - 0
drivers/platform/msm/ipa/ipa_common_i.h

@@ -832,4 +832,7 @@ int ipa_eth_client_conn_evt(struct ipa_ecm_msg *msg);
 
 int ipa_eth_client_disconn_evt(struct ipa_ecm_msg *msg);
 
+/* ULSO mode Query */
+bool ipa3_is_ulso_supported(void);
+
 #endif /* _IPA_COMMON_I_H_ */

+ 51 - 0
drivers/platform/msm/ipa/ipa_v3/ipa.c

@@ -5284,6 +5284,15 @@ static int ipa3_setup_apps_pipes(void)
 		sys_in.client = IPA_CLIENT_APPS_LAN_PROD;
 		sys_in.desc_fifo_sz = IPA_SYS_TX_DATA_DESC_FIFO_SZ;
 		sys_in.ipa_ep_cfg.mode.mode = IPA_BASIC;
+		if (ipa3_ctx->ulso_supported) {
+			sys_in.ipa_ep_cfg.ulso.ipid_min_max_idx =
+				ENDP_INIT_ULSO_CFG_IP_ID_MIN_MAX_VAL_IDX_LINUX;
+			sys_in.ipa_ep_cfg.ulso.is_ulso_pipe = true;
+			sys_in.ipa_ep_cfg.cfg.cs_offload_en = IPA_ENABLE_CS_OFFLOAD_UL;
+			sys_in.ipa_ep_cfg.hdr.hdr_len = QMAP_HDR_LEN + ETH_HLEN;
+			sys_in.ipa_ep_cfg.hdr_ext.hdr_bytes_to_remove_valid = true;
+			sys_in.ipa_ep_cfg.hdr_ext.hdr_bytes_to_remove = QMAP_HDR_LEN;
+		}
 		if (ipa3_setup_sys_pipe(&sys_in,
 			&ipa3_ctx->clnt_hdl_data_out)) {
 			IPAERR(":setup sys pipe (LAN_PROD) failed.\n");
@@ -7794,6 +7803,9 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
 	ipa3_ctx->ipa_wdi3_5g_holb_timeout =
 		resource_p->ipa_wdi3_5g_holb_timeout;
 	ipa3_ctx->is_wdi3_tx1_needed = false;
+	ipa3_ctx->ulso_supported = resource_p->ulso_supported;
+	ipa3_ctx->ulso_ip_id_min = resource_p->ulso_ip_id_min;
+	ipa3_ctx->ulso_ip_id_max = resource_p->ulso_ip_id_max;
 
 	if (resource_p->gsi_fw_file_name) {
 		ipa3_ctx->gsi_fw_file_name =
@@ -8538,6 +8550,43 @@ static void get_dts_tx_wrapper_cache_size(struct platform_device *pdev,
 		ipa_drv_res->tx_wrapper_cache_max_size);
 }
 
+static void ipa_dts_get_ulso_data(struct platform_device *pdev,
+		struct ipa3_plat_drv_res *ipa_drv_res)
+{
+	int result;
+	u32 tmp;
+
+	ipa_drv_res->ulso_supported = of_property_read_bool(pdev->dev.of_node,
+		"qcom,ulso-supported");
+	IPADBG(": ulso_supported = %d", ipa_drv_res->ulso_supported);
+	if (!ipa_drv_res->ulso_supported)
+		return;
+
+	result = of_property_read_u32(
+		pdev->dev.of_node,
+		"qcom,ulso-ip-id-min-linux-val",
+		&tmp);
+	if (result) {
+		ipa_drv_res->ulso_ip_id_min = 0;
+	} else {
+		ipa_drv_res->ulso_ip_id_min = tmp;
+	}
+	IPADBG("ulso_ip_id_min is set to %d",
+		ipa_drv_res->ulso_ip_id_min);
+
+	result = of_property_read_u32(
+		pdev->dev.of_node,
+		"qcom,ulso-ip-id-max-linux-val",
+		&tmp);
+	if (result) {
+		ipa_drv_res->ulso_ip_id_max = 0xffff;
+	} else {
+		ipa_drv_res->ulso_ip_id_max = tmp;
+	}
+	IPADBG("ulso_ip_id_max is set to %d",
+		ipa_drv_res->ulso_ip_id_max);
+}
+
 static int get_ipa_dts_configuration(struct platform_device *pdev,
 		struct ipa3_plat_drv_res *ipa_drv_res)
 {
@@ -9177,6 +9226,8 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
 
 	get_dts_tx_wrapper_cache_size(pdev, ipa_drv_res);
 
+	ipa_dts_get_ulso_data(pdev, ipa_drv_res);
+
 	result = of_property_read_u32(pdev->dev.of_node,
 		"qcom,max_num_smmu_cb",
 		&ipa_drv_res->max_num_smmu_cb);

+ 7 - 4
drivers/platform/msm/ipa/ipa_v3/ipa_dp.c

@@ -1959,14 +1959,17 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
 			ipa_imm_cmd_modify_ip_packet_init_ex_dest_pipe(
 				ipa3_ctx->pkt_init_ex_imm[ipa3_ctx->ipa_num_pipes].base,
 				dst_ep_idx);
-			desc[data_idx].opcode =
-				ipa3_ctx->pkt_init_ex_imm_opcode;
+			desc[data_idx].opcode = ipa3_ctx->pkt_init_ex_imm_opcode;
 			desc[data_idx].dma_address =
 				ipa3_ctx->pkt_init_ex_imm[ipa3_ctx->ipa_num_pipes].phys_base;
+		} else if (ipa3_ctx->ep[dst_ep_idx].cfg.ulso.is_ulso_pipe &&
+			skb_is_gso(skb)) {
+			desc[data_idx].opcode = ipa3_ctx->pkt_init_ex_imm_opcode;
+			desc[data_idx].dma_address =
+				ipa3_ctx->pkt_init_ex_imm[dst_ep_idx].phys_base;
 		} else {
 			desc[data_idx].opcode = ipa3_ctx->pkt_init_imm_opcode;
-			desc[data_idx].dma_address =
-				ipa3_ctx->pkt_init_imm[dst_ep_idx];
+			desc[data_idx].dma_address = ipa3_ctx->pkt_init_imm[dst_ep_idx];
 		}
 		desc[data_idx].dma_address_valid = true;
 		desc[data_idx].type = IPA_IMM_CMD_DESC;

+ 18 - 0
drivers/platform/msm/ipa/ipa_v3/ipa_i.h

@@ -74,6 +74,16 @@
 #define IPA_HOLB_TMR_VAL_4_5 31
 #define IPA_IMM_IP_PACKET_INIT_EX_CMD_NUM (IPA5_MAX_NUM_PIPES + 1)
 
+/* ULSO Constants */
+enum {
+	ENDP_INIT_ULSO_CFG_IP_ID_MIN_MAX_VAL_IDX_LINUX,
+	ENDP_INIT_ULSO_CFG_IP_ID_MIN_MAX_VAL_IDX_FREE1,
+	ENDP_INIT_ULSO_CFG_IP_ID_MIN_MAX_VAL_IDX_FREE2,
+	ENDP_INIT_ULSO_CFG_IP_ID_MIN_MAX_VAL_IDX_MAX
+};
+
+#define QMAP_HDR_LEN 8
+
 /*
  * The transport descriptor size was changed to GSI_CHAN_RE_SIZE_16B, but
  * IPA users still use sps_iovec size as FIFO element size.
@@ -2215,6 +2225,9 @@ struct ipa3_context {
 	struct ipa_mem_buffer pkt_init_ex_mem;
 	struct ipa_mem_buffer pkt_init_ex_imm[IPA_IMM_IP_PACKET_INIT_EX_CMD_NUM];
 	bool is_modem_up;
+	bool ulso_supported;
+	u16 ulso_ip_id_min;
+	u16 ulso_ip_id_max;
 };
 
 struct ipa3_plat_drv_res {
@@ -2288,6 +2301,9 @@ struct ipa3_plat_drv_res {
 	u32 ipa_wdi3_2g_holb_timeout;
 	u32 ipa_wdi3_5g_holb_timeout;
 	bool ipa_endp_delay_wa_v2;
+	bool ulso_supported;
+	u16 ulso_ip_id_min;
+	u16 ulso_ip_id_max;
 };
 
 /**
@@ -2616,6 +2632,8 @@ int ipa3_cfg_ep_holb_by_client(enum ipa_client_type client,
 
 int ipa3_cfg_ep_ctrl(u32 clnt_hdl, const struct ipa_ep_cfg_ctrl *ep_ctrl);
 
+int ipa3_cfg_ep_ulso(u32 clnt_hdl, const struct ipa_ep_cfg_ulso *ep_ulso);
+
 /*
  * Header removal / addition
  */

+ 71 - 0
drivers/platform/msm/ipa/ipa_v3/ipa_utils.c

@@ -675,6 +675,8 @@ static const struct rsrc_min_max ipa3_rsrc_dst_grp_config
 		{6, 6}, {5, 5}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {39, 39},  },
 		[IPA_v5_0_RSRC_GRP_TYPE_DST_DPS_DMARS] = {
 		{0, 3}, {0, 3}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},  },
+		[IPA_v5_0_RSRC_GRP_TYPE_DST_ULSO_SEGMENTS] = {
+		{0, 0x3f}, {0, 0x3f}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},  },
 	},
 	[IPA_5_0_MHI] = {
 		/* UL  DL  unused  unused unused  UC_RX_Q DRBIP N/A */
@@ -690,6 +692,8 @@ static const struct rsrc_min_max ipa3_rsrc_dst_grp_config
 		{6, 6}, {5, 5}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {39, 39},  },
 		[IPA_v5_0_RSRC_GRP_TYPE_DST_DPS_DMARS] = {
 		{0, 3}, {0, 3}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},  },
+		[IPA_v5_0_RSRC_GRP_TYPE_DST_ULSO_SEGMENTS] = {
+		{0, 0x3f}, {0, 0x3f}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},  },
 	},
 };
 
@@ -6559,6 +6563,13 @@ int ipa3_init_hw(void)
 		}
 	}
 
+	if (ipa3_is_ulso_supported()) {
+		ipahal_write_reg_n(IPA_ULSO_CFG_IP_ID_MIN_VALUE_n, 0,
+			ipa3_ctx->ulso_ip_id_min);
+		ipahal_write_reg_n(IPA_ULSO_CFG_IP_ID_MAX_VALUE_n, 0,
+		ipa3_ctx->ulso_ip_id_max);
+	}
+
 	ipa_comp_cfg();
 
 	/*
@@ -7005,6 +7016,13 @@ int ipa3_cfg_ep(u32 clnt_hdl, const struct ipa_ep_cfg *ipa_ep_cfg)
 	if (result)
 		return result;
 
+	if (ipa3_is_ulso_supported()) {
+		result = ipa3_cfg_ep_ulso(clnt_hdl,
+			&ipa_ep_cfg->ulso);
+		if (result)
+			return result;
+	}
+
 	if (IPA_CLIENT_IS_PROD(ipa3_ctx->ep[clnt_hdl].client)) {
 		result = ipa3_cfg_ep_nat(clnt_hdl, &ipa_ep_cfg->nat);
 		if (result)
@@ -7393,6 +7411,45 @@ int ipa3_cfg_ep_hdr_ext(u32 clnt_hdl,
 	return 0;
 }
 
+/**
+ * ipa3_cfg_ep_ulso() -  IPA end-point ulso configuration
+ * @clnt_hdl:	[in] opaque client handle assigned by IPA to client
+ * @ep_ulso:	[in] IPA end-point ulso configuration params
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:	Should not be called from atomic context
+ */
+int ipa3_cfg_ep_ulso(u32 clnt_hdl,
+		       const struct ipa_ep_cfg_ulso *ep_ulso)
+{
+	struct ipa3_ep_context *ep;
+
+	if (clnt_hdl >= ipa3_ctx->ipa_num_pipes ||
+	    ipa3_ctx->ep[clnt_hdl].valid == 0 || ep_ulso == NULL) {
+		IPAERR("bad parm, clnt_hdl = %d , ep_valid = %d\n",
+				clnt_hdl, ipa3_ctx->ep[clnt_hdl].valid);
+		return -EINVAL;
+	}
+
+	IPADBG("pipe=%d ipid_min_max_idx=%d is_ulso_pipe=%d\n",
+		clnt_hdl, ep_ulso->ipid_min_max_idx, ep_ulso->is_ulso_pipe);
+
+	ep = &ipa3_ctx->ep[clnt_hdl];
+
+	/* copy over EP cfg */
+	ep->cfg.ulso = *ep_ulso;
+
+	IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(clnt_hdl));
+
+	ipahal_write_reg_n(IPA_ENDP_INIT_ULSO_CFG_n, clnt_hdl,
+		ep->cfg.ulso.ipid_min_max_idx);
+
+	IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl));
+
+	return 0;
+}
+
 /**
  * ipa3_cfg_ep_ctrl() -  IPA end-point Control configuration
  * @clnt_hdl:	[in] opaque client handle assigned by IPA to client
@@ -11663,3 +11720,17 @@ void ipa3_set_modem_up(bool is_up)
 	ipa3_ctx->is_modem_up = is_up;
 	mutex_unlock(&ipa3_ctx->lock);
 }
+
+/**
+ * ipa3_is_ulso_supported() - Query IPA for ulso support
+ *
+ * Return value: true if ulso is supported, false otherwise
+ *
+ */
+bool ipa3_is_ulso_supported(void)
+{
+	if (!ipa3_ctx)
+		return false;
+
+	return ipa3_ctx->ulso_supported;
+}

+ 13 - 1
drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c

@@ -162,7 +162,10 @@ static const char *ipareg_name_to_str[IPA_REG_MAX] = {
 	__stringify(IPA_NAT_UC_SHARED_CFG),
 	__stringify(IPA_CONN_TRACK_UC_EXTERNAL_CFG),
 	__stringify(IPA_CONN_TRACK_UC_LOCAL_CFG),
-	__stringify(IPA_CONN_TRACK_UC_SHARED_CFG)
+	__stringify(IPA_CONN_TRACK_UC_SHARED_CFG),
+	__stringify(IPA_ULSO_CFG_IP_ID_MIN_VALUE_n),
+	__stringify(IPA_ULSO_CFG_IP_ID_MAX_VALUE_n),
+	__stringify(IPA_ENDP_INIT_ULSO_CFG_n),
 };
 
 static void ipareg_construct_dummy(enum ipahal_reg_name reg,
@@ -4479,6 +4482,15 @@ static struct ipahal_reg_obj ipahal_reg_objs[IPA_HW_MAX][IPA_REG_MAX] = {
 	[IPA_HW_v5_0][IPA_COAL_QMAP_CFG] = {
 		ipareg_construct_coal_qmap_cfg, ipareg_parse_coal_qmap_cfg,
 		0x0000091c, 0, 0, 0, 0, 0},
+	[IPA_HW_v5_0][IPA_ULSO_CFG_IP_ID_MIN_VALUE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000934, 0x4, 0, 0, 0, 0},
+	[IPA_HW_v5_0][IPA_ULSO_CFG_IP_ID_MAX_VALUE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000924, 0x4, 0, 0, 0, 0},
+	[IPA_HW_v5_0][IPA_ENDP_INIT_ULSO_CFG_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x0000106c, 0x80, 0, 0, 0, 0},
 
 	/* IPA_DEBUG */
 	[IPA_HW_v5_0][IPA_RX_HPS_CLIENTS_MIN_DEPTH_1] = { //TODO contstruct not matching previous version

+ 3 - 0
drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h

@@ -160,6 +160,9 @@ enum ipahal_reg_name {
 	IPA_CONN_TRACK_UC_EXTERNAL_CFG,
 	IPA_CONN_TRACK_UC_LOCAL_CFG,
 	IPA_CONN_TRACK_UC_SHARED_CFG,
+	IPA_ULSO_CFG_IP_ID_MIN_VALUE_n,
+	IPA_ULSO_CFG_IP_ID_MAX_VALUE_n,
+	IPA_ENDP_INIT_ULSO_CFG_n,
 	IPA_REG_MAX,
 };
 

+ 16 - 0
drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h

@@ -803,4 +803,20 @@ int ipahal_reg_init(enum ipa_hw_type ipa_hw_type);
 #define IPA_COMP_CFG_IPA_FULL_FLUSH_WAIT_RSC_CLOSURE_EN_SHFT_v5_0 17
 #define IPA_COMP_CFG_RAM_ARB_PRIORITY_CLIENT_SAMP_FIX_DISABLE_BMSK_v5_0 0x1
 #define IPA_COMP_CFG_RAM_ARB_PRIORITY_CLIENT_SAMP_FIX_DISABLE_SHFT_v5_0 0
+
+
+/* IPA_ULSO registers */
+
+/* IPA_ULSO_CFG_IP_ID_MIN_VALUE_n register */
+#define IPA_ULSO_CFG_IP_ID_MIN_VALUE_n_IP_ID_MIN_VALUE_BMSK 0xffff
+#define IPA_ULSO_CFG_IP_ID_MIN_VALUE_n_IP_ID_MIN_VALUE_SHFT 0
+
+ /* IPA_ULSO_CFG_IP_ID_MAX_VALUE_n register */
+#define IPA_ULSO_CFG_IP_ID_MAX_VALUE_n_IP_ID_MAX_VALUE_BMSK 0xffff
+#define IPA_ULSO_CFG_IP_ID_MAX_VALUE_n_IP_ID_MAX_VALUE_SHFT 0
+
+ /* IPA_ENDP_INIT_ULSO_CFG_n register */
+#define IPA_ENDP_INIT_ULSO_CFG_n_IPV4_ID_MIN_MAX_VAL_INDEX_BMSK 0x3
+#define IPA_ENDP_INIT_ULSO_CFG_n_IPV4_ID_MIN_MAX_VAL_INDEX_SHFT 0
+
 #endif /* _IPAHAL_REG_I_H_ */