Loading drivers/platform/msm/ipa/ipa_v2/ipa.c +9 −0 Original line number Diff line number Diff line Loading @@ -3855,6 +3855,7 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p, ipa_ctx->use_ipa_teth_bridge = resource_p->use_ipa_teth_bridge; ipa_ctx->ipa_bam_remote_mode = resource_p->ipa_bam_remote_mode; ipa_ctx->modem_cfg_emb_pipe_flt = resource_p->modem_cfg_emb_pipe_flt; ipa_ctx->ipa_wdi2 = resource_p->ipa_wdi2; ipa_ctx->wan_rx_ring_size = resource_p->wan_rx_ring_size; ipa_ctx->lan_rx_ring_size = resource_p->lan_rx_ring_size; ipa_ctx->skip_uc_pipe_reset = resource_p->skip_uc_pipe_reset; Loading Loading @@ -4393,6 +4394,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev, ipa_drv_res->ipa_hw_mode = 0; ipa_drv_res->ipa_bam_remote_mode = false; ipa_drv_res->modem_cfg_emb_pipe_flt = false; ipa_drv_res->ipa_wdi2 = false; ipa_drv_res->wan_rx_ring_size = IPA_GENERIC_RX_POOL_SZ; ipa_drv_res->lan_rx_ring_size = IPA_GENERIC_RX_POOL_SZ; Loading Loading @@ -4459,6 +4461,13 @@ static int get_ipa_dts_configuration(struct platform_device *pdev, ipa_drv_res->modem_cfg_emb_pipe_flt ? "True" : "False"); ipa_drv_res->ipa_wdi2 = of_property_read_bool(pdev->dev.of_node, "qcom,ipa-wdi2"); IPADBG(": WDI-2.0 = %s\n", ipa_drv_res->ipa_wdi2 ? "True" : "False"); ipa_drv_res->skip_uc_pipe_reset = of_property_read_bool(pdev->dev.of_node, "qcom,skip-uc-pipe-reset"); Loading drivers/platform/msm/ipa/ipa_v2/ipa_i.h +14 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,9 @@ #define IPA_DL_CHECKSUM_LENGTH (8) #define IPA_NUM_DESC_PER_SW_TX (2) #define IPA_GENERIC_RX_POOL_SZ 1000 #define IPA_UC_FINISH_MAX 6 #define IPA_UC_WAIT_MIN_SLEEP 1000 #define IPA_UC_WAII_MAX_SLEEP 1200 #define IPA_MAX_STATUS_STAT_NUM 30 Loading Loading @@ -884,6 +887,14 @@ struct ipa_uc_ctx { u32 uc_status; bool uc_zip_error; u32 uc_error_type; phys_addr_t rdy_ring_base_pa; phys_addr_t rdy_ring_rp_pa; u32 rdy_ring_size; phys_addr_t rdy_comp_ring_base_pa; phys_addr_t rdy_comp_ring_wp_pa; u32 rdy_comp_ring_size; u32 *rdy_ring_rp_va; u32 *rdy_comp_ring_wp_va; }; /** Loading Loading @@ -988,6 +999,7 @@ struct ipacm_client_info { * @use_ipa_teth_bridge: use tethering bridge driver * @ipa_bam_remote_mode: ipa bam is in remote mode * @modem_cfg_emb_pipe_flt: modem configure embedded pipe filtering rules * @ipa_wdi2: using wdi-2.0 * @ipa_bus_hdl: msm driver handle for the data path bus * @ctrl: holds the core specific operations based on * core version (vtable like) Loading Loading @@ -1075,6 +1087,7 @@ struct ipa_context { bool use_ipa_teth_bridge; bool ipa_bam_remote_mode; bool modem_cfg_emb_pipe_flt; bool ipa_wdi2; /* featurize if memory footprint becomes a concern */ struct ipa_stats stats; void *smem_pipe_mem; Loading Loading @@ -1165,6 +1178,7 @@ struct ipa_plat_drv_res { u32 ee; bool ipa_bam_remote_mode; bool modem_cfg_emb_pipe_flt; bool ipa_wdi2; u32 wan_rx_ring_size; u32 lan_rx_ring_size; bool skip_uc_pipe_reset; Loading drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c +355 −71 Original line number Diff line number Diff line Loading @@ -27,10 +27,12 @@ #define IPA_WDI_RX_RING_RES 0 #define IPA_WDI_RX_RING_RP_RES 1 #define IPA_WDI_TX_RING_RES 2 #define IPA_WDI_CE_RING_RES 3 #define IPA_WDI_CE_DB_RES 4 #define IPA_WDI_MAX_RES 5 #define IPA_WDI_RX_COMP_RING_RES 2 #define IPA_WDI_RX_COMP_RING_WP_RES 3 #define IPA_WDI_TX_RING_RES 4 #define IPA_WDI_CE_RING_RES 5 #define IPA_WDI_CE_DB_RES 6 #define IPA_WDI_MAX_RES 7 struct ipa_wdi_res { struct ipa_wdi_buffer_info *res; Loading Loading @@ -232,6 +234,21 @@ struct IpaHwWdiTxSetUpCmdData_t { u8 reserved; } __packed; struct IpaHwWdi2TxSetUpCmdData_t { u32 comp_ring_base_pa; u32 comp_ring_base_pa_hi; u16 comp_ring_size; u16 reserved_comp_ring; u32 ce_ring_base_pa; u32 ce_ring_base_pa_hi; u16 ce_ring_size; u16 reserved_ce_ring; u32 ce_ring_doorbell_pa; u32 ce_ring_doorbell_pa_hi; u16 num_tx_buffers; u8 ipa_pipe_number; u8 reserved; } __packed; /** * struct IpaHwWdiRxSetUpCmdData_t - Structure holding the parameters for * IPA_CPU_2_HW_CMD_WDI_RX_SET_UP command. Loading @@ -253,6 +270,19 @@ struct IpaHwWdiRxSetUpCmdData_t { u8 ipa_pipe_number; } __packed; struct IpaHwWdi2RxSetUpCmdData_t { u32 rx_ring_base_pa; u32 rx_ring_base_pa_hi; u32 rx_ring_size; u32 rx_ring_rp_pa; u32 rx_ring_rp_pa_hi; u32 rx_comp_ring_base_pa; u32 rx_comp_ring_base_pa_hi; u32 rx_comp_ring_size; u32 rx_comp_ring_wp_pa; u32 rx_comp_ring_wp_pa_hi; u8 ipa_pipe_number; } __packed; /** * union IpaHwWdiRxExtCfgCmdData_t - Structure holding the parameters for * IPA_CPU_2_HW_CMD_WDI_RX_EXT_CFG command. Loading Loading @@ -560,6 +590,9 @@ static void ipa_release_uc_smmu_mappings(enum ipa_client_type client) end = IPA_WDI_CE_DB_RES; } else { start = IPA_WDI_RX_RING_RES; if (ipa_ctx->ipa_wdi2) end = IPA_WDI_RX_COMP_RING_WP_RES; else end = IPA_WDI_RX_RING_RP_RES; } Loading Loading @@ -708,6 +741,8 @@ int ipa2_connect_wdi_pipe(struct ipa_wdi_in_params *in, struct ipa_mem_buffer cmd; struct IpaHwWdiTxSetUpCmdData_t *tx; struct IpaHwWdiRxSetUpCmdData_t *rx; struct IpaHwWdi2TxSetUpCmdData_t *tx_2; struct IpaHwWdi2RxSetUpCmdData_t *rx_2; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; unsigned long va; phys_addr_t pa; Loading Loading @@ -760,6 +795,9 @@ int ipa2_connect_wdi_pipe(struct ipa_wdi_in_params *in, IPADBG("client=%d ep=%d\n", in->sys.client, ipa_ep_idx); if (IPA_CLIENT_IS_CONS(in->sys.client)) { if (ipa_ctx->ipa_wdi2) cmd.size = sizeof(*tx_2); else cmd.size = sizeof(*tx); IPADBG("comp_ring_base_pa=0x%pa\n", &in->u.dl.comp_ring_base_pa); Loading @@ -769,11 +807,60 @@ int ipa2_connect_wdi_pipe(struct ipa_wdi_in_params *in, IPADBG("ce_ring_doorbell_pa=0x%pa\n", &in->u.dl.ce_door_bell_pa); IPADBG("num_tx_buffers=%d\n", in->u.dl.num_tx_buffers); } else { if (ipa_ctx->ipa_wdi2) { /* WDI2.0 feature */ cmd.size = sizeof(*rx_2); IPADBG("rdy_ring_rp value =%d\n", *in->u.ul.rdy_ring_rp_va); IPADBG("rx_comp_ring_wp value=%d\n", *in->u.ul.rdy_comp_ring_wp_va); ipa_ctx->uc_ctx.rdy_ring_rp_va = in->u.ul.rdy_ring_rp_va; ipa_ctx->uc_ctx.rdy_comp_ring_wp_va = in->u.ul.rdy_comp_ring_wp_va; } else { cmd.size = sizeof(*rx); IPADBG("rx_ring_base_pa=0x%pa\n", &in->u.ul.rdy_ring_base_pa); IPADBG("rx_ring_size=%d\n", in->u.ul.rdy_ring_size); IPADBG("rx_ring_rp_pa=0x%pa\n", &in->u.ul.rdy_ring_rp_pa); } IPADBG("rx_ring_base_pa=0x%pa\n", &in->u.ul.rdy_ring_base_pa); IPADBG("rx_ring_size=%d\n", in->u.ul.rdy_ring_size); IPADBG("rx_ring_rp_pa=0x%pa\n", &in->u.ul.rdy_ring_rp_pa); IPADBG("rx_comp_ring_base_pa=0x%pa\n", &in->u.ul.rdy_comp_ring_base_pa); IPADBG("rx_comp_ring_size=%d\n", in->u.ul.rdy_comp_ring_size); IPADBG("rx_comp_ring_wp_pa=0x%pa\n", &in->u.ul.rdy_comp_ring_wp_pa); ipa_ctx->uc_ctx.rdy_ring_base_pa = in->u.ul.rdy_ring_base_pa; ipa_ctx->uc_ctx.rdy_ring_rp_pa = in->u.ul.rdy_ring_rp_pa; ipa_ctx->uc_ctx.rdy_ring_size = in->u.ul.rdy_ring_size; ipa_ctx->uc_ctx.rdy_comp_ring_base_pa = in->u.ul.rdy_comp_ring_base_pa; ipa_ctx->uc_ctx.rdy_comp_ring_wp_pa = in->u.ul.rdy_comp_ring_wp_pa; ipa_ctx->uc_ctx.rdy_comp_ring_size = in->u.ul.rdy_comp_ring_size; /* check if the VA is empty */ if (!in->u.ul.rdy_ring_rp_va && ipa_ctx->ipa_wdi2) { IPAERR("rdy_ring_rp_va is empty, wdi2.0(%d)\n", ipa_ctx->ipa_wdi2); goto dma_alloc_fail; } if (!in->u.ul.rdy_comp_ring_wp_va && ipa_ctx->ipa_wdi2) { IPAERR("comp_ring_wp_va is empty, wdi2.0(%d)\n", ipa_ctx->ipa_wdi2); goto dma_alloc_fail; } } cmd.base = dma_alloc_coherent(ipa_ctx->uc_pdev, cmd.size, Loading @@ -785,11 +872,87 @@ int ipa2_connect_wdi_pipe(struct ipa_wdi_in_params *in, } if (IPA_CLIENT_IS_CONS(in->sys.client)) { tx = (struct IpaHwWdiTxSetUpCmdData_t *)cmd.base; if (ipa_ctx->ipa_wdi2) { tx_2 = (struct IpaHwWdi2TxSetUpCmdData_t *)cmd.base; len = in->smmu_enabled ? in->u.dl_smmu.comp_ring_size : in->u.dl.comp_ring_size; IPADBG("TX ring smmu_en=%d ring_size=%d %d\n", in->smmu_enabled, IPADBG("TX_2 ring smmu_en=%d ring_size=%d %d\n", in->smmu_enabled, in->u.dl_smmu.comp_ring_size, in->u.dl.comp_ring_size); if (ipa_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES, in->smmu_enabled, in->u.dl.comp_ring_base_pa, &in->u.dl_smmu.comp_ring, len, false, &va)) { IPAERR("fail to create uc mapping TX ring.\n"); result = -ENOMEM; goto uc_timeout; } tx_2->comp_ring_base_pa_hi = (u32) ((va & 0xFFFFFFFF00000000) >> 32); tx_2->comp_ring_base_pa = (u32) (va & 0xFFFFFFFF); tx_2->comp_ring_size = len; IPADBG("TX_2 comp_ring_base_pa_hi=0x%08x :0x%08x\n", tx_2->comp_ring_base_pa_hi, tx_2->comp_ring_base_pa); len = in->smmu_enabled ? in->u.dl_smmu.ce_ring_size : in->u.dl.ce_ring_size; IPADBG("TX_2 CE ring smmu_en=%d ring_size=%d %d\n", in->smmu_enabled, in->u.dl_smmu.ce_ring_size, in->u.dl.ce_ring_size); if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES, in->smmu_enabled, in->u.dl.ce_ring_base_pa, &in->u.dl_smmu.ce_ring, len, false, &va)) { IPAERR("fail to create uc mapping CE ring.\n"); result = -ENOMEM; goto uc_timeout; } tx_2->ce_ring_base_pa_hi = (u32) ((va & 0xFFFFFFFF00000000) >> 32); tx_2->ce_ring_base_pa = (u32) (va & 0xFFFFFFFF); tx_2->ce_ring_size = len; IPADBG("TX_2 ce_ring_base_pa_hi=0x%08x :0x%08x\n", tx_2->ce_ring_base_pa_hi, tx_2->ce_ring_base_pa); pa = in->smmu_enabled ? in->u.dl_smmu.ce_door_bell_pa : in->u.dl.ce_door_bell_pa; if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES, in->smmu_enabled, pa, NULL, 4, true, &va)) { IPAERR("fail to create uc mapping CE DB.\n"); result = -ENOMEM; goto uc_timeout; } tx_2->ce_ring_doorbell_pa_hi = (u32) ((va & 0xFFFFFFFF00000000) >> 32); tx_2->ce_ring_doorbell_pa = (u32) (va & 0xFFFFFFFF); IPADBG("TX_2 ce_ring_doorbell_pa_hi=0x%08x :0x%08x\n", tx_2->ce_ring_doorbell_pa_hi, tx_2->ce_ring_doorbell_pa); tx_2->num_tx_buffers = in->u.dl.num_tx_buffers; tx_2->ipa_pipe_number = ipa_ep_idx; } else { tx = (struct IpaHwWdiTxSetUpCmdData_t *)cmd.base; len = in->smmu_enabled ? in->u.dl_smmu.comp_ring_size : in->u.dl.comp_ring_size; IPADBG("TX ring smmu_en=%d ring_size=%d %d\n", in->smmu_enabled, in->u.dl_smmu.comp_ring_size, in->u.dl.comp_ring_size); if (ipa_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES, Loading Loading @@ -825,7 +988,6 @@ int ipa2_connect_wdi_pipe(struct ipa_wdi_in_params *in, } tx->ce_ring_base_pa = va; tx->ce_ring_size = len; pa = in->smmu_enabled ? in->u.dl_smmu.ce_door_bell_pa : in->u.dl.ce_door_bell_pa; if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES, Loading @@ -840,9 +1002,10 @@ int ipa2_connect_wdi_pipe(struct ipa_wdi_in_params *in, goto uc_timeout; } tx->ce_ring_doorbell_pa = va; tx->num_tx_buffers = in->u.dl.num_tx_buffers; tx->ipa_pipe_number = ipa_ep_idx; } if (ipa_ctx->ipa_hw_type >= IPA_HW_v2_5) { out->uc_door_bell_pa = ipa_ctx->ipa_wrapper_base + Loading @@ -858,12 +1021,109 @@ int ipa2_connect_wdi_pipe(struct ipa_wdi_in_params *in, IPA_HW_WDI_TX_MBOX_START_INDEX/32, IPA_HW_WDI_TX_MBOX_START_INDEX % 32); } } else { if (ipa_ctx->ipa_wdi2) { rx_2 = (struct IpaHwWdi2RxSetUpCmdData_t *)cmd.base; len = in->smmu_enabled ? in->u.ul_smmu.rdy_ring_size : in->u.ul.rdy_ring_size; IPADBG("RX_2 ring smmu_en=%d ring_size=%d %d\n", in->smmu_enabled, in->u.ul_smmu.rdy_ring_size, in->u.ul.rdy_ring_size); if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES, in->smmu_enabled, in->u.ul.rdy_ring_base_pa, &in->u.ul_smmu.rdy_ring, len, false, &va)) { IPAERR("fail to create uc RX_2 ring.\n"); result = -ENOMEM; goto uc_timeout; } rx_2->rx_ring_base_pa_hi = (u32) ((va & 0xFFFFFFFF00000000) >> 32); rx_2->rx_ring_base_pa = (u32) (va & 0xFFFFFFFF); rx_2->rx_ring_size = len; IPADBG("RX_2 rx_ring_base_pa_hi=0x%08x:0x%08x\n", rx_2->rx_ring_base_pa_hi, rx_2->rx_ring_base_pa); pa = in->smmu_enabled ? in->u.ul_smmu.rdy_ring_rp_pa : in->u.ul.rdy_ring_rp_pa; if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES, in->smmu_enabled, pa, NULL, 4, false, &va)) { IPAERR("fail to create uc RX_2 rng RP\n"); result = -ENOMEM; goto uc_timeout; } rx_2->rx_ring_rp_pa_hi = (u32) ((va & 0xFFFFFFFF00000000) >> 32); rx_2->rx_ring_rp_pa = (u32) (va & 0xFFFFFFFF); IPADBG("RX_2 rx_ring_rp_pa_hi=0x%08x :0x%08x\n", rx_2->rx_ring_rp_pa_hi, rx_2->rx_ring_rp_pa); len = in->smmu_enabled ? in->u.ul_smmu.rdy_comp_ring_size : in->u.ul.rdy_comp_ring_size; IPADBG("RX_2 ring smmu_en=%d comp_ring_size=%d %d\n", in->smmu_enabled, in->u.ul_smmu.rdy_comp_ring_size, in->u.ul.rdy_comp_ring_size); if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_COMP_RING_RES, in->smmu_enabled, in->u.ul.rdy_comp_ring_base_pa, &in->u.ul_smmu.rdy_comp_ring, len, false, &va)) { IPAERR("fail to create uc RX_2 comp_ring.\n"); result = -ENOMEM; goto uc_timeout; } rx_2->rx_comp_ring_base_pa_hi = (u32) ((va & 0xFFFFFFFF00000000) >> 32); rx_2->rx_comp_ring_base_pa = (u32) (va & 0xFFFFFFFF); rx_2->rx_comp_ring_size = len; IPADBG("RX_2 rx_comp_ring_base_pa_hi=0x%08x:0x%08x\n", rx_2->rx_comp_ring_base_pa_hi, rx_2->rx_comp_ring_base_pa); pa = in->smmu_enabled ? in->u.ul_smmu.rdy_comp_ring_wp_pa : in->u.ul.rdy_comp_ring_wp_pa; if (ipa_create_uc_smmu_mapping( IPA_WDI_RX_COMP_RING_WP_RES, in->smmu_enabled, pa, NULL, 4, false, &va)) { IPAERR("fail to create uc RX_2 comp_rng WP\n"); result = -ENOMEM; goto uc_timeout; } rx_2->rx_comp_ring_wp_pa_hi = (u32) ((va & 0xFFFFFFFF00000000) >> 32); rx_2->rx_comp_ring_wp_pa = (u32) (va & 0xFFFFFFFF); IPADBG("RX_2 rx_comp_ring_wp_pa_hi=0x%08x:0x%08x\n", rx_2->rx_comp_ring_wp_pa_hi, rx_2->rx_comp_ring_wp_pa); rx_2->ipa_pipe_number = ipa_ep_idx; } else { rx = (struct IpaHwWdiRxSetUpCmdData_t *)cmd.base; len = in->smmu_enabled ? in->u.ul_smmu.rdy_ring_size : in->u.ul.rdy_ring_size; IPADBG("RX ring smmu_en=%d ring_size=%d %d\n", in->smmu_enabled, IPADBG("RX ring smmu_en=%d ring_size=%d %d\n", in->smmu_enabled, in->u.ul_smmu.rdy_ring_size, in->u.ul.rdy_ring_size); if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES, Loading Loading @@ -894,8 +1154,9 @@ int ipa2_connect_wdi_pipe(struct ipa_wdi_in_params *in, goto uc_timeout; } rx->rx_ring_rp_pa = va; rx->ipa_pipe_number = ipa_ep_idx; } if (ipa_ctx->ipa_hw_type >= IPA_HW_v2_5) { out->uc_door_bell_pa = ipa_ctx->ipa_wrapper_base + Loading Loading @@ -1127,6 +1388,7 @@ int ipa2_disable_wdi_pipe(u32 clnt_hdl) union IpaHwWdiCommonChCmdData_t disable; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; u32 prod_hdl; int i; if (unlikely(!ipa_ctx)) { IPAERR("IPA driver was not initialized\n"); Loading @@ -1143,6 +1405,28 @@ int ipa2_disable_wdi_pipe(u32 clnt_hdl) if (result) return result; /* checking rdy_ring_rp_pa matches the rdy_comp_ring_wp_pa on WDI2.0 */ if (ipa_ctx->ipa_wdi2) { for (i = 0; i < IPA_UC_FINISH_MAX; i++) { IPADBG("(%d) rp_value(%u), comp_wp_value(%u)\n", i, *ipa_ctx->uc_ctx.rdy_ring_rp_va, *ipa_ctx->uc_ctx.rdy_comp_ring_wp_va); if (*ipa_ctx->uc_ctx.rdy_ring_rp_va != *ipa_ctx->uc_ctx.rdy_comp_ring_wp_va) { usleep_range(IPA_UC_WAIT_MIN_SLEEP, IPA_UC_WAII_MAX_SLEEP); } else { break; } } /* In case ipa_uc still haven't processed all * pending descriptors, we have to assert */ if (i == IPA_UC_FINISH_MAX) BUG(); } IPADBG("ep=%d\n", clnt_hdl); ep = &ipa_ctx->ep[clnt_hdl]; Loading Loading
drivers/platform/msm/ipa/ipa_v2/ipa.c +9 −0 Original line number Diff line number Diff line Loading @@ -3855,6 +3855,7 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p, ipa_ctx->use_ipa_teth_bridge = resource_p->use_ipa_teth_bridge; ipa_ctx->ipa_bam_remote_mode = resource_p->ipa_bam_remote_mode; ipa_ctx->modem_cfg_emb_pipe_flt = resource_p->modem_cfg_emb_pipe_flt; ipa_ctx->ipa_wdi2 = resource_p->ipa_wdi2; ipa_ctx->wan_rx_ring_size = resource_p->wan_rx_ring_size; ipa_ctx->lan_rx_ring_size = resource_p->lan_rx_ring_size; ipa_ctx->skip_uc_pipe_reset = resource_p->skip_uc_pipe_reset; Loading Loading @@ -4393,6 +4394,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev, ipa_drv_res->ipa_hw_mode = 0; ipa_drv_res->ipa_bam_remote_mode = false; ipa_drv_res->modem_cfg_emb_pipe_flt = false; ipa_drv_res->ipa_wdi2 = false; ipa_drv_res->wan_rx_ring_size = IPA_GENERIC_RX_POOL_SZ; ipa_drv_res->lan_rx_ring_size = IPA_GENERIC_RX_POOL_SZ; Loading Loading @@ -4459,6 +4461,13 @@ static int get_ipa_dts_configuration(struct platform_device *pdev, ipa_drv_res->modem_cfg_emb_pipe_flt ? "True" : "False"); ipa_drv_res->ipa_wdi2 = of_property_read_bool(pdev->dev.of_node, "qcom,ipa-wdi2"); IPADBG(": WDI-2.0 = %s\n", ipa_drv_res->ipa_wdi2 ? "True" : "False"); ipa_drv_res->skip_uc_pipe_reset = of_property_read_bool(pdev->dev.of_node, "qcom,skip-uc-pipe-reset"); Loading
drivers/platform/msm/ipa/ipa_v2/ipa_i.h +14 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,9 @@ #define IPA_DL_CHECKSUM_LENGTH (8) #define IPA_NUM_DESC_PER_SW_TX (2) #define IPA_GENERIC_RX_POOL_SZ 1000 #define IPA_UC_FINISH_MAX 6 #define IPA_UC_WAIT_MIN_SLEEP 1000 #define IPA_UC_WAII_MAX_SLEEP 1200 #define IPA_MAX_STATUS_STAT_NUM 30 Loading Loading @@ -884,6 +887,14 @@ struct ipa_uc_ctx { u32 uc_status; bool uc_zip_error; u32 uc_error_type; phys_addr_t rdy_ring_base_pa; phys_addr_t rdy_ring_rp_pa; u32 rdy_ring_size; phys_addr_t rdy_comp_ring_base_pa; phys_addr_t rdy_comp_ring_wp_pa; u32 rdy_comp_ring_size; u32 *rdy_ring_rp_va; u32 *rdy_comp_ring_wp_va; }; /** Loading Loading @@ -988,6 +999,7 @@ struct ipacm_client_info { * @use_ipa_teth_bridge: use tethering bridge driver * @ipa_bam_remote_mode: ipa bam is in remote mode * @modem_cfg_emb_pipe_flt: modem configure embedded pipe filtering rules * @ipa_wdi2: using wdi-2.0 * @ipa_bus_hdl: msm driver handle for the data path bus * @ctrl: holds the core specific operations based on * core version (vtable like) Loading Loading @@ -1075,6 +1087,7 @@ struct ipa_context { bool use_ipa_teth_bridge; bool ipa_bam_remote_mode; bool modem_cfg_emb_pipe_flt; bool ipa_wdi2; /* featurize if memory footprint becomes a concern */ struct ipa_stats stats; void *smem_pipe_mem; Loading Loading @@ -1165,6 +1178,7 @@ struct ipa_plat_drv_res { u32 ee; bool ipa_bam_remote_mode; bool modem_cfg_emb_pipe_flt; bool ipa_wdi2; u32 wan_rx_ring_size; u32 lan_rx_ring_size; bool skip_uc_pipe_reset; Loading
drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c +355 −71 Original line number Diff line number Diff line Loading @@ -27,10 +27,12 @@ #define IPA_WDI_RX_RING_RES 0 #define IPA_WDI_RX_RING_RP_RES 1 #define IPA_WDI_TX_RING_RES 2 #define IPA_WDI_CE_RING_RES 3 #define IPA_WDI_CE_DB_RES 4 #define IPA_WDI_MAX_RES 5 #define IPA_WDI_RX_COMP_RING_RES 2 #define IPA_WDI_RX_COMP_RING_WP_RES 3 #define IPA_WDI_TX_RING_RES 4 #define IPA_WDI_CE_RING_RES 5 #define IPA_WDI_CE_DB_RES 6 #define IPA_WDI_MAX_RES 7 struct ipa_wdi_res { struct ipa_wdi_buffer_info *res; Loading Loading @@ -232,6 +234,21 @@ struct IpaHwWdiTxSetUpCmdData_t { u8 reserved; } __packed; struct IpaHwWdi2TxSetUpCmdData_t { u32 comp_ring_base_pa; u32 comp_ring_base_pa_hi; u16 comp_ring_size; u16 reserved_comp_ring; u32 ce_ring_base_pa; u32 ce_ring_base_pa_hi; u16 ce_ring_size; u16 reserved_ce_ring; u32 ce_ring_doorbell_pa; u32 ce_ring_doorbell_pa_hi; u16 num_tx_buffers; u8 ipa_pipe_number; u8 reserved; } __packed; /** * struct IpaHwWdiRxSetUpCmdData_t - Structure holding the parameters for * IPA_CPU_2_HW_CMD_WDI_RX_SET_UP command. Loading @@ -253,6 +270,19 @@ struct IpaHwWdiRxSetUpCmdData_t { u8 ipa_pipe_number; } __packed; struct IpaHwWdi2RxSetUpCmdData_t { u32 rx_ring_base_pa; u32 rx_ring_base_pa_hi; u32 rx_ring_size; u32 rx_ring_rp_pa; u32 rx_ring_rp_pa_hi; u32 rx_comp_ring_base_pa; u32 rx_comp_ring_base_pa_hi; u32 rx_comp_ring_size; u32 rx_comp_ring_wp_pa; u32 rx_comp_ring_wp_pa_hi; u8 ipa_pipe_number; } __packed; /** * union IpaHwWdiRxExtCfgCmdData_t - Structure holding the parameters for * IPA_CPU_2_HW_CMD_WDI_RX_EXT_CFG command. Loading Loading @@ -560,6 +590,9 @@ static void ipa_release_uc_smmu_mappings(enum ipa_client_type client) end = IPA_WDI_CE_DB_RES; } else { start = IPA_WDI_RX_RING_RES; if (ipa_ctx->ipa_wdi2) end = IPA_WDI_RX_COMP_RING_WP_RES; else end = IPA_WDI_RX_RING_RP_RES; } Loading Loading @@ -708,6 +741,8 @@ int ipa2_connect_wdi_pipe(struct ipa_wdi_in_params *in, struct ipa_mem_buffer cmd; struct IpaHwWdiTxSetUpCmdData_t *tx; struct IpaHwWdiRxSetUpCmdData_t *rx; struct IpaHwWdi2TxSetUpCmdData_t *tx_2; struct IpaHwWdi2RxSetUpCmdData_t *rx_2; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; unsigned long va; phys_addr_t pa; Loading Loading @@ -760,6 +795,9 @@ int ipa2_connect_wdi_pipe(struct ipa_wdi_in_params *in, IPADBG("client=%d ep=%d\n", in->sys.client, ipa_ep_idx); if (IPA_CLIENT_IS_CONS(in->sys.client)) { if (ipa_ctx->ipa_wdi2) cmd.size = sizeof(*tx_2); else cmd.size = sizeof(*tx); IPADBG("comp_ring_base_pa=0x%pa\n", &in->u.dl.comp_ring_base_pa); Loading @@ -769,11 +807,60 @@ int ipa2_connect_wdi_pipe(struct ipa_wdi_in_params *in, IPADBG("ce_ring_doorbell_pa=0x%pa\n", &in->u.dl.ce_door_bell_pa); IPADBG("num_tx_buffers=%d\n", in->u.dl.num_tx_buffers); } else { if (ipa_ctx->ipa_wdi2) { /* WDI2.0 feature */ cmd.size = sizeof(*rx_2); IPADBG("rdy_ring_rp value =%d\n", *in->u.ul.rdy_ring_rp_va); IPADBG("rx_comp_ring_wp value=%d\n", *in->u.ul.rdy_comp_ring_wp_va); ipa_ctx->uc_ctx.rdy_ring_rp_va = in->u.ul.rdy_ring_rp_va; ipa_ctx->uc_ctx.rdy_comp_ring_wp_va = in->u.ul.rdy_comp_ring_wp_va; } else { cmd.size = sizeof(*rx); IPADBG("rx_ring_base_pa=0x%pa\n", &in->u.ul.rdy_ring_base_pa); IPADBG("rx_ring_size=%d\n", in->u.ul.rdy_ring_size); IPADBG("rx_ring_rp_pa=0x%pa\n", &in->u.ul.rdy_ring_rp_pa); } IPADBG("rx_ring_base_pa=0x%pa\n", &in->u.ul.rdy_ring_base_pa); IPADBG("rx_ring_size=%d\n", in->u.ul.rdy_ring_size); IPADBG("rx_ring_rp_pa=0x%pa\n", &in->u.ul.rdy_ring_rp_pa); IPADBG("rx_comp_ring_base_pa=0x%pa\n", &in->u.ul.rdy_comp_ring_base_pa); IPADBG("rx_comp_ring_size=%d\n", in->u.ul.rdy_comp_ring_size); IPADBG("rx_comp_ring_wp_pa=0x%pa\n", &in->u.ul.rdy_comp_ring_wp_pa); ipa_ctx->uc_ctx.rdy_ring_base_pa = in->u.ul.rdy_ring_base_pa; ipa_ctx->uc_ctx.rdy_ring_rp_pa = in->u.ul.rdy_ring_rp_pa; ipa_ctx->uc_ctx.rdy_ring_size = in->u.ul.rdy_ring_size; ipa_ctx->uc_ctx.rdy_comp_ring_base_pa = in->u.ul.rdy_comp_ring_base_pa; ipa_ctx->uc_ctx.rdy_comp_ring_wp_pa = in->u.ul.rdy_comp_ring_wp_pa; ipa_ctx->uc_ctx.rdy_comp_ring_size = in->u.ul.rdy_comp_ring_size; /* check if the VA is empty */ if (!in->u.ul.rdy_ring_rp_va && ipa_ctx->ipa_wdi2) { IPAERR("rdy_ring_rp_va is empty, wdi2.0(%d)\n", ipa_ctx->ipa_wdi2); goto dma_alloc_fail; } if (!in->u.ul.rdy_comp_ring_wp_va && ipa_ctx->ipa_wdi2) { IPAERR("comp_ring_wp_va is empty, wdi2.0(%d)\n", ipa_ctx->ipa_wdi2); goto dma_alloc_fail; } } cmd.base = dma_alloc_coherent(ipa_ctx->uc_pdev, cmd.size, Loading @@ -785,11 +872,87 @@ int ipa2_connect_wdi_pipe(struct ipa_wdi_in_params *in, } if (IPA_CLIENT_IS_CONS(in->sys.client)) { tx = (struct IpaHwWdiTxSetUpCmdData_t *)cmd.base; if (ipa_ctx->ipa_wdi2) { tx_2 = (struct IpaHwWdi2TxSetUpCmdData_t *)cmd.base; len = in->smmu_enabled ? in->u.dl_smmu.comp_ring_size : in->u.dl.comp_ring_size; IPADBG("TX ring smmu_en=%d ring_size=%d %d\n", in->smmu_enabled, IPADBG("TX_2 ring smmu_en=%d ring_size=%d %d\n", in->smmu_enabled, in->u.dl_smmu.comp_ring_size, in->u.dl.comp_ring_size); if (ipa_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES, in->smmu_enabled, in->u.dl.comp_ring_base_pa, &in->u.dl_smmu.comp_ring, len, false, &va)) { IPAERR("fail to create uc mapping TX ring.\n"); result = -ENOMEM; goto uc_timeout; } tx_2->comp_ring_base_pa_hi = (u32) ((va & 0xFFFFFFFF00000000) >> 32); tx_2->comp_ring_base_pa = (u32) (va & 0xFFFFFFFF); tx_2->comp_ring_size = len; IPADBG("TX_2 comp_ring_base_pa_hi=0x%08x :0x%08x\n", tx_2->comp_ring_base_pa_hi, tx_2->comp_ring_base_pa); len = in->smmu_enabled ? in->u.dl_smmu.ce_ring_size : in->u.dl.ce_ring_size; IPADBG("TX_2 CE ring smmu_en=%d ring_size=%d %d\n", in->smmu_enabled, in->u.dl_smmu.ce_ring_size, in->u.dl.ce_ring_size); if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES, in->smmu_enabled, in->u.dl.ce_ring_base_pa, &in->u.dl_smmu.ce_ring, len, false, &va)) { IPAERR("fail to create uc mapping CE ring.\n"); result = -ENOMEM; goto uc_timeout; } tx_2->ce_ring_base_pa_hi = (u32) ((va & 0xFFFFFFFF00000000) >> 32); tx_2->ce_ring_base_pa = (u32) (va & 0xFFFFFFFF); tx_2->ce_ring_size = len; IPADBG("TX_2 ce_ring_base_pa_hi=0x%08x :0x%08x\n", tx_2->ce_ring_base_pa_hi, tx_2->ce_ring_base_pa); pa = in->smmu_enabled ? in->u.dl_smmu.ce_door_bell_pa : in->u.dl.ce_door_bell_pa; if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES, in->smmu_enabled, pa, NULL, 4, true, &va)) { IPAERR("fail to create uc mapping CE DB.\n"); result = -ENOMEM; goto uc_timeout; } tx_2->ce_ring_doorbell_pa_hi = (u32) ((va & 0xFFFFFFFF00000000) >> 32); tx_2->ce_ring_doorbell_pa = (u32) (va & 0xFFFFFFFF); IPADBG("TX_2 ce_ring_doorbell_pa_hi=0x%08x :0x%08x\n", tx_2->ce_ring_doorbell_pa_hi, tx_2->ce_ring_doorbell_pa); tx_2->num_tx_buffers = in->u.dl.num_tx_buffers; tx_2->ipa_pipe_number = ipa_ep_idx; } else { tx = (struct IpaHwWdiTxSetUpCmdData_t *)cmd.base; len = in->smmu_enabled ? in->u.dl_smmu.comp_ring_size : in->u.dl.comp_ring_size; IPADBG("TX ring smmu_en=%d ring_size=%d %d\n", in->smmu_enabled, in->u.dl_smmu.comp_ring_size, in->u.dl.comp_ring_size); if (ipa_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES, Loading Loading @@ -825,7 +988,6 @@ int ipa2_connect_wdi_pipe(struct ipa_wdi_in_params *in, } tx->ce_ring_base_pa = va; tx->ce_ring_size = len; pa = in->smmu_enabled ? in->u.dl_smmu.ce_door_bell_pa : in->u.dl.ce_door_bell_pa; if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES, Loading @@ -840,9 +1002,10 @@ int ipa2_connect_wdi_pipe(struct ipa_wdi_in_params *in, goto uc_timeout; } tx->ce_ring_doorbell_pa = va; tx->num_tx_buffers = in->u.dl.num_tx_buffers; tx->ipa_pipe_number = ipa_ep_idx; } if (ipa_ctx->ipa_hw_type >= IPA_HW_v2_5) { out->uc_door_bell_pa = ipa_ctx->ipa_wrapper_base + Loading @@ -858,12 +1021,109 @@ int ipa2_connect_wdi_pipe(struct ipa_wdi_in_params *in, IPA_HW_WDI_TX_MBOX_START_INDEX/32, IPA_HW_WDI_TX_MBOX_START_INDEX % 32); } } else { if (ipa_ctx->ipa_wdi2) { rx_2 = (struct IpaHwWdi2RxSetUpCmdData_t *)cmd.base; len = in->smmu_enabled ? in->u.ul_smmu.rdy_ring_size : in->u.ul.rdy_ring_size; IPADBG("RX_2 ring smmu_en=%d ring_size=%d %d\n", in->smmu_enabled, in->u.ul_smmu.rdy_ring_size, in->u.ul.rdy_ring_size); if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES, in->smmu_enabled, in->u.ul.rdy_ring_base_pa, &in->u.ul_smmu.rdy_ring, len, false, &va)) { IPAERR("fail to create uc RX_2 ring.\n"); result = -ENOMEM; goto uc_timeout; } rx_2->rx_ring_base_pa_hi = (u32) ((va & 0xFFFFFFFF00000000) >> 32); rx_2->rx_ring_base_pa = (u32) (va & 0xFFFFFFFF); rx_2->rx_ring_size = len; IPADBG("RX_2 rx_ring_base_pa_hi=0x%08x:0x%08x\n", rx_2->rx_ring_base_pa_hi, rx_2->rx_ring_base_pa); pa = in->smmu_enabled ? in->u.ul_smmu.rdy_ring_rp_pa : in->u.ul.rdy_ring_rp_pa; if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES, in->smmu_enabled, pa, NULL, 4, false, &va)) { IPAERR("fail to create uc RX_2 rng RP\n"); result = -ENOMEM; goto uc_timeout; } rx_2->rx_ring_rp_pa_hi = (u32) ((va & 0xFFFFFFFF00000000) >> 32); rx_2->rx_ring_rp_pa = (u32) (va & 0xFFFFFFFF); IPADBG("RX_2 rx_ring_rp_pa_hi=0x%08x :0x%08x\n", rx_2->rx_ring_rp_pa_hi, rx_2->rx_ring_rp_pa); len = in->smmu_enabled ? in->u.ul_smmu.rdy_comp_ring_size : in->u.ul.rdy_comp_ring_size; IPADBG("RX_2 ring smmu_en=%d comp_ring_size=%d %d\n", in->smmu_enabled, in->u.ul_smmu.rdy_comp_ring_size, in->u.ul.rdy_comp_ring_size); if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_COMP_RING_RES, in->smmu_enabled, in->u.ul.rdy_comp_ring_base_pa, &in->u.ul_smmu.rdy_comp_ring, len, false, &va)) { IPAERR("fail to create uc RX_2 comp_ring.\n"); result = -ENOMEM; goto uc_timeout; } rx_2->rx_comp_ring_base_pa_hi = (u32) ((va & 0xFFFFFFFF00000000) >> 32); rx_2->rx_comp_ring_base_pa = (u32) (va & 0xFFFFFFFF); rx_2->rx_comp_ring_size = len; IPADBG("RX_2 rx_comp_ring_base_pa_hi=0x%08x:0x%08x\n", rx_2->rx_comp_ring_base_pa_hi, rx_2->rx_comp_ring_base_pa); pa = in->smmu_enabled ? in->u.ul_smmu.rdy_comp_ring_wp_pa : in->u.ul.rdy_comp_ring_wp_pa; if (ipa_create_uc_smmu_mapping( IPA_WDI_RX_COMP_RING_WP_RES, in->smmu_enabled, pa, NULL, 4, false, &va)) { IPAERR("fail to create uc RX_2 comp_rng WP\n"); result = -ENOMEM; goto uc_timeout; } rx_2->rx_comp_ring_wp_pa_hi = (u32) ((va & 0xFFFFFFFF00000000) >> 32); rx_2->rx_comp_ring_wp_pa = (u32) (va & 0xFFFFFFFF); IPADBG("RX_2 rx_comp_ring_wp_pa_hi=0x%08x:0x%08x\n", rx_2->rx_comp_ring_wp_pa_hi, rx_2->rx_comp_ring_wp_pa); rx_2->ipa_pipe_number = ipa_ep_idx; } else { rx = (struct IpaHwWdiRxSetUpCmdData_t *)cmd.base; len = in->smmu_enabled ? in->u.ul_smmu.rdy_ring_size : in->u.ul.rdy_ring_size; IPADBG("RX ring smmu_en=%d ring_size=%d %d\n", in->smmu_enabled, IPADBG("RX ring smmu_en=%d ring_size=%d %d\n", in->smmu_enabled, in->u.ul_smmu.rdy_ring_size, in->u.ul.rdy_ring_size); if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES, Loading Loading @@ -894,8 +1154,9 @@ int ipa2_connect_wdi_pipe(struct ipa_wdi_in_params *in, goto uc_timeout; } rx->rx_ring_rp_pa = va; rx->ipa_pipe_number = ipa_ep_idx; } if (ipa_ctx->ipa_hw_type >= IPA_HW_v2_5) { out->uc_door_bell_pa = ipa_ctx->ipa_wrapper_base + Loading Loading @@ -1127,6 +1388,7 @@ int ipa2_disable_wdi_pipe(u32 clnt_hdl) union IpaHwWdiCommonChCmdData_t disable; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; u32 prod_hdl; int i; if (unlikely(!ipa_ctx)) { IPAERR("IPA driver was not initialized\n"); Loading @@ -1143,6 +1405,28 @@ int ipa2_disable_wdi_pipe(u32 clnt_hdl) if (result) return result; /* checking rdy_ring_rp_pa matches the rdy_comp_ring_wp_pa on WDI2.0 */ if (ipa_ctx->ipa_wdi2) { for (i = 0; i < IPA_UC_FINISH_MAX; i++) { IPADBG("(%d) rp_value(%u), comp_wp_value(%u)\n", i, *ipa_ctx->uc_ctx.rdy_ring_rp_va, *ipa_ctx->uc_ctx.rdy_comp_ring_wp_va); if (*ipa_ctx->uc_ctx.rdy_ring_rp_va != *ipa_ctx->uc_ctx.rdy_comp_ring_wp_va) { usleep_range(IPA_UC_WAIT_MIN_SLEEP, IPA_UC_WAII_MAX_SLEEP); } else { break; } } /* In case ipa_uc still haven't processed all * pending descriptors, we have to assert */ if (i == IPA_UC_FINISH_MAX) BUG(); } IPADBG("ep=%d\n", clnt_hdl); ep = &ipa_ctx->ep[clnt_hdl]; Loading