Loading drivers/platform/msm/gsi/gsi.c +84 −0 Original line number Diff line number Diff line Loading @@ -2203,6 +2203,57 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl, } EXPORT_SYMBOL(gsi_alloc_channel); static int gsi_alloc_ap_channel(unsigned int chan_hdl) { struct gsi_chan_ctx *ctx; uint32_t val; int res; int ee; enum gsi_ch_cmd_opcode op = GSI_CH_ALLOCATE; if (!gsi_ctx) { pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); return -GSI_STATUS_NODEV; } ctx = &gsi_ctx->chan[chan_hdl]; if (ctx->allocated) { GSIERR("chan %d already allocated\n", chan_hdl); return -GSI_STATUS_NODEV; } memset(ctx, 0, sizeof(*ctx)); mutex_init(&ctx->mlock); init_completion(&ctx->compl); atomic_set(&ctx->poll_mode, GSI_CHAN_MODE_CALLBACK); mutex_lock(&gsi_ctx->mlock); ee = gsi_ctx->per.ee; gsi_ctx->ch_dbg[chan_hdl].ch_allocate++; val = (((chan_hdl << GSI_EE_n_GSI_CH_CMD_CHID_SHFT) & GSI_EE_n_GSI_CH_CMD_CHID_BMSK) | ((op << GSI_EE_n_GSI_CH_CMD_OPCODE_SHFT) & GSI_EE_n_GSI_CH_CMD_OPCODE_BMSK)); gsi_writel(val, gsi_ctx->base + GSI_EE_n_GSI_CH_CMD_OFFS(ee)); res = wait_for_completion_timeout(&ctx->compl, GSI_CMD_TIMEOUT); if (res == 0) { GSIERR("chan_hdl=%u timed out\n", chan_hdl); mutex_unlock(&gsi_ctx->mlock); return -GSI_STATUS_TIMED_OUT; } if (ctx->state != GSI_CHAN_STATE_ALLOCATED) { GSIERR("chan_hdl=%u allocation failed state=%d\n", chan_hdl, ctx->state); mutex_unlock(&gsi_ctx->mlock); return -GSI_STATUS_RES_ALLOC_FAILURE; } mutex_unlock(&gsi_ctx->mlock); return GSI_STATUS_SUCCESS; } static void __gsi_write_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch val) { Loading @@ -2221,6 +2272,36 @@ static void __gsi_write_channel_scratch(unsigned long chan_hdl, gsi_ctx->per.ee)); } int gsi_write_channel_scratch3_reg(unsigned long chan_hdl, union __packed gsi_wdi_channel_scratch3_reg val) { struct gsi_chan_ctx *ctx; if (!gsi_ctx) { pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); return -GSI_STATUS_NODEV; } if (chan_hdl >= gsi_ctx->max_ch) { GSIERR("bad params chan_hdl=%lu\n", chan_hdl); return -GSI_STATUS_INVALID_PARAMS; } ctx = &gsi_ctx->chan[chan_hdl]; mutex_lock(&ctx->mlock); ctx->scratch.wdi.endp_metadatareg_offset = val.wdi.endp_metadatareg_offset; ctx->scratch.wdi.qmap_id = val.wdi.qmap_id; gsi_writel(val.data.word1, gsi_ctx->base + GSI_EE_n_GSI_CH_k_SCRATCH_3_OFFS(chan_hdl, gsi_ctx->per.ee)); mutex_unlock(&ctx->mlock); return GSI_STATUS_SUCCESS; } static void __gsi_read_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch * val) { Loading Loading @@ -3632,6 +3713,9 @@ int gsi_alloc_channel_ee(unsigned int chan_idx, unsigned int ee, int *code) return -GSI_STATUS_INVALID_PARAMS; } if (ee == 0) return gsi_alloc_ap_channel(chan_idx); mutex_lock(&gsi_ctx->mlock); reinit_completion(&gsi_ctx->gen_ee_cmd_compl); Loading drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c +40 −79 Original line number Diff line number Diff line Loading @@ -1857,12 +1857,8 @@ int ipa3_disconnect_gsi_wdi_pipe(u32 clnt_hdl) if (!ep->keep_ipa_awake) IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(clnt_hdl)); result = gsi_reset_evt_ring(ep->gsi_evt_ring_hdl); if (result != GSI_STATUS_SUCCESS) { IPAERR("Failed to reset evt ring: %d.\n", result); goto fail_dealloc_channel; } ipa3_reset_gsi_channel(clnt_hdl); ipa3_reset_gsi_event_ring(clnt_hdl); if (!ep->keep_ipa_awake) IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl)); Loading Loading @@ -2223,6 +2219,8 @@ int ipa3_resume_gsi_wdi_pipe(u32 clnt_hdl) int result = 0; struct ipa3_ep_context *ep; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; struct gsi_chan_info chan_info; union __packed gsi_channel_scratch gsi_scratch; IPADBG("ep=%d\n", clnt_hdl); ep = &ipa3_ctx->ep[clnt_hdl]; Loading @@ -2246,6 +2244,19 @@ int ipa3_resume_gsi_wdi_pipe(u32 clnt_hdl) IPAERR("gsi_start_channel failed %d\n", result); ipa_assert(); } gsi_query_channel_info(ep->gsi_chan_hdl, &chan_info); gsi_read_channel_scratch(ep->gsi_chan_hdl, &gsi_scratch); IPADBG("ch=%lu channel base = 0x%llx , event base 0x%llx\n", ep->gsi_chan_hdl, ep->gsi_mem_info.chan_ring_base_addr, ep->gsi_mem_info.evt_ring_base_addr); IPADBG("RP=0x%llx WP=0x%llx ev_valid=%d ERP=0x%llx EWP=0x%llx\n", chan_info.rp, chan_info.wp, chan_info.evt_valid, chan_info.evt_rp, chan_info.evt_wp); IPADBG("Scratch 0 = %x Scratch 1 = %x Scratch 2 = %x Scratch 3 = %x\n", gsi_scratch.data.word1, gsi_scratch.data.word2, gsi_scratch.data.word3, gsi_scratch.data.word4); ep->gsi_offload_state |= IPA_WDI_RESUMED; IPADBG("exit\n"); return result; Loading Loading @@ -2324,6 +2335,8 @@ int ipa3_suspend_gsi_wdi_pipe(u32 clnt_hdl) bool disable_force_clear = false; struct ipahal_ep_cfg_ctrl_scnd ep_ctrl_scnd = { 0 }; int retry_cnt = 0; struct gsi_chan_info chan_info; union __packed gsi_channel_scratch gsi_scratch; ipa_ep_idx = ipa3_get_ep_mapping(ipa3_get_client_mapping(clnt_hdl)); if (ipa_ep_idx < 0) { Loading Loading @@ -2373,14 +2386,22 @@ int ipa3_suspend_gsi_wdi_pipe(u32 clnt_hdl) } else { IPADBG("GSI channel %ld STOP\n", ep->gsi_chan_hdl); } res = ipa3_reset_gsi_channel(clnt_hdl); if (res != GSI_STATUS_SUCCESS) { IPAERR("Failed to reset chan: %d.\n", res); goto fail_stop_channel; gsi_query_channel_info(ep->gsi_chan_hdl, &chan_info); gsi_read_channel_scratch(ep->gsi_chan_hdl, &gsi_scratch); IPADBG("ch=%lu channel base = 0x%llx , event base 0x%llx\n", ep->gsi_chan_hdl, ep->gsi_mem_info.chan_ring_base_addr, ep->gsi_mem_info.evt_ring_base_addr); IPADBG("RP=0x%llx WP=0x%llx ev_valid=%d ERP=0x%llx", chan_info.rp, chan_info.wp, chan_info.evt_valid, chan_info.evt_rp); IPADBG("EWP=0x%llx\n", chan_info.evt_wp); IPADBG("Scratch 0 = %x Scratch 1 = %x Scratch 2 = %x", gsi_scratch.data.word1, gsi_scratch.data.word2, gsi_scratch.data.word3); IPADBG("Scratch 3 = %x\n", gsi_scratch.data.word4); } } if (disable_force_clear) ipa3_disable_force_clear(clnt_hdl); IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl)); Loading Loading @@ -2539,87 +2560,27 @@ int ipa3_write_qmapid_gsi_wdi_pipe(u32 clnt_hdl, u8 qmap_id) { int result = 0; struct ipa3_ep_context *ep; union __packed gsi_channel_scratch gsi_scratch; int retry_cnt = 0; u32 source_pipe_bitmask = 0; bool disable_force_clear = false; struct ipahal_ep_cfg_ctrl_scnd ep_ctrl_scnd = { 0 }; union __packed gsi_wdi_channel_scratch3_reg gsi_scratch; memset(&gsi_scratch, 0, sizeof(gsi_scratch)); ep = &ipa3_ctx->ep[clnt_hdl]; IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(clnt_hdl)); result = gsi_read_channel_scratch(ep->gsi_chan_hdl, &gsi_scratch); if (result != GSI_STATUS_SUCCESS) { IPAERR("gsi_read_write_channel_scratch failed %d\n", result); goto fail_read_channel_scratch; } if (ep->gsi_offload_state == (IPA_WDI_CONNECTED | IPA_WDI_ENABLED | IPA_WDI_RESUMED)) { source_pipe_bitmask = 1 << ipa3_get_ep_mapping(ep->client); result = ipa3_enable_force_clear(clnt_hdl, false, source_pipe_bitmask); if (result) { /* * assuming here modem SSR, AP can remove * the delay in this case */ IPAERR("failed to force clear %d\n", result); IPAERR("remove delay from SCND reg\n"); ep_ctrl_scnd.endp_delay = false; ipahal_write_reg_n_fields( IPA_ENDP_INIT_CTRL_SCND_n, clnt_hdl, &ep_ctrl_scnd); } else { disable_force_clear = true; } retry_gsi_stop: result = ipa3_stop_gsi_channel(clnt_hdl); if (result != 0 && result != -GSI_STATUS_AGAIN && result != -GSI_STATUS_TIMED_OUT) { IPAERR("GSI stop channel failed %d\n", result); goto fail_stop_channel; } else if (result == -GSI_STATUS_AGAIN) { IPADBG("GSI stop channel failed retry cnt = %d\n", retry_cnt); retry_cnt++; if (retry_cnt >= GSI_STOP_MAX_RETRY_CNT) goto fail_stop_channel; goto retry_gsi_stop; } else { IPADBG("GSI channel %ld STOP\n", ep->gsi_chan_hdl); } } gsi_scratch.wdi.qmap_id = qmap_id; result = gsi_write_channel_scratch(ep->gsi_chan_hdl, gsi_scratch); gsi_scratch.wdi.endp_metadatareg_offset = ipahal_get_reg_mn_ofst( IPA_ENDP_INIT_HDR_METADATA_n, 0, clnt_hdl)/4; result = gsi_write_channel_scratch3_reg(ep->gsi_chan_hdl, gsi_scratch); if (result != GSI_STATUS_SUCCESS) { IPAERR("gsi_write_channel_scratch failed %d\n", result); goto fail_write_channel_scratch; } if (ep->gsi_offload_state == (IPA_WDI_CONNECTED | IPA_WDI_ENABLED | IPA_WDI_RESUMED)) { result = gsi_start_channel(ep->gsi_chan_hdl); if (result != GSI_STATUS_SUCCESS) { IPAERR("gsi_start_channel failed %d\n", result); goto fail_start_channel; } } if (disable_force_clear) ipa3_disable_force_clear(clnt_hdl); IPADBG("client (ep: %d) qmap_id %d updated\n", clnt_hdl, qmap_id); IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl)); return 0; fail_start_channel: fail_read_channel_scratch: fail_write_channel_scratch: fail_stop_channel: ipa_assert(); return result; } Loading include/linux/msm_gsi.h +40 −0 Original line number Diff line number Diff line Loading @@ -690,6 +690,28 @@ union __packed gsi_channel_scratch { } data; }; /** * gsi_wdi_channel_scratch3 - WDI protocol SW config area of * channel scratch3 */ struct __packed gsi_wdi_channel_scratch3 { uint32_t endp_metadatareg_offset:16; uint32_t qmap_id:16; }; /** * gsi_wdi_channel_scratch3_reg - channel scratch3 SW config area * */ union __packed gsi_wdi_channel_scratch3_reg { struct __packed gsi_wdi_channel_scratch3 wdi; struct __packed { uint32_t word1; } data; }; /** * gsi_mhi_evt_scratch - MHI protocol SW config area of * event scratch Loading Loading @@ -976,6 +998,19 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl, int gsi_write_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch val); /** * gsi_write_channel_scratch3_reg - Peripheral should call this function to * write to the scratch3 reg area of the channel context * * @chan_hdl: Client handle previously obtained from * gsi_alloc_channel * @val: Value to write * * @Return gsi_status */ int gsi_write_channel_scratch3_reg(unsigned long chan_hdl, union __packed gsi_wdi_channel_scratch3_reg val); /** * gsi_read_channel_scratch - Peripheral should call this function to * read to the scratch area of the channel context Loading Loading @@ -1408,6 +1443,11 @@ static inline int gsi_write_channel_scratch(unsigned long chan_hdl, { return -GSI_STATUS_UNSUPPORTED_OP; } static inline int gsi_write_channel_scratch3_reg(unsigned long chan_hdl, union __packed gsi_wdi_channel_scratch3_reg val) { return -GSI_STATUS_UNSUPPORTED_OP; } static inline int gsi_read_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch *val) Loading Loading
drivers/platform/msm/gsi/gsi.c +84 −0 Original line number Diff line number Diff line Loading @@ -2203,6 +2203,57 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl, } EXPORT_SYMBOL(gsi_alloc_channel); static int gsi_alloc_ap_channel(unsigned int chan_hdl) { struct gsi_chan_ctx *ctx; uint32_t val; int res; int ee; enum gsi_ch_cmd_opcode op = GSI_CH_ALLOCATE; if (!gsi_ctx) { pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); return -GSI_STATUS_NODEV; } ctx = &gsi_ctx->chan[chan_hdl]; if (ctx->allocated) { GSIERR("chan %d already allocated\n", chan_hdl); return -GSI_STATUS_NODEV; } memset(ctx, 0, sizeof(*ctx)); mutex_init(&ctx->mlock); init_completion(&ctx->compl); atomic_set(&ctx->poll_mode, GSI_CHAN_MODE_CALLBACK); mutex_lock(&gsi_ctx->mlock); ee = gsi_ctx->per.ee; gsi_ctx->ch_dbg[chan_hdl].ch_allocate++; val = (((chan_hdl << GSI_EE_n_GSI_CH_CMD_CHID_SHFT) & GSI_EE_n_GSI_CH_CMD_CHID_BMSK) | ((op << GSI_EE_n_GSI_CH_CMD_OPCODE_SHFT) & GSI_EE_n_GSI_CH_CMD_OPCODE_BMSK)); gsi_writel(val, gsi_ctx->base + GSI_EE_n_GSI_CH_CMD_OFFS(ee)); res = wait_for_completion_timeout(&ctx->compl, GSI_CMD_TIMEOUT); if (res == 0) { GSIERR("chan_hdl=%u timed out\n", chan_hdl); mutex_unlock(&gsi_ctx->mlock); return -GSI_STATUS_TIMED_OUT; } if (ctx->state != GSI_CHAN_STATE_ALLOCATED) { GSIERR("chan_hdl=%u allocation failed state=%d\n", chan_hdl, ctx->state); mutex_unlock(&gsi_ctx->mlock); return -GSI_STATUS_RES_ALLOC_FAILURE; } mutex_unlock(&gsi_ctx->mlock); return GSI_STATUS_SUCCESS; } static void __gsi_write_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch val) { Loading @@ -2221,6 +2272,36 @@ static void __gsi_write_channel_scratch(unsigned long chan_hdl, gsi_ctx->per.ee)); } int gsi_write_channel_scratch3_reg(unsigned long chan_hdl, union __packed gsi_wdi_channel_scratch3_reg val) { struct gsi_chan_ctx *ctx; if (!gsi_ctx) { pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); return -GSI_STATUS_NODEV; } if (chan_hdl >= gsi_ctx->max_ch) { GSIERR("bad params chan_hdl=%lu\n", chan_hdl); return -GSI_STATUS_INVALID_PARAMS; } ctx = &gsi_ctx->chan[chan_hdl]; mutex_lock(&ctx->mlock); ctx->scratch.wdi.endp_metadatareg_offset = val.wdi.endp_metadatareg_offset; ctx->scratch.wdi.qmap_id = val.wdi.qmap_id; gsi_writel(val.data.word1, gsi_ctx->base + GSI_EE_n_GSI_CH_k_SCRATCH_3_OFFS(chan_hdl, gsi_ctx->per.ee)); mutex_unlock(&ctx->mlock); return GSI_STATUS_SUCCESS; } static void __gsi_read_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch * val) { Loading Loading @@ -3632,6 +3713,9 @@ int gsi_alloc_channel_ee(unsigned int chan_idx, unsigned int ee, int *code) return -GSI_STATUS_INVALID_PARAMS; } if (ee == 0) return gsi_alloc_ap_channel(chan_idx); mutex_lock(&gsi_ctx->mlock); reinit_completion(&gsi_ctx->gen_ee_cmd_compl); Loading
drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c +40 −79 Original line number Diff line number Diff line Loading @@ -1857,12 +1857,8 @@ int ipa3_disconnect_gsi_wdi_pipe(u32 clnt_hdl) if (!ep->keep_ipa_awake) IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(clnt_hdl)); result = gsi_reset_evt_ring(ep->gsi_evt_ring_hdl); if (result != GSI_STATUS_SUCCESS) { IPAERR("Failed to reset evt ring: %d.\n", result); goto fail_dealloc_channel; } ipa3_reset_gsi_channel(clnt_hdl); ipa3_reset_gsi_event_ring(clnt_hdl); if (!ep->keep_ipa_awake) IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl)); Loading Loading @@ -2223,6 +2219,8 @@ int ipa3_resume_gsi_wdi_pipe(u32 clnt_hdl) int result = 0; struct ipa3_ep_context *ep; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; struct gsi_chan_info chan_info; union __packed gsi_channel_scratch gsi_scratch; IPADBG("ep=%d\n", clnt_hdl); ep = &ipa3_ctx->ep[clnt_hdl]; Loading @@ -2246,6 +2244,19 @@ int ipa3_resume_gsi_wdi_pipe(u32 clnt_hdl) IPAERR("gsi_start_channel failed %d\n", result); ipa_assert(); } gsi_query_channel_info(ep->gsi_chan_hdl, &chan_info); gsi_read_channel_scratch(ep->gsi_chan_hdl, &gsi_scratch); IPADBG("ch=%lu channel base = 0x%llx , event base 0x%llx\n", ep->gsi_chan_hdl, ep->gsi_mem_info.chan_ring_base_addr, ep->gsi_mem_info.evt_ring_base_addr); IPADBG("RP=0x%llx WP=0x%llx ev_valid=%d ERP=0x%llx EWP=0x%llx\n", chan_info.rp, chan_info.wp, chan_info.evt_valid, chan_info.evt_rp, chan_info.evt_wp); IPADBG("Scratch 0 = %x Scratch 1 = %x Scratch 2 = %x Scratch 3 = %x\n", gsi_scratch.data.word1, gsi_scratch.data.word2, gsi_scratch.data.word3, gsi_scratch.data.word4); ep->gsi_offload_state |= IPA_WDI_RESUMED; IPADBG("exit\n"); return result; Loading Loading @@ -2324,6 +2335,8 @@ int ipa3_suspend_gsi_wdi_pipe(u32 clnt_hdl) bool disable_force_clear = false; struct ipahal_ep_cfg_ctrl_scnd ep_ctrl_scnd = { 0 }; int retry_cnt = 0; struct gsi_chan_info chan_info; union __packed gsi_channel_scratch gsi_scratch; ipa_ep_idx = ipa3_get_ep_mapping(ipa3_get_client_mapping(clnt_hdl)); if (ipa_ep_idx < 0) { Loading Loading @@ -2373,14 +2386,22 @@ int ipa3_suspend_gsi_wdi_pipe(u32 clnt_hdl) } else { IPADBG("GSI channel %ld STOP\n", ep->gsi_chan_hdl); } res = ipa3_reset_gsi_channel(clnt_hdl); if (res != GSI_STATUS_SUCCESS) { IPAERR("Failed to reset chan: %d.\n", res); goto fail_stop_channel; gsi_query_channel_info(ep->gsi_chan_hdl, &chan_info); gsi_read_channel_scratch(ep->gsi_chan_hdl, &gsi_scratch); IPADBG("ch=%lu channel base = 0x%llx , event base 0x%llx\n", ep->gsi_chan_hdl, ep->gsi_mem_info.chan_ring_base_addr, ep->gsi_mem_info.evt_ring_base_addr); IPADBG("RP=0x%llx WP=0x%llx ev_valid=%d ERP=0x%llx", chan_info.rp, chan_info.wp, chan_info.evt_valid, chan_info.evt_rp); IPADBG("EWP=0x%llx\n", chan_info.evt_wp); IPADBG("Scratch 0 = %x Scratch 1 = %x Scratch 2 = %x", gsi_scratch.data.word1, gsi_scratch.data.word2, gsi_scratch.data.word3); IPADBG("Scratch 3 = %x\n", gsi_scratch.data.word4); } } if (disable_force_clear) ipa3_disable_force_clear(clnt_hdl); IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl)); Loading Loading @@ -2539,87 +2560,27 @@ int ipa3_write_qmapid_gsi_wdi_pipe(u32 clnt_hdl, u8 qmap_id) { int result = 0; struct ipa3_ep_context *ep; union __packed gsi_channel_scratch gsi_scratch; int retry_cnt = 0; u32 source_pipe_bitmask = 0; bool disable_force_clear = false; struct ipahal_ep_cfg_ctrl_scnd ep_ctrl_scnd = { 0 }; union __packed gsi_wdi_channel_scratch3_reg gsi_scratch; memset(&gsi_scratch, 0, sizeof(gsi_scratch)); ep = &ipa3_ctx->ep[clnt_hdl]; IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(clnt_hdl)); result = gsi_read_channel_scratch(ep->gsi_chan_hdl, &gsi_scratch); if (result != GSI_STATUS_SUCCESS) { IPAERR("gsi_read_write_channel_scratch failed %d\n", result); goto fail_read_channel_scratch; } if (ep->gsi_offload_state == (IPA_WDI_CONNECTED | IPA_WDI_ENABLED | IPA_WDI_RESUMED)) { source_pipe_bitmask = 1 << ipa3_get_ep_mapping(ep->client); result = ipa3_enable_force_clear(clnt_hdl, false, source_pipe_bitmask); if (result) { /* * assuming here modem SSR, AP can remove * the delay in this case */ IPAERR("failed to force clear %d\n", result); IPAERR("remove delay from SCND reg\n"); ep_ctrl_scnd.endp_delay = false; ipahal_write_reg_n_fields( IPA_ENDP_INIT_CTRL_SCND_n, clnt_hdl, &ep_ctrl_scnd); } else { disable_force_clear = true; } retry_gsi_stop: result = ipa3_stop_gsi_channel(clnt_hdl); if (result != 0 && result != -GSI_STATUS_AGAIN && result != -GSI_STATUS_TIMED_OUT) { IPAERR("GSI stop channel failed %d\n", result); goto fail_stop_channel; } else if (result == -GSI_STATUS_AGAIN) { IPADBG("GSI stop channel failed retry cnt = %d\n", retry_cnt); retry_cnt++; if (retry_cnt >= GSI_STOP_MAX_RETRY_CNT) goto fail_stop_channel; goto retry_gsi_stop; } else { IPADBG("GSI channel %ld STOP\n", ep->gsi_chan_hdl); } } gsi_scratch.wdi.qmap_id = qmap_id; result = gsi_write_channel_scratch(ep->gsi_chan_hdl, gsi_scratch); gsi_scratch.wdi.endp_metadatareg_offset = ipahal_get_reg_mn_ofst( IPA_ENDP_INIT_HDR_METADATA_n, 0, clnt_hdl)/4; result = gsi_write_channel_scratch3_reg(ep->gsi_chan_hdl, gsi_scratch); if (result != GSI_STATUS_SUCCESS) { IPAERR("gsi_write_channel_scratch failed %d\n", result); goto fail_write_channel_scratch; } if (ep->gsi_offload_state == (IPA_WDI_CONNECTED | IPA_WDI_ENABLED | IPA_WDI_RESUMED)) { result = gsi_start_channel(ep->gsi_chan_hdl); if (result != GSI_STATUS_SUCCESS) { IPAERR("gsi_start_channel failed %d\n", result); goto fail_start_channel; } } if (disable_force_clear) ipa3_disable_force_clear(clnt_hdl); IPADBG("client (ep: %d) qmap_id %d updated\n", clnt_hdl, qmap_id); IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl)); return 0; fail_start_channel: fail_read_channel_scratch: fail_write_channel_scratch: fail_stop_channel: ipa_assert(); return result; } Loading
include/linux/msm_gsi.h +40 −0 Original line number Diff line number Diff line Loading @@ -690,6 +690,28 @@ union __packed gsi_channel_scratch { } data; }; /** * gsi_wdi_channel_scratch3 - WDI protocol SW config area of * channel scratch3 */ struct __packed gsi_wdi_channel_scratch3 { uint32_t endp_metadatareg_offset:16; uint32_t qmap_id:16; }; /** * gsi_wdi_channel_scratch3_reg - channel scratch3 SW config area * */ union __packed gsi_wdi_channel_scratch3_reg { struct __packed gsi_wdi_channel_scratch3 wdi; struct __packed { uint32_t word1; } data; }; /** * gsi_mhi_evt_scratch - MHI protocol SW config area of * event scratch Loading Loading @@ -976,6 +998,19 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl, int gsi_write_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch val); /** * gsi_write_channel_scratch3_reg - Peripheral should call this function to * write to the scratch3 reg area of the channel context * * @chan_hdl: Client handle previously obtained from * gsi_alloc_channel * @val: Value to write * * @Return gsi_status */ int gsi_write_channel_scratch3_reg(unsigned long chan_hdl, union __packed gsi_wdi_channel_scratch3_reg val); /** * gsi_read_channel_scratch - Peripheral should call this function to * read to the scratch area of the channel context Loading Loading @@ -1408,6 +1443,11 @@ static inline int gsi_write_channel_scratch(unsigned long chan_hdl, { return -GSI_STATUS_UNSUPPORTED_OP; } static inline int gsi_write_channel_scratch3_reg(unsigned long chan_hdl, union __packed gsi_wdi_channel_scratch3_reg val) { return -GSI_STATUS_UNSUPPORTED_OP; } static inline int gsi_read_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch *val) Loading