diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h index 329b34ae6e..2d1a755803 100644 --- a/drivers/platform/msm/ipa/ipa_common_i.h +++ b/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_ */ diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 2e25e48a29..3b84ed6c79 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/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"); @@ -7812,6 +7821,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 = @@ -8556,6 +8568,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) { @@ -9195,6 +9244,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); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index 4c5b16c650..d5fb3cffb8 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/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; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index f3c0bd32a8..612b0161ee 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/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 */ diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 6bba46021a..65765f6273 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -691,6 +691,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 */ @@ -706,6 +708,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_1_APQ] = { @@ -6673,6 +6677,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(); /* @@ -7119,6 +7130,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) @@ -7507,6 +7525,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 @@ -11779,3 +11836,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; +} diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c index c5da91959e..872b18b530 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c +++ b/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 diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h index 80c77e42e2..f4f6c55722 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h +++ b/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, }; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h index f9f8d9db5a..d74629ef09 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h +++ b/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_ */