Loading drivers/platform/msm/ipa/ipa_clients/ipa_usb.c +26 −180 Original line number Diff line number Diff line /* Copyright (c) 2015, 2016 The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -125,7 +125,6 @@ enum ipa3_usb_state { IPA_USB_CONNECTED, IPA_USB_STOPPED, IPA_USB_SUSPEND_REQUESTED, IPA_USB_SUSPEND_IN_PROGRESS, IPA_USB_SUSPENDED, IPA_USB_SUSPENDED_NO_RWAKEUP, IPA_USB_RESUME_IN_PROGRESS Loading @@ -146,13 +145,6 @@ enum ipa3_usb_transport_type { #define IPA3_USB_IS_TTYPE_DPL(__ttype) \ ((__ttype) == IPA_USB_TRANSPORT_DPL) struct finish_suspend_work_context { struct work_struct work; enum ipa3_usb_transport_type ttype; u32 dl_clnt_hdl; u32 ul_clnt_hdl; }; struct ipa3_usb_teth_prot_conn_params { u32 usb_to_ipa_clnt_hdl; u32 ipa_to_usb_clnt_hdl; Loading @@ -168,7 +160,6 @@ struct ipa3_usb_transport_type_ctx { int (*ipa_usb_notify_cb)(enum ipa_usb_notify_event, void *user_data); void *user_data; enum ipa3_usb_state state; struct finish_suspend_work_context finish_suspend_work; struct ipa_usb_xdci_chan_params ch_params; struct ipa3_usb_teth_prot_conn_params teth_conn_params; }; Loading Loading @@ -221,16 +212,10 @@ struct ipa3_usb_status_dbg_info { static void ipa3_usb_wq_notify_remote_wakeup(struct work_struct *work); static void ipa3_usb_wq_dpl_notify_remote_wakeup(struct work_struct *work); static void ipa3_usb_wq_notify_suspend_completed(struct work_struct *work); static void ipa3_usb_wq_dpl_notify_suspend_completed(struct work_struct *work); static DECLARE_WORK(ipa3_usb_notify_remote_wakeup_work, ipa3_usb_wq_notify_remote_wakeup); static DECLARE_WORK(ipa3_usb_dpl_notify_remote_wakeup_work, ipa3_usb_wq_dpl_notify_remote_wakeup); static DECLARE_WORK(ipa3_usb_notify_suspend_completed_work, ipa3_usb_wq_notify_suspend_completed); static DECLARE_WORK(ipa3_usb_dpl_notify_suspend_completed_work, ipa3_usb_wq_dpl_notify_suspend_completed); struct ipa3_usb_context *ipa3_usb_ctx; Loading Loading @@ -273,8 +258,6 @@ static char *ipa3_usb_state_to_string(enum ipa3_usb_state state) return "IPA_USB_STOPPED"; case IPA_USB_SUSPEND_REQUESTED: return "IPA_USB_SUSPEND_REQUESTED"; case IPA_USB_SUSPEND_IN_PROGRESS: return "IPA_USB_SUSPEND_IN_PROGRESS"; case IPA_USB_SUSPENDED: return "IPA_USB_SUSPENDED"; case IPA_USB_SUSPENDED_NO_RWAKEUP: Loading Loading @@ -330,17 +313,11 @@ static bool ipa3_usb_set_state(enum ipa3_usb_state new_state, bool err_permit, * In case of failure during suspend request * handling, state is reverted to connected. */ (err_permit && state == IPA_USB_SUSPEND_REQUESTED) || /* * In case of failure during suspend completing * handling, state is reverted to connected. */ (err_permit && state == IPA_USB_SUSPEND_IN_PROGRESS)) (err_permit && state == IPA_USB_SUSPEND_REQUESTED)) state_legal = true; break; case IPA_USB_STOPPED: if (state == IPA_USB_SUSPEND_IN_PROGRESS || state == IPA_USB_CONNECTED || if (state == IPA_USB_CONNECTED || state == IPA_USB_SUSPENDED || state == IPA_USB_SUSPENDED_NO_RWAKEUP) state_legal = true; Loading @@ -349,19 +326,8 @@ static bool ipa3_usb_set_state(enum ipa3_usb_state new_state, bool err_permit, if (state == IPA_USB_CONNECTED) state_legal = true; break; case IPA_USB_SUSPEND_IN_PROGRESS: if (state == IPA_USB_SUSPEND_REQUESTED || /* * In case of failure during resume, state is reverted * to original, which could be suspend_in_progress. * Allow it. */ (err_permit && state == IPA_USB_RESUME_IN_PROGRESS)) state_legal = true; break; case IPA_USB_SUSPENDED: if (state == IPA_USB_SUSPEND_REQUESTED || state == IPA_USB_SUSPEND_IN_PROGRESS || /* * In case of failure during resume, state is reverted * to original, which could be suspended. Allow it Loading @@ -374,8 +340,7 @@ static bool ipa3_usb_set_state(enum ipa3_usb_state new_state, bool err_permit, state_legal = true; break; case IPA_USB_RESUME_IN_PROGRESS: if (state == IPA_USB_SUSPEND_IN_PROGRESS || state == IPA_USB_SUSPENDED) if (state == IPA_USB_SUSPENDED) state_legal = true; break; default: Loading Loading @@ -452,7 +417,6 @@ static bool ipa3_usb_check_legal_op(enum ipa3_usb_op op, break; case IPA_USB_OP_DISCONNECT: if (state == IPA_USB_CONNECTED || state == IPA_USB_SUSPEND_IN_PROGRESS || state == IPA_USB_SUSPENDED || state == IPA_USB_SUSPENDED_NO_RWAKEUP) is_legal = true; Loading Loading @@ -483,7 +447,6 @@ static bool ipa3_usb_check_legal_op(enum ipa3_usb_op op, break; case IPA_USB_OP_RESUME: if (state == IPA_USB_SUSPENDED || state == IPA_USB_SUSPEND_IN_PROGRESS || state == IPA_USB_SUSPENDED_NO_RWAKEUP) is_legal = true; break; Loading Loading @@ -582,71 +545,6 @@ static void ipa3_usb_wq_dpl_notify_remote_wakeup(struct work_struct *work) ipa3_usb_notify_do(IPA_USB_TRANSPORT_DPL, IPA_USB_REMOTE_WAKEUP); } static void ipa3_usb_wq_notify_suspend_completed(struct work_struct *work) { ipa3_usb_notify_do(IPA_USB_TRANSPORT_TETH, IPA_USB_SUSPEND_COMPLETED); } static void ipa3_usb_wq_dpl_notify_suspend_completed(struct work_struct *work) { ipa3_usb_notify_do(IPA_USB_TRANSPORT_DPL, IPA_USB_SUSPEND_COMPLETED); } static void ipa3_usb_wq_finish_suspend_work(struct work_struct *work) { struct finish_suspend_work_context *finish_suspend_work_ctx; unsigned long flags; int result = -EFAULT; struct ipa3_usb_transport_type_ctx *tctx; mutex_lock(&ipa3_usb_ctx->general_mutex); IPA_USB_DBG_LOW("entry\n"); finish_suspend_work_ctx = container_of(work, struct finish_suspend_work_context, work); tctx = &ipa3_usb_ctx->ttype_ctx[finish_suspend_work_ctx->ttype]; spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags); if (tctx->state != IPA_USB_SUSPEND_IN_PROGRESS) { spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags); mutex_unlock(&ipa3_usb_ctx->general_mutex); return; } spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags); /* Stop DL/DPL channel */ result = ipa3_stop_gsi_channel(finish_suspend_work_ctx->dl_clnt_hdl); if (result) { IPAERR("Error stopping DL/DPL channel: %d, resuming channel\n", result); ipa3_xdci_resume(finish_suspend_work_ctx->ul_clnt_hdl, finish_suspend_work_ctx->dl_clnt_hdl, IPA3_USB_IS_TTYPE_DPL(finish_suspend_work_ctx->ttype)); /* Change state back to CONNECTED */ if (!ipa3_usb_set_state(IPA_USB_CONNECTED, true, finish_suspend_work_ctx->ttype)) IPA_USB_ERR("failed to change state to connected\n"); queue_work(ipa3_usb_ctx->wq, IPA3_USB_IS_TTYPE_DPL(finish_suspend_work_ctx->ttype) ? &ipa3_usb_dpl_notify_remote_wakeup_work : &ipa3_usb_notify_remote_wakeup_work); mutex_unlock(&ipa3_usb_ctx->general_mutex); return; } /* Change ipa_usb state to SUSPENDED */ if (!ipa3_usb_set_state(IPA_USB_SUSPENDED, false, finish_suspend_work_ctx->ttype)) IPA_USB_ERR("failed to change state to suspended\n"); queue_work(ipa3_usb_ctx->wq, IPA3_USB_IS_TTYPE_DPL(finish_suspend_work_ctx->ttype) ? &ipa3_usb_dpl_notify_suspend_completed_work : &ipa3_usb_notify_suspend_completed_work); IPA_USB_DBG_LOW("exit\n"); mutex_unlock(&ipa3_usb_ctx->general_mutex); } static int ipa3_usb_cons_request_resource_cb_do( enum ipa3_usb_transport_type ttype, struct work_struct *remote_wakeup_work) Loading Loading @@ -674,17 +572,6 @@ static int ipa3_usb_cons_request_resource_cb_do( else result = -EINPROGRESS; break; case IPA_USB_SUSPEND_IN_PROGRESS: /* * This case happens due to suspend interrupt. * CONS is granted */ if (!rm_ctx->cons_requested) { rm_ctx->cons_requested = true; queue_work(ipa3_usb_ctx->wq, remote_wakeup_work); } result = 0; break; case IPA_USB_SUSPENDED: if (!rm_ctx->cons_requested) { rm_ctx->cons_requested = true; Loading Loading @@ -727,15 +614,10 @@ static int ipa3_usb_cons_release_resource_cb_do( ipa3_usb_state_to_string( ipa3_usb_ctx->ttype_ctx[ttype].state)); switch (ipa3_usb_ctx->ttype_ctx[ttype].state) { case IPA_USB_SUSPEND_IN_PROGRESS: case IPA_USB_SUSPENDED: /* Proceed with the suspend if no DL/DPL data */ if (rm_ctx->cons_requested) rm_ctx->cons_requested_released = true; else { queue_work(ipa3_usb_ctx->wq, &ipa3_usb_ctx->ttype_ctx[ttype]. finish_suspend_work.work); } break; case IPA_USB_SUSPEND_REQUESTED: if (rm_ctx->cons_requested) Loading Loading @@ -2311,8 +2193,7 @@ int ipa_usb_xdci_disconnect(u32 ul_clnt_hdl, u32 dl_clnt_hdl, spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags); orig_state = ipa3_usb_ctx->ttype_ctx[ttype].state; if (!IPA3_USB_IS_TTYPE_DPL(ttype)) { if (orig_state != IPA_USB_SUSPEND_IN_PROGRESS && orig_state != IPA_USB_SUSPENDED) { if (orig_state != IPA_USB_SUSPENDED) { spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags); /* Stop UL channel */ Loading Loading @@ -2340,8 +2221,7 @@ int ipa_usb_xdci_disconnect(u32 ul_clnt_hdl, u32 dl_clnt_hdl, if (result) goto bad_params; if (orig_state != IPA_USB_SUSPEND_IN_PROGRESS && orig_state != IPA_USB_SUSPENDED) { if (orig_state != IPA_USB_SUSPENDED) { result = ipa3_usb_release_prod(ttype); if (result) { IPA_USB_ERR("failed to release PROD.\n"); Loading Loading @@ -2547,7 +2427,6 @@ int ipa_usb_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, { int result = 0; unsigned long flags; enum ipa3_usb_cons_state curr_cons_state; enum ipa3_usb_transport_type ttype; mutex_lock(&ipa3_usb_ctx->general_mutex); Loading Loading @@ -2602,20 +2481,13 @@ int ipa_usb_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, goto release_prod_fail; } spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags); curr_cons_state = ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_state; spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags); if (curr_cons_state == IPA_USB_CONS_GRANTED) { /* Change state to SUSPEND_IN_PROGRESS */ if (!ipa3_usb_set_state(IPA_USB_SUSPEND_IN_PROGRESS, false, ttype)) IPA_USB_ERR("fail set state to suspend_in_progress\n"); /* Check if DL/DPL data pending */ spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags); if (ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_requested) { IPA_USB_DBG( "DL/DPL data pending, invoke remote wakeup\n"); if (ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_state == IPA_USB_CONS_GRANTED && ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_requested) { IPA_USB_DBG("DL/DPL data pending, invoke remote wakeup\n"); queue_work(ipa3_usb_ctx->wq, IPA3_USB_IS_TTYPE_DPL(ttype) ? &ipa3_usb_dpl_notify_remote_wakeup_work : Loading @@ -2623,28 +2495,6 @@ int ipa_usb_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, } spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags); ipa3_usb_ctx->ttype_ctx[ttype].finish_suspend_work.ttype = ttype; ipa3_usb_ctx->ttype_ctx[ttype].finish_suspend_work.dl_clnt_hdl = dl_clnt_hdl; ipa3_usb_ctx->ttype_ctx[ttype].finish_suspend_work.ul_clnt_hdl = ul_clnt_hdl; INIT_WORK(&ipa3_usb_ctx->ttype_ctx[ttype]. finish_suspend_work.work, ipa3_usb_wq_finish_suspend_work); result = -EINPROGRESS; IPA_USB_DBG("exit with suspend_in_progress\n"); goto bad_params; } /* Stop DL channel */ result = ipa3_stop_gsi_channel(dl_clnt_hdl); if (result) { IPAERR("Error stopping DL/DPL channel: %d\n", result); result = -EFAULT; goto release_prod_fail; } /* Change state to SUSPENDED */ if (!ipa3_usb_set_state(IPA_USB_SUSPENDED, false, ttype)) IPA_USB_ERR("failed to change state to suspended\n"); Loading Loading @@ -2803,14 +2653,12 @@ int ipa_usb_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, } } if (prev_state != IPA_USB_SUSPEND_IN_PROGRESS) { /* Start DL/DPL channel */ result = ipa3_start_gsi_channel(dl_clnt_hdl); if (result) { IPA_USB_ERR("failed to start DL/DPL channel.\n"); goto start_dl_fail; } } /* Change state to CONNECTED */ if (!ipa3_usb_set_state(IPA_USB_CONNECTED, false, ttype)) { Loading @@ -2824,12 +2672,10 @@ int ipa_usb_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, return 0; state_change_connected_fail: if (prev_state != IPA_USB_SUSPEND_IN_PROGRESS) { result = ipa3_stop_gsi_channel(dl_clnt_hdl); if (result) IPA_USB_ERR("Error stopping DL/DPL channel: %d\n", result); } start_dl_fail: if (!IPA3_USB_IS_TTYPE_DPL(ttype)) { result = ipa3_stop_gsi_channel(ul_clnt_hdl); Loading drivers/platform/msm/ipa/ipa_v3/ipa.c +5 −60 Original line number Diff line number Diff line Loading @@ -498,63 +498,6 @@ static int ipa3_open(struct inode *inode, struct file *filp) return 0; } /** * ipa3_flow_control() - Enable/Disable flow control on a particular client. * Return codes: * None */ void ipa3_flow_control(enum ipa_client_type ipa_client, bool enable, uint32_t qmap_id) { struct ipa_ep_cfg_ctrl ep_ctrl = {0}; int ep_idx; struct ipa3_ep_context *ep; /* Check if tethered flow control is needed or not.*/ if (!ipa3_ctx->tethered_flow_control) { IPADBG("Apps flow control is not needed\n"); return; } /* Check if ep is valid. */ ep_idx = ipa3_get_ep_mapping(ipa_client); if (ep_idx == -1) { IPADBG("Invalid IPA client\n"); return; } ep = &ipa3_ctx->ep[ep_idx]; if (!ep->valid || (ep->client != IPA_CLIENT_USB_PROD)) { IPADBG("EP not valid/Not applicable for client.\n"); return; } spin_lock(&ipa3_ctx->disconnect_lock); /* Check if the QMAP_ID matches. */ if (ep->cfg.meta.qmap_id != qmap_id) { IPADBG("Flow control ind not for same flow: %u %u\n", ep->cfg.meta.qmap_id, qmap_id); spin_unlock(&ipa3_ctx->disconnect_lock); return; } if (!ep->disconnect_in_progress) { if (enable) { IPADBG("Enabling Flow\n"); ep_ctrl.ipa_ep_delay = false; IPA_STATS_INC_CNT(ipa3_ctx->stats.flow_enable); } else { IPADBG("Disabling Flow\n"); ep_ctrl.ipa_ep_delay = true; IPA_STATS_INC_CNT(ipa3_ctx->stats.flow_disable); } ep_ctrl.ipa_ep_suspend = false; ipa3_cfg_ep_ctrl(ep_idx, &ep_ctrl); } else { IPADBG("EP disconnect is in progress\n"); } spin_unlock(&ipa3_ctx->disconnect_lock); } static void ipa3_wan_msg_free_cb(void *buff, u32 len, u32 type) { if (!buff) { Loading Loading @@ -1866,6 +1809,8 @@ static void ipa3_q6_avoid_holb(void) IPA_ENDP_INIT_HOL_BLOCK_EN_n, ep_idx, &ep_holb); /* from IPA 4.0 pipe suspend is not supported */ if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) ipahal_write_reg_n_fields( IPA_ENDP_INIT_CTRL_n, ep_idx, &ep_suspend); Loading drivers/platform/msm/ipa/ipa_v3/ipa_client.c +78 −46 Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ int ipa3_enable_data_path(u32 clnt_hdl) } /* Enable the pipe */ if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { if (IPA_CLIENT_IS_CONS(ep->client) && (ep->keep_ipa_awake || ipa3_ctx->resume_on_connect[ep->client] || Loading @@ -77,6 +78,7 @@ int ipa3_enable_data_path(u32 clnt_hdl) ep_cfg_ctrl.ipa_ep_suspend = false; res = ipa3_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl); } } return res; } Loading @@ -97,18 +99,24 @@ int ipa3_disable_data_path(u32 clnt_hdl) res = ipa3_cfg_ep_holb(clnt_hdl, &holb_cfg); } /* * for IPA 4.0 and above aggregation frame is closed together with * channel STOP */ if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { /* Suspend the pipe */ if (IPA_CLIENT_IS_CONS(ep->client)) { /* * for RG10 workaround uC needs to be loaded before pipe can * be suspended in this case. * for RG10 workaround uC needs to be loaded before * pipe can be suspended in this case. */ if (ipa3_ctx->apply_rg10_wa && ipa3_uc_state_check()) { IPADBG("uC is not loaded yet, waiting...\n"); res = wait_for_completion_timeout( &ipa3_ctx->uc_loaded_completion_obj, 60 * HZ); &ipa3_ctx->uc_loaded_completion_obj, 60 * HZ); if (res == 0) IPADBG("timeout waiting for uC to load\n"); IPADBG("timeout waiting for uC load\n"); } memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); Loading @@ -117,13 +125,15 @@ int ipa3_disable_data_path(u32 clnt_hdl) } udelay(IPA_PKT_FLUSH_TO_US); ipahal_read_reg_n_fields(IPA_ENDP_INIT_AGGR_n, clnt_hdl, &ep_aggr); ipahal_read_reg_n_fields(IPA_ENDP_INIT_AGGR_n, clnt_hdl, &ep_aggr); if (ep_aggr.aggr_en) { res = ipa3_tag_aggr_force_close(clnt_hdl); if (res) { IPAERR("tag process timeout, client:%d err:%d\n", IPAERR("tag process timeout client:%d err:%d\n", clnt_hdl, res); BUG(); ipa_assert(); } } } Loading Loading @@ -1257,10 +1267,12 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, goto disable_clk_and_exit; } if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { /* Suspend the DL/DPL EP */ memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); ep_cfg_ctrl.ipa_ep_suspend = true; ipa3_cfg_ep_ctrl(dl_clnt_hdl, &ep_cfg_ctrl); } /* * Check if DL/DPL channel is empty again, data could enter the channel Loading @@ -1275,6 +1287,14 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, goto unsuspend_dl_and_exit; } /* Stop DL channel */ result = ipa3_stop_gsi_channel(dl_clnt_hdl); if (result) { IPAERR("Error stopping DL/DPL channel: %d\n", result); result = -EFAULT; goto unsuspend_dl_and_exit; } /* STOP UL channel */ if (!is_dpl) { source_pipe_bitmask = 1 << ipa3_get_ep_mapping(ul_ep->client); Loading @@ -1283,7 +1303,7 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, if (result) { IPAERR("Error stopping UL channel: result = %d\n", result); goto unsuspend_dl_and_exit; goto start_dl_and_exit; } } Loading @@ -1292,11 +1312,15 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, IPADBG("exit\n"); return 0; start_dl_and_exit: gsi_start_channel(dl_ep->gsi_chan_hdl); unsuspend_dl_and_exit: if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { /* Unsuspend the DL EP */ memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); ep_cfg_ctrl.ipa_ep_suspend = false; ipa3_cfg_ep_ctrl(dl_clnt_hdl, &ep_cfg_ctrl); } disable_clk_and_exit: IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(dl_clnt_hdl)); return result; Loading Loading @@ -1340,7 +1364,8 @@ int ipa3_start_gsi_channel(u32 clnt_hdl) int ipa3_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, bool is_dpl) { struct ipa3_ep_context *ul_ep, *dl_ep; struct ipa3_ep_context *ul_ep = NULL; struct ipa3_ep_context *dl_ep = NULL; enum gsi_status gsi_res; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; Loading @@ -1360,10 +1385,17 @@ int ipa3_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, bool is_dpl) ul_ep = &ipa3_ctx->ep[ul_clnt_hdl]; IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(dl_clnt_hdl)); if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { /* Unsuspend the DL/DPL EP */ memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); ep_cfg_ctrl.ipa_ep_suspend = false; ipa3_cfg_ep_ctrl(dl_clnt_hdl, &ep_cfg_ctrl); } /* Start DL channel */ gsi_res = gsi_start_channel(dl_ep->gsi_chan_hdl); if (gsi_res != GSI_STATUS_SUCCESS) IPAERR("Error starting DL channel: %d\n", gsi_res); /* Start UL channel */ if (!is_dpl) { Loading drivers/platform/msm/ipa/ipa_v3/ipa_i.h +0 −2 Original line number Diff line number Diff line Loading @@ -1970,8 +1970,6 @@ int ipa3_set_flt_tuple_mask(int pipe_idx, struct ipahal_reg_hash_tuple *tuple); int ipa3_set_rt_tuple_mask(int tbl_idx, struct ipahal_reg_hash_tuple *tuple); void ipa3_set_resorce_groups_min_max_limits(void); void ipa3_suspend_apps_pipes(bool suspend); void ipa3_flow_control(enum ipa_client_type ipa_client, bool enable, uint32_t qmap_id); int ipa3_flt_read_tbl_from_hw(u32 pipe_idx, enum ipa_ip_type ip_type, bool hashable, Loading drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c +9 −7 Original line number Diff line number Diff line Loading @@ -1600,13 +1600,15 @@ int ipa3_suspend_wdi_pipe(u32 clnt_hdl) memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); if (IPA_CLIENT_IS_CONS(ep->client)) { if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { ep_cfg_ctrl.ipa_ep_suspend = true; result = ipa3_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl); if (result) IPAERR("client (ep: %d) failed to suspend result=%d\n", IPAERR("(ep: %d) failed to suspend result=%d\n", clnt_hdl, result); else IPADBG("client (ep: %d) suspended\n", clnt_hdl); IPADBG("(ep: %d) suspended\n", clnt_hdl); } } else { ep_cfg_ctrl.ipa_ep_delay = true; result = ipa3_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl); Loading Loading
drivers/platform/msm/ipa/ipa_clients/ipa_usb.c +26 −180 Original line number Diff line number Diff line /* Copyright (c) 2015, 2016 The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -125,7 +125,6 @@ enum ipa3_usb_state { IPA_USB_CONNECTED, IPA_USB_STOPPED, IPA_USB_SUSPEND_REQUESTED, IPA_USB_SUSPEND_IN_PROGRESS, IPA_USB_SUSPENDED, IPA_USB_SUSPENDED_NO_RWAKEUP, IPA_USB_RESUME_IN_PROGRESS Loading @@ -146,13 +145,6 @@ enum ipa3_usb_transport_type { #define IPA3_USB_IS_TTYPE_DPL(__ttype) \ ((__ttype) == IPA_USB_TRANSPORT_DPL) struct finish_suspend_work_context { struct work_struct work; enum ipa3_usb_transport_type ttype; u32 dl_clnt_hdl; u32 ul_clnt_hdl; }; struct ipa3_usb_teth_prot_conn_params { u32 usb_to_ipa_clnt_hdl; u32 ipa_to_usb_clnt_hdl; Loading @@ -168,7 +160,6 @@ struct ipa3_usb_transport_type_ctx { int (*ipa_usb_notify_cb)(enum ipa_usb_notify_event, void *user_data); void *user_data; enum ipa3_usb_state state; struct finish_suspend_work_context finish_suspend_work; struct ipa_usb_xdci_chan_params ch_params; struct ipa3_usb_teth_prot_conn_params teth_conn_params; }; Loading Loading @@ -221,16 +212,10 @@ struct ipa3_usb_status_dbg_info { static void ipa3_usb_wq_notify_remote_wakeup(struct work_struct *work); static void ipa3_usb_wq_dpl_notify_remote_wakeup(struct work_struct *work); static void ipa3_usb_wq_notify_suspend_completed(struct work_struct *work); static void ipa3_usb_wq_dpl_notify_suspend_completed(struct work_struct *work); static DECLARE_WORK(ipa3_usb_notify_remote_wakeup_work, ipa3_usb_wq_notify_remote_wakeup); static DECLARE_WORK(ipa3_usb_dpl_notify_remote_wakeup_work, ipa3_usb_wq_dpl_notify_remote_wakeup); static DECLARE_WORK(ipa3_usb_notify_suspend_completed_work, ipa3_usb_wq_notify_suspend_completed); static DECLARE_WORK(ipa3_usb_dpl_notify_suspend_completed_work, ipa3_usb_wq_dpl_notify_suspend_completed); struct ipa3_usb_context *ipa3_usb_ctx; Loading Loading @@ -273,8 +258,6 @@ static char *ipa3_usb_state_to_string(enum ipa3_usb_state state) return "IPA_USB_STOPPED"; case IPA_USB_SUSPEND_REQUESTED: return "IPA_USB_SUSPEND_REQUESTED"; case IPA_USB_SUSPEND_IN_PROGRESS: return "IPA_USB_SUSPEND_IN_PROGRESS"; case IPA_USB_SUSPENDED: return "IPA_USB_SUSPENDED"; case IPA_USB_SUSPENDED_NO_RWAKEUP: Loading Loading @@ -330,17 +313,11 @@ static bool ipa3_usb_set_state(enum ipa3_usb_state new_state, bool err_permit, * In case of failure during suspend request * handling, state is reverted to connected. */ (err_permit && state == IPA_USB_SUSPEND_REQUESTED) || /* * In case of failure during suspend completing * handling, state is reverted to connected. */ (err_permit && state == IPA_USB_SUSPEND_IN_PROGRESS)) (err_permit && state == IPA_USB_SUSPEND_REQUESTED)) state_legal = true; break; case IPA_USB_STOPPED: if (state == IPA_USB_SUSPEND_IN_PROGRESS || state == IPA_USB_CONNECTED || if (state == IPA_USB_CONNECTED || state == IPA_USB_SUSPENDED || state == IPA_USB_SUSPENDED_NO_RWAKEUP) state_legal = true; Loading @@ -349,19 +326,8 @@ static bool ipa3_usb_set_state(enum ipa3_usb_state new_state, bool err_permit, if (state == IPA_USB_CONNECTED) state_legal = true; break; case IPA_USB_SUSPEND_IN_PROGRESS: if (state == IPA_USB_SUSPEND_REQUESTED || /* * In case of failure during resume, state is reverted * to original, which could be suspend_in_progress. * Allow it. */ (err_permit && state == IPA_USB_RESUME_IN_PROGRESS)) state_legal = true; break; case IPA_USB_SUSPENDED: if (state == IPA_USB_SUSPEND_REQUESTED || state == IPA_USB_SUSPEND_IN_PROGRESS || /* * In case of failure during resume, state is reverted * to original, which could be suspended. Allow it Loading @@ -374,8 +340,7 @@ static bool ipa3_usb_set_state(enum ipa3_usb_state new_state, bool err_permit, state_legal = true; break; case IPA_USB_RESUME_IN_PROGRESS: if (state == IPA_USB_SUSPEND_IN_PROGRESS || state == IPA_USB_SUSPENDED) if (state == IPA_USB_SUSPENDED) state_legal = true; break; default: Loading Loading @@ -452,7 +417,6 @@ static bool ipa3_usb_check_legal_op(enum ipa3_usb_op op, break; case IPA_USB_OP_DISCONNECT: if (state == IPA_USB_CONNECTED || state == IPA_USB_SUSPEND_IN_PROGRESS || state == IPA_USB_SUSPENDED || state == IPA_USB_SUSPENDED_NO_RWAKEUP) is_legal = true; Loading Loading @@ -483,7 +447,6 @@ static bool ipa3_usb_check_legal_op(enum ipa3_usb_op op, break; case IPA_USB_OP_RESUME: if (state == IPA_USB_SUSPENDED || state == IPA_USB_SUSPEND_IN_PROGRESS || state == IPA_USB_SUSPENDED_NO_RWAKEUP) is_legal = true; break; Loading Loading @@ -582,71 +545,6 @@ static void ipa3_usb_wq_dpl_notify_remote_wakeup(struct work_struct *work) ipa3_usb_notify_do(IPA_USB_TRANSPORT_DPL, IPA_USB_REMOTE_WAKEUP); } static void ipa3_usb_wq_notify_suspend_completed(struct work_struct *work) { ipa3_usb_notify_do(IPA_USB_TRANSPORT_TETH, IPA_USB_SUSPEND_COMPLETED); } static void ipa3_usb_wq_dpl_notify_suspend_completed(struct work_struct *work) { ipa3_usb_notify_do(IPA_USB_TRANSPORT_DPL, IPA_USB_SUSPEND_COMPLETED); } static void ipa3_usb_wq_finish_suspend_work(struct work_struct *work) { struct finish_suspend_work_context *finish_suspend_work_ctx; unsigned long flags; int result = -EFAULT; struct ipa3_usb_transport_type_ctx *tctx; mutex_lock(&ipa3_usb_ctx->general_mutex); IPA_USB_DBG_LOW("entry\n"); finish_suspend_work_ctx = container_of(work, struct finish_suspend_work_context, work); tctx = &ipa3_usb_ctx->ttype_ctx[finish_suspend_work_ctx->ttype]; spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags); if (tctx->state != IPA_USB_SUSPEND_IN_PROGRESS) { spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags); mutex_unlock(&ipa3_usb_ctx->general_mutex); return; } spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags); /* Stop DL/DPL channel */ result = ipa3_stop_gsi_channel(finish_suspend_work_ctx->dl_clnt_hdl); if (result) { IPAERR("Error stopping DL/DPL channel: %d, resuming channel\n", result); ipa3_xdci_resume(finish_suspend_work_ctx->ul_clnt_hdl, finish_suspend_work_ctx->dl_clnt_hdl, IPA3_USB_IS_TTYPE_DPL(finish_suspend_work_ctx->ttype)); /* Change state back to CONNECTED */ if (!ipa3_usb_set_state(IPA_USB_CONNECTED, true, finish_suspend_work_ctx->ttype)) IPA_USB_ERR("failed to change state to connected\n"); queue_work(ipa3_usb_ctx->wq, IPA3_USB_IS_TTYPE_DPL(finish_suspend_work_ctx->ttype) ? &ipa3_usb_dpl_notify_remote_wakeup_work : &ipa3_usb_notify_remote_wakeup_work); mutex_unlock(&ipa3_usb_ctx->general_mutex); return; } /* Change ipa_usb state to SUSPENDED */ if (!ipa3_usb_set_state(IPA_USB_SUSPENDED, false, finish_suspend_work_ctx->ttype)) IPA_USB_ERR("failed to change state to suspended\n"); queue_work(ipa3_usb_ctx->wq, IPA3_USB_IS_TTYPE_DPL(finish_suspend_work_ctx->ttype) ? &ipa3_usb_dpl_notify_suspend_completed_work : &ipa3_usb_notify_suspend_completed_work); IPA_USB_DBG_LOW("exit\n"); mutex_unlock(&ipa3_usb_ctx->general_mutex); } static int ipa3_usb_cons_request_resource_cb_do( enum ipa3_usb_transport_type ttype, struct work_struct *remote_wakeup_work) Loading Loading @@ -674,17 +572,6 @@ static int ipa3_usb_cons_request_resource_cb_do( else result = -EINPROGRESS; break; case IPA_USB_SUSPEND_IN_PROGRESS: /* * This case happens due to suspend interrupt. * CONS is granted */ if (!rm_ctx->cons_requested) { rm_ctx->cons_requested = true; queue_work(ipa3_usb_ctx->wq, remote_wakeup_work); } result = 0; break; case IPA_USB_SUSPENDED: if (!rm_ctx->cons_requested) { rm_ctx->cons_requested = true; Loading Loading @@ -727,15 +614,10 @@ static int ipa3_usb_cons_release_resource_cb_do( ipa3_usb_state_to_string( ipa3_usb_ctx->ttype_ctx[ttype].state)); switch (ipa3_usb_ctx->ttype_ctx[ttype].state) { case IPA_USB_SUSPEND_IN_PROGRESS: case IPA_USB_SUSPENDED: /* Proceed with the suspend if no DL/DPL data */ if (rm_ctx->cons_requested) rm_ctx->cons_requested_released = true; else { queue_work(ipa3_usb_ctx->wq, &ipa3_usb_ctx->ttype_ctx[ttype]. finish_suspend_work.work); } break; case IPA_USB_SUSPEND_REQUESTED: if (rm_ctx->cons_requested) Loading Loading @@ -2311,8 +2193,7 @@ int ipa_usb_xdci_disconnect(u32 ul_clnt_hdl, u32 dl_clnt_hdl, spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags); orig_state = ipa3_usb_ctx->ttype_ctx[ttype].state; if (!IPA3_USB_IS_TTYPE_DPL(ttype)) { if (orig_state != IPA_USB_SUSPEND_IN_PROGRESS && orig_state != IPA_USB_SUSPENDED) { if (orig_state != IPA_USB_SUSPENDED) { spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags); /* Stop UL channel */ Loading Loading @@ -2340,8 +2221,7 @@ int ipa_usb_xdci_disconnect(u32 ul_clnt_hdl, u32 dl_clnt_hdl, if (result) goto bad_params; if (orig_state != IPA_USB_SUSPEND_IN_PROGRESS && orig_state != IPA_USB_SUSPENDED) { if (orig_state != IPA_USB_SUSPENDED) { result = ipa3_usb_release_prod(ttype); if (result) { IPA_USB_ERR("failed to release PROD.\n"); Loading Loading @@ -2547,7 +2427,6 @@ int ipa_usb_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, { int result = 0; unsigned long flags; enum ipa3_usb_cons_state curr_cons_state; enum ipa3_usb_transport_type ttype; mutex_lock(&ipa3_usb_ctx->general_mutex); Loading Loading @@ -2602,20 +2481,13 @@ int ipa_usb_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, goto release_prod_fail; } spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags); curr_cons_state = ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_state; spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags); if (curr_cons_state == IPA_USB_CONS_GRANTED) { /* Change state to SUSPEND_IN_PROGRESS */ if (!ipa3_usb_set_state(IPA_USB_SUSPEND_IN_PROGRESS, false, ttype)) IPA_USB_ERR("fail set state to suspend_in_progress\n"); /* Check if DL/DPL data pending */ spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags); if (ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_requested) { IPA_USB_DBG( "DL/DPL data pending, invoke remote wakeup\n"); if (ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_state == IPA_USB_CONS_GRANTED && ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_requested) { IPA_USB_DBG("DL/DPL data pending, invoke remote wakeup\n"); queue_work(ipa3_usb_ctx->wq, IPA3_USB_IS_TTYPE_DPL(ttype) ? &ipa3_usb_dpl_notify_remote_wakeup_work : Loading @@ -2623,28 +2495,6 @@ int ipa_usb_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, } spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags); ipa3_usb_ctx->ttype_ctx[ttype].finish_suspend_work.ttype = ttype; ipa3_usb_ctx->ttype_ctx[ttype].finish_suspend_work.dl_clnt_hdl = dl_clnt_hdl; ipa3_usb_ctx->ttype_ctx[ttype].finish_suspend_work.ul_clnt_hdl = ul_clnt_hdl; INIT_WORK(&ipa3_usb_ctx->ttype_ctx[ttype]. finish_suspend_work.work, ipa3_usb_wq_finish_suspend_work); result = -EINPROGRESS; IPA_USB_DBG("exit with suspend_in_progress\n"); goto bad_params; } /* Stop DL channel */ result = ipa3_stop_gsi_channel(dl_clnt_hdl); if (result) { IPAERR("Error stopping DL/DPL channel: %d\n", result); result = -EFAULT; goto release_prod_fail; } /* Change state to SUSPENDED */ if (!ipa3_usb_set_state(IPA_USB_SUSPENDED, false, ttype)) IPA_USB_ERR("failed to change state to suspended\n"); Loading Loading @@ -2803,14 +2653,12 @@ int ipa_usb_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, } } if (prev_state != IPA_USB_SUSPEND_IN_PROGRESS) { /* Start DL/DPL channel */ result = ipa3_start_gsi_channel(dl_clnt_hdl); if (result) { IPA_USB_ERR("failed to start DL/DPL channel.\n"); goto start_dl_fail; } } /* Change state to CONNECTED */ if (!ipa3_usb_set_state(IPA_USB_CONNECTED, false, ttype)) { Loading @@ -2824,12 +2672,10 @@ int ipa_usb_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, return 0; state_change_connected_fail: if (prev_state != IPA_USB_SUSPEND_IN_PROGRESS) { result = ipa3_stop_gsi_channel(dl_clnt_hdl); if (result) IPA_USB_ERR("Error stopping DL/DPL channel: %d\n", result); } start_dl_fail: if (!IPA3_USB_IS_TTYPE_DPL(ttype)) { result = ipa3_stop_gsi_channel(ul_clnt_hdl); Loading
drivers/platform/msm/ipa/ipa_v3/ipa.c +5 −60 Original line number Diff line number Diff line Loading @@ -498,63 +498,6 @@ static int ipa3_open(struct inode *inode, struct file *filp) return 0; } /** * ipa3_flow_control() - Enable/Disable flow control on a particular client. * Return codes: * None */ void ipa3_flow_control(enum ipa_client_type ipa_client, bool enable, uint32_t qmap_id) { struct ipa_ep_cfg_ctrl ep_ctrl = {0}; int ep_idx; struct ipa3_ep_context *ep; /* Check if tethered flow control is needed or not.*/ if (!ipa3_ctx->tethered_flow_control) { IPADBG("Apps flow control is not needed\n"); return; } /* Check if ep is valid. */ ep_idx = ipa3_get_ep_mapping(ipa_client); if (ep_idx == -1) { IPADBG("Invalid IPA client\n"); return; } ep = &ipa3_ctx->ep[ep_idx]; if (!ep->valid || (ep->client != IPA_CLIENT_USB_PROD)) { IPADBG("EP not valid/Not applicable for client.\n"); return; } spin_lock(&ipa3_ctx->disconnect_lock); /* Check if the QMAP_ID matches. */ if (ep->cfg.meta.qmap_id != qmap_id) { IPADBG("Flow control ind not for same flow: %u %u\n", ep->cfg.meta.qmap_id, qmap_id); spin_unlock(&ipa3_ctx->disconnect_lock); return; } if (!ep->disconnect_in_progress) { if (enable) { IPADBG("Enabling Flow\n"); ep_ctrl.ipa_ep_delay = false; IPA_STATS_INC_CNT(ipa3_ctx->stats.flow_enable); } else { IPADBG("Disabling Flow\n"); ep_ctrl.ipa_ep_delay = true; IPA_STATS_INC_CNT(ipa3_ctx->stats.flow_disable); } ep_ctrl.ipa_ep_suspend = false; ipa3_cfg_ep_ctrl(ep_idx, &ep_ctrl); } else { IPADBG("EP disconnect is in progress\n"); } spin_unlock(&ipa3_ctx->disconnect_lock); } static void ipa3_wan_msg_free_cb(void *buff, u32 len, u32 type) { if (!buff) { Loading Loading @@ -1866,6 +1809,8 @@ static void ipa3_q6_avoid_holb(void) IPA_ENDP_INIT_HOL_BLOCK_EN_n, ep_idx, &ep_holb); /* from IPA 4.0 pipe suspend is not supported */ if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) ipahal_write_reg_n_fields( IPA_ENDP_INIT_CTRL_n, ep_idx, &ep_suspend); Loading
drivers/platform/msm/ipa/ipa_v3/ipa_client.c +78 −46 Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ int ipa3_enable_data_path(u32 clnt_hdl) } /* Enable the pipe */ if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { if (IPA_CLIENT_IS_CONS(ep->client) && (ep->keep_ipa_awake || ipa3_ctx->resume_on_connect[ep->client] || Loading @@ -77,6 +78,7 @@ int ipa3_enable_data_path(u32 clnt_hdl) ep_cfg_ctrl.ipa_ep_suspend = false; res = ipa3_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl); } } return res; } Loading @@ -97,18 +99,24 @@ int ipa3_disable_data_path(u32 clnt_hdl) res = ipa3_cfg_ep_holb(clnt_hdl, &holb_cfg); } /* * for IPA 4.0 and above aggregation frame is closed together with * channel STOP */ if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { /* Suspend the pipe */ if (IPA_CLIENT_IS_CONS(ep->client)) { /* * for RG10 workaround uC needs to be loaded before pipe can * be suspended in this case. * for RG10 workaround uC needs to be loaded before * pipe can be suspended in this case. */ if (ipa3_ctx->apply_rg10_wa && ipa3_uc_state_check()) { IPADBG("uC is not loaded yet, waiting...\n"); res = wait_for_completion_timeout( &ipa3_ctx->uc_loaded_completion_obj, 60 * HZ); &ipa3_ctx->uc_loaded_completion_obj, 60 * HZ); if (res == 0) IPADBG("timeout waiting for uC to load\n"); IPADBG("timeout waiting for uC load\n"); } memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); Loading @@ -117,13 +125,15 @@ int ipa3_disable_data_path(u32 clnt_hdl) } udelay(IPA_PKT_FLUSH_TO_US); ipahal_read_reg_n_fields(IPA_ENDP_INIT_AGGR_n, clnt_hdl, &ep_aggr); ipahal_read_reg_n_fields(IPA_ENDP_INIT_AGGR_n, clnt_hdl, &ep_aggr); if (ep_aggr.aggr_en) { res = ipa3_tag_aggr_force_close(clnt_hdl); if (res) { IPAERR("tag process timeout, client:%d err:%d\n", IPAERR("tag process timeout client:%d err:%d\n", clnt_hdl, res); BUG(); ipa_assert(); } } } Loading Loading @@ -1257,10 +1267,12 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, goto disable_clk_and_exit; } if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { /* Suspend the DL/DPL EP */ memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); ep_cfg_ctrl.ipa_ep_suspend = true; ipa3_cfg_ep_ctrl(dl_clnt_hdl, &ep_cfg_ctrl); } /* * Check if DL/DPL channel is empty again, data could enter the channel Loading @@ -1275,6 +1287,14 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, goto unsuspend_dl_and_exit; } /* Stop DL channel */ result = ipa3_stop_gsi_channel(dl_clnt_hdl); if (result) { IPAERR("Error stopping DL/DPL channel: %d\n", result); result = -EFAULT; goto unsuspend_dl_and_exit; } /* STOP UL channel */ if (!is_dpl) { source_pipe_bitmask = 1 << ipa3_get_ep_mapping(ul_ep->client); Loading @@ -1283,7 +1303,7 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, if (result) { IPAERR("Error stopping UL channel: result = %d\n", result); goto unsuspend_dl_and_exit; goto start_dl_and_exit; } } Loading @@ -1292,11 +1312,15 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, IPADBG("exit\n"); return 0; start_dl_and_exit: gsi_start_channel(dl_ep->gsi_chan_hdl); unsuspend_dl_and_exit: if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { /* Unsuspend the DL EP */ memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); ep_cfg_ctrl.ipa_ep_suspend = false; ipa3_cfg_ep_ctrl(dl_clnt_hdl, &ep_cfg_ctrl); } disable_clk_and_exit: IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(dl_clnt_hdl)); return result; Loading Loading @@ -1340,7 +1364,8 @@ int ipa3_start_gsi_channel(u32 clnt_hdl) int ipa3_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, bool is_dpl) { struct ipa3_ep_context *ul_ep, *dl_ep; struct ipa3_ep_context *ul_ep = NULL; struct ipa3_ep_context *dl_ep = NULL; enum gsi_status gsi_res; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; Loading @@ -1360,10 +1385,17 @@ int ipa3_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, bool is_dpl) ul_ep = &ipa3_ctx->ep[ul_clnt_hdl]; IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(dl_clnt_hdl)); if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { /* Unsuspend the DL/DPL EP */ memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); ep_cfg_ctrl.ipa_ep_suspend = false; ipa3_cfg_ep_ctrl(dl_clnt_hdl, &ep_cfg_ctrl); } /* Start DL channel */ gsi_res = gsi_start_channel(dl_ep->gsi_chan_hdl); if (gsi_res != GSI_STATUS_SUCCESS) IPAERR("Error starting DL channel: %d\n", gsi_res); /* Start UL channel */ if (!is_dpl) { Loading
drivers/platform/msm/ipa/ipa_v3/ipa_i.h +0 −2 Original line number Diff line number Diff line Loading @@ -1970,8 +1970,6 @@ int ipa3_set_flt_tuple_mask(int pipe_idx, struct ipahal_reg_hash_tuple *tuple); int ipa3_set_rt_tuple_mask(int tbl_idx, struct ipahal_reg_hash_tuple *tuple); void ipa3_set_resorce_groups_min_max_limits(void); void ipa3_suspend_apps_pipes(bool suspend); void ipa3_flow_control(enum ipa_client_type ipa_client, bool enable, uint32_t qmap_id); int ipa3_flt_read_tbl_from_hw(u32 pipe_idx, enum ipa_ip_type ip_type, bool hashable, Loading
drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c +9 −7 Original line number Diff line number Diff line Loading @@ -1600,13 +1600,15 @@ int ipa3_suspend_wdi_pipe(u32 clnt_hdl) memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); if (IPA_CLIENT_IS_CONS(ep->client)) { if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { ep_cfg_ctrl.ipa_ep_suspend = true; result = ipa3_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl); if (result) IPAERR("client (ep: %d) failed to suspend result=%d\n", IPAERR("(ep: %d) failed to suspend result=%d\n", clnt_hdl, result); else IPADBG("client (ep: %d) suspended\n", clnt_hdl); IPADBG("(ep: %d) suspended\n", clnt_hdl); } } else { ep_cfg_ctrl.ipa_ep_delay = true; result = ipa3_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl); Loading