Loading drivers/platform/msm/ipa/ipa_clients/ipa_usb.c +31 −0 Original line number Diff line number Diff line Loading @@ -2147,6 +2147,18 @@ static void ipa_usb_debugfs_init(void){} static void ipa_usb_debugfs_remove(void){} #endif /* CONFIG_DEBUG_FS */ static int ipa_usb_set_lock_unlock(bool is_lock) { IPA_USB_DBG("entry\n"); if (is_lock) mutex_lock(&ipa3_usb_ctx->general_mutex); else mutex_unlock(&ipa3_usb_ctx->general_mutex); IPA_USB_DBG("exit\n"); return 0; } int ipa_usb_xdci_connect(struct ipa_usb_xdci_chan_params *ul_chan_params, Loading Loading @@ -2210,6 +2222,16 @@ int ipa_usb_xdci_connect(struct ipa_usb_xdci_chan_params *ul_chan_params, goto connect_fail; } /* * Register for xdci lock/unlock callback with ipa core driver. * As per use case, only register for IPA_CONS end point for now. * If needed we can include the same for IPA_PROD ep. * For IPA_USB_DIAG/DPL config there will not be any UL ep. */ if (connect_params->teth_prot != IPA_USB_DIAG) ipa3_register_lock_unlock_callback(&ipa_usb_set_lock_unlock, ul_out_params->clnt_hdl); IPA_USB_DBG_LOW("exit\n"); mutex_unlock(&ipa3_usb_ctx->general_mutex); return 0; Loading Loading @@ -2287,6 +2309,15 @@ static int ipa_usb_xdci_dismiss_channels(u32 ul_clnt_hdl, u32 dl_clnt_hdl, } } /* * Deregister for xdci lock/unlock callback from ipa core driver. * As per use case, only deregister for IPA_CONS end point for now. * If needed we can include the same for IPA_PROD ep. * For IPA_USB_DIAG/DPL config there will not be any UL config. */ if (!IPA3_USB_IS_TTYPE_DPL(ttype)) ipa3_deregister_lock_unlock_callback(ul_clnt_hdl); /* Change state to STOPPED */ if (!ipa3_usb_set_state(IPA_USB_STOPPED, false, ttype)) IPA_USB_ERR("failed to change state to stopped\n"); Loading drivers/platform/msm/ipa/ipa_v3/ipa.c +2 −0 Original line number Diff line number Diff line Loading @@ -2604,6 +2604,8 @@ void ipa3_q6_pre_shutdown_cleanup(void) */ ipa3_q6_pipe_delay(false); ipa3_set_usb_prod_pipe_delay(); IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); IPADBG_LOW("Exit with success\n"); } Loading drivers/platform/msm/ipa/ipa_v3/ipa_client.c +103 −0 Original line number Diff line number Diff line Loading @@ -640,6 +640,69 @@ int ipa3_smmu_map_peer_buff(u64 iova, u32 size, bool map, struct sg_table *sgt, return 0; } void ipa3_register_lock_unlock_callback(int (*client_cb)(bool is_lock), u32 ipa_ep_idx) { struct ipa3_ep_context *ep; IPADBG("entry\n"); ep = &ipa3_ctx->ep[ipa_ep_idx]; if (!ep->valid) { IPAERR("Invalid EP\n"); return; } if (client_cb == NULL) { IPAERR("Bad Param"); return; } ep->client_lock_unlock = client_cb; IPADBG("exit\n"); } void ipa3_deregister_lock_unlock_callback(u32 ipa_ep_idx) { struct ipa3_ep_context *ep; IPADBG("entry\n"); ep = &ipa3_ctx->ep[ipa_ep_idx]; if (!ep->valid) { IPAERR("Invalid EP\n"); return; } if (ep->client_lock_unlock == NULL) { IPAERR("client_lock_unlock is already NULL"); return; } ep->client_lock_unlock = NULL; IPADBG("exit\n"); } static void client_lock_unlock_cb(u32 ipa_ep_idx, bool is_lock) { struct ipa3_ep_context *ep; IPADBG("entry\n"); ep = &ipa3_ctx->ep[ipa_ep_idx]; if (!ep->valid) { IPAERR("Invalid EP\n"); return; } if (ep->client_lock_unlock) ep->client_lock_unlock(is_lock); IPADBG("exit\n"); } int ipa3_request_gsi_channel(struct ipa_request_gsi_channel_params *params, struct ipa_req_chan_out_params *out_params) Loading Loading @@ -1265,6 +1328,46 @@ static int ipa3_stop_ul_chan_with_data_drain(u32 qmi_req_id, return result; } /* * Set USB PROD pipe delay for MBIM/RMNET config * Clocks, should be voted before calling this API * locks should be taken before calling this API */ void ipa3_set_usb_prod_pipe_delay(void) { int result; int pipe_idx; struct ipa3_ep_context *ep; struct ipa_ep_cfg_ctrl ep_ctrl; memset(&ep_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); ep_ctrl.ipa_ep_delay = true; pipe_idx = ipa3_get_ep_mapping(IPA_CLIENT_USB_PROD); if (pipe_idx == IPA_EP_NOT_ALLOCATED) { IPAERR("client (%d) not valid\n", IPA_CLIENT_USB_PROD); return; } ep = &ipa3_ctx->ep[pipe_idx]; /* Setting delay on USB_PROD with skip_ep_cfg */ client_lock_unlock_cb(pipe_idx, true); if (ep->valid && ep->skip_ep_cfg) { ep->ep_delay_set = ep_ctrl.ipa_ep_delay; result = ipa3_cfg_ep_ctrl(pipe_idx, &ep_ctrl); if (result) IPAERR("client (ep: %d) failed result=%d\n", pipe_idx, result); else IPADBG("client (ep: %d) success\n", pipe_idx); } client_lock_unlock_cb(pipe_idx, false); } void ipa3_xdci_ep_delay_rm(u32 clnt_hdl) { struct ipa3_ep_context *ep; Loading drivers/platform/msm/ipa/ipa_v3/ipa_i.h +7 −0 Original line number Diff line number Diff line Loading @@ -564,6 +564,8 @@ struct ipa3_status_stats { * @qmi_request_sent: Indicates whether QMI request to enable clear data path * request is sent or not. * @napi_enabled: when true, IPA call client callback to start polling * @client_lock_unlock: callback function to take mutex lock/unlock for USB * clients */ struct ipa3_ep_context { int valid; Loading Loading @@ -596,6 +598,8 @@ struct ipa3_ep_context { u32 eot_in_poll_err; bool ep_delay_set; int (*client_lock_unlock)(bool is_lock); /* sys MUST be the last element of this struct */ struct ipa3_sys_context *sys; }; Loading Loading @@ -1732,6 +1736,9 @@ int ipa3_xdci_connect(u32 clnt_hdl); int ipa3_xdci_disconnect(u32 clnt_hdl, bool should_force_clear, u32 qmi_req_id); void ipa3_xdci_ep_delay_rm(u32 clnt_hdl); void ipa3_register_lock_unlock_callback(int (*client_cb)(bool), u32 ipa_ep_idx); void ipa3_deregister_lock_unlock_callback(u32 ipa_ep_idx); void ipa3_set_usb_prod_pipe_delay(void); int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, bool should_force_clear, u32 qmi_req_id, bool is_dpl); Loading Loading
drivers/platform/msm/ipa/ipa_clients/ipa_usb.c +31 −0 Original line number Diff line number Diff line Loading @@ -2147,6 +2147,18 @@ static void ipa_usb_debugfs_init(void){} static void ipa_usb_debugfs_remove(void){} #endif /* CONFIG_DEBUG_FS */ static int ipa_usb_set_lock_unlock(bool is_lock) { IPA_USB_DBG("entry\n"); if (is_lock) mutex_lock(&ipa3_usb_ctx->general_mutex); else mutex_unlock(&ipa3_usb_ctx->general_mutex); IPA_USB_DBG("exit\n"); return 0; } int ipa_usb_xdci_connect(struct ipa_usb_xdci_chan_params *ul_chan_params, Loading Loading @@ -2210,6 +2222,16 @@ int ipa_usb_xdci_connect(struct ipa_usb_xdci_chan_params *ul_chan_params, goto connect_fail; } /* * Register for xdci lock/unlock callback with ipa core driver. * As per use case, only register for IPA_CONS end point for now. * If needed we can include the same for IPA_PROD ep. * For IPA_USB_DIAG/DPL config there will not be any UL ep. */ if (connect_params->teth_prot != IPA_USB_DIAG) ipa3_register_lock_unlock_callback(&ipa_usb_set_lock_unlock, ul_out_params->clnt_hdl); IPA_USB_DBG_LOW("exit\n"); mutex_unlock(&ipa3_usb_ctx->general_mutex); return 0; Loading Loading @@ -2287,6 +2309,15 @@ static int ipa_usb_xdci_dismiss_channels(u32 ul_clnt_hdl, u32 dl_clnt_hdl, } } /* * Deregister for xdci lock/unlock callback from ipa core driver. * As per use case, only deregister for IPA_CONS end point for now. * If needed we can include the same for IPA_PROD ep. * For IPA_USB_DIAG/DPL config there will not be any UL config. */ if (!IPA3_USB_IS_TTYPE_DPL(ttype)) ipa3_deregister_lock_unlock_callback(ul_clnt_hdl); /* Change state to STOPPED */ if (!ipa3_usb_set_state(IPA_USB_STOPPED, false, ttype)) IPA_USB_ERR("failed to change state to stopped\n"); Loading
drivers/platform/msm/ipa/ipa_v3/ipa.c +2 −0 Original line number Diff line number Diff line Loading @@ -2604,6 +2604,8 @@ void ipa3_q6_pre_shutdown_cleanup(void) */ ipa3_q6_pipe_delay(false); ipa3_set_usb_prod_pipe_delay(); IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); IPADBG_LOW("Exit with success\n"); } Loading
drivers/platform/msm/ipa/ipa_v3/ipa_client.c +103 −0 Original line number Diff line number Diff line Loading @@ -640,6 +640,69 @@ int ipa3_smmu_map_peer_buff(u64 iova, u32 size, bool map, struct sg_table *sgt, return 0; } void ipa3_register_lock_unlock_callback(int (*client_cb)(bool is_lock), u32 ipa_ep_idx) { struct ipa3_ep_context *ep; IPADBG("entry\n"); ep = &ipa3_ctx->ep[ipa_ep_idx]; if (!ep->valid) { IPAERR("Invalid EP\n"); return; } if (client_cb == NULL) { IPAERR("Bad Param"); return; } ep->client_lock_unlock = client_cb; IPADBG("exit\n"); } void ipa3_deregister_lock_unlock_callback(u32 ipa_ep_idx) { struct ipa3_ep_context *ep; IPADBG("entry\n"); ep = &ipa3_ctx->ep[ipa_ep_idx]; if (!ep->valid) { IPAERR("Invalid EP\n"); return; } if (ep->client_lock_unlock == NULL) { IPAERR("client_lock_unlock is already NULL"); return; } ep->client_lock_unlock = NULL; IPADBG("exit\n"); } static void client_lock_unlock_cb(u32 ipa_ep_idx, bool is_lock) { struct ipa3_ep_context *ep; IPADBG("entry\n"); ep = &ipa3_ctx->ep[ipa_ep_idx]; if (!ep->valid) { IPAERR("Invalid EP\n"); return; } if (ep->client_lock_unlock) ep->client_lock_unlock(is_lock); IPADBG("exit\n"); } int ipa3_request_gsi_channel(struct ipa_request_gsi_channel_params *params, struct ipa_req_chan_out_params *out_params) Loading Loading @@ -1265,6 +1328,46 @@ static int ipa3_stop_ul_chan_with_data_drain(u32 qmi_req_id, return result; } /* * Set USB PROD pipe delay for MBIM/RMNET config * Clocks, should be voted before calling this API * locks should be taken before calling this API */ void ipa3_set_usb_prod_pipe_delay(void) { int result; int pipe_idx; struct ipa3_ep_context *ep; struct ipa_ep_cfg_ctrl ep_ctrl; memset(&ep_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); ep_ctrl.ipa_ep_delay = true; pipe_idx = ipa3_get_ep_mapping(IPA_CLIENT_USB_PROD); if (pipe_idx == IPA_EP_NOT_ALLOCATED) { IPAERR("client (%d) not valid\n", IPA_CLIENT_USB_PROD); return; } ep = &ipa3_ctx->ep[pipe_idx]; /* Setting delay on USB_PROD with skip_ep_cfg */ client_lock_unlock_cb(pipe_idx, true); if (ep->valid && ep->skip_ep_cfg) { ep->ep_delay_set = ep_ctrl.ipa_ep_delay; result = ipa3_cfg_ep_ctrl(pipe_idx, &ep_ctrl); if (result) IPAERR("client (ep: %d) failed result=%d\n", pipe_idx, result); else IPADBG("client (ep: %d) success\n", pipe_idx); } client_lock_unlock_cb(pipe_idx, false); } void ipa3_xdci_ep_delay_rm(u32 clnt_hdl) { struct ipa3_ep_context *ep; Loading
drivers/platform/msm/ipa/ipa_v3/ipa_i.h +7 −0 Original line number Diff line number Diff line Loading @@ -564,6 +564,8 @@ struct ipa3_status_stats { * @qmi_request_sent: Indicates whether QMI request to enable clear data path * request is sent or not. * @napi_enabled: when true, IPA call client callback to start polling * @client_lock_unlock: callback function to take mutex lock/unlock for USB * clients */ struct ipa3_ep_context { int valid; Loading Loading @@ -596,6 +598,8 @@ struct ipa3_ep_context { u32 eot_in_poll_err; bool ep_delay_set; int (*client_lock_unlock)(bool is_lock); /* sys MUST be the last element of this struct */ struct ipa3_sys_context *sys; }; Loading Loading @@ -1732,6 +1736,9 @@ int ipa3_xdci_connect(u32 clnt_hdl); int ipa3_xdci_disconnect(u32 clnt_hdl, bool should_force_clear, u32 qmi_req_id); void ipa3_xdci_ep_delay_rm(u32 clnt_hdl); void ipa3_register_lock_unlock_callback(int (*client_cb)(bool), u32 ipa_ep_idx); void ipa3_deregister_lock_unlock_callback(u32 ipa_ep_idx); void ipa3_set_usb_prod_pipe_delay(void); int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, bool should_force_clear, u32 qmi_req_id, bool is_dpl); Loading