Loading drivers/platform/msm/ipa/ipa_clients/ipa_usb.c +132 −27 Original line number Diff line number Diff line Loading @@ -144,13 +144,15 @@ enum ipa3_usb_state { enum ipa3_usb_transport_type { IPA_USB_TRANSPORT_TETH, IPA_USB_TRANSPORT_DPL, IPA_USB_TRANSPORT_TETH_2, IPA_USB_TRANSPORT_MAX }; /* Get transport type from tethering protocol */ #define IPA3_USB_GET_TTYPE(__teth_prot) \ (((__teth_prot) == IPA_USB_DIAG) ? \ IPA_USB_TRANSPORT_DPL : IPA_USB_TRANSPORT_TETH) IPA_USB_TRANSPORT_DPL : (((__teth_prot) == IPA_USB_RMNET_CV2X) ? \ IPA_USB_TRANSPORT_TETH_2 : IPA_USB_TRANSPORT_TETH)) /* Does the given transport type is DPL? */ #define IPA3_USB_IS_TTYPE_DPL(__ttype) \ Loading Loading @@ -204,7 +206,7 @@ struct ipa3_usb_context { struct ipa3_usb_teth_prot_context teth_prot_ctx[IPA_USB_MAX_TETH_PROT_SIZE]; int num_init_prot; /* without dpl */ struct teth_bridge_init_params teth_bridge_params; struct teth_bridge_init_params teth_bridge_params[IPA_TETH_BRIDGE_MAX]; struct completion dev_ready_comp; u32 qmi_req_id; spinlock_t state_lock; Loading Loading @@ -770,6 +772,8 @@ static char *ipa3_usb_teth_prot_to_string(enum ipa_usb_teth_prot teth_prot) case IPA_USB_RMNET: case IPA_USB_MBIM: return "teth_bridge"; case IPA_USB_RMNET_CV2X: return "teth_bridge_cv2x"; case IPA_USB_DIAG: return "dpl"; default: Loading @@ -785,6 +789,8 @@ static char *ipa3_usb_teth_bridge_prot_to_string( switch (teth_prot) { case IPA_USB_RMNET: return "rmnet"; case IPA_USB_RMNET_CV2X: return "rmnet_cv2x"; case IPA_USB_MBIM: return "mbim"; default: Loading @@ -794,11 +800,18 @@ static char *ipa3_usb_teth_bridge_prot_to_string( return "unsupported"; } static int ipa3_usb_init_teth_bridge(void) static int ipa3_usb_init_teth_bridge(enum ipa_usb_teth_prot teth_prot) { int result; result = teth_bridge_init(&ipa3_usb_ctx->teth_bridge_params); if (teth_prot == IPA_USB_RMNET_CV2X) result = teth_bridge_init( &ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_2]); else result = teth_bridge_init( &ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1]); if (result) { IPA_USB_ERR("Failed to initialize teth_bridge\n"); return result; Loading @@ -812,15 +825,26 @@ static int ipa3_usb_register_pm(enum ipa3_usb_transport_type ttype) struct ipa3_usb_transport_type_ctx *ttype_ctx = &ipa3_usb_ctx->ttype_ctx[ttype]; int result; enum ipa_client_type consumer; /* * One PM resource for teth1, * One PM resource for teth2 (CV2X), * One for DPL, */ /* there is one PM resource for teth and one for DPL */ if (!IPA3_USB_IS_TTYPE_DPL(ttype) && ipa3_usb_ctx->num_init_prot > 0) if (!IPA3_USB_IS_TTYPE_DPL(ttype) && (ipa3_usb_ctx->num_init_prot > 0) && (ttype != IPA_USB_TRANSPORT_TETH_2)) return 0; memset(&ttype_ctx->pm_ctx.reg_params, 0, sizeof(ttype_ctx->pm_ctx.reg_params)); ttype_ctx->pm_ctx.reg_params.name = (ttype == IPA_USB_TRANSPORT_DPL) ? "USB DPL" : "USB"; ttype_ctx->pm_ctx.reg_params.name = (ttype == IPA_USB_TRANSPORT_DPL) ? "USB DPL" : (ttype == IPA_USB_TRANSPORT_TETH_2) ? "USB2" : "USB"; ttype_ctx->pm_ctx.reg_params.callback = ipa3_usb_pm_cb; ttype_ctx->pm_ctx.reg_params.user_data = ttype_ctx; ttype_ctx->pm_ctx.reg_params.group = IPA_PM_GROUP_DEFAULT; Loading @@ -832,9 +856,12 @@ static int ipa3_usb_register_pm(enum ipa3_usb_transport_type ttype) goto fail_pm_reg; } consumer = (ttype == IPA_USB_TRANSPORT_DPL) ? IPA_CLIENT_USB_DPL_CONS : (ttype == IPA_USB_TRANSPORT_TETH_2) ? IPA_CLIENT_USB2_CONS : IPA_CLIENT_USB_CONS; result = ipa_pm_associate_ipa_cons_to_client(ttype_ctx->pm_ctx.hdl, (ttype == IPA_USB_TRANSPORT_DPL) ? IPA_CLIENT_USB_DPL_CONS : IPA_CLIENT_USB_CONS); consumer); if (result) { IPA_USB_ERR("fail to associate cons with PM %d\n", result); goto fail_pm_cons; Loading Loading @@ -1121,9 +1148,11 @@ int ipa_usb_init_teth_prot(enum ipa_usb_teth_prot teth_prot, goto bad_params; } ipa3_usb_ctx->teth_prot_ctx[teth_prot].user_data = user_data; result = ipa3_usb_init_teth_bridge(); result = ipa3_usb_init_teth_bridge(teth_prot); if (result) goto teth_prot_init_fail; ipa3_usb_ctx->teth_prot_ctx[teth_prot].state = IPA_USB_TETH_PROT_INITIALIZED; ipa3_usb_ctx->num_init_prot++; Loading @@ -1139,6 +1168,26 @@ int ipa_usb_init_teth_prot(enum ipa_usb_teth_prot teth_prot, ipa3_register_client_callback(&ipa_usb_set_lock_unlock, &ipa3_usb_get_teth_port_state, IPA_CLIENT_USB_PROD); break; case IPA_USB_RMNET_CV2X: if (ipa3_usb_ctx->teth_prot_ctx[teth_prot].state != IPA_USB_TETH_PROT_INVALID) { IPA_USB_DBG("%s already initialized\n", ipa3_usb_teth_prot_to_string(teth_prot)); result = -EPERM; goto bad_params; } ipa3_usb_ctx->teth_prot_ctx[teth_prot].user_data = user_data; result = ipa3_usb_init_teth_bridge(teth_prot); if (result) goto teth_prot_init_fail; ipa3_usb_ctx->teth_prot_ctx[teth_prot].state = IPA_USB_TETH_PROT_INITIALIZED; IPA_USB_DBG("initialized %s %s\n", ipa3_usb_teth_prot_to_string(teth_prot), ipa3_usb_teth_bridge_prot_to_string(teth_prot)); break; case IPA_USB_DIAG: if (ipa3_usb_ctx->teth_prot_ctx[teth_prot].state != IPA_USB_TETH_PROT_INVALID) { Loading Loading @@ -1166,7 +1215,8 @@ int ipa_usb_init_teth_prot(enum ipa_usb_teth_prot teth_prot, teth_prot_init_fail: if ((IPA3_USB_IS_TTYPE_DPL(ttype)) || (ipa3_usb_ctx->num_init_prot == 0)) { || (ipa3_usb_ctx->num_init_prot == 0) || (teth_prot == IPA_USB_RMNET_CV2X)) { if (ipa_pm_is_used()) { ipa3_usb_deregister_pm(ttype); } else { Loading Loading @@ -1249,6 +1299,7 @@ static bool ipa3_usb_check_chan_params(struct ipa_usb_xdci_chan_params *params) } break; case IPA_USB_RMNET: case IPA_USB_RMNET_CV2X: case IPA_USB_MBIM: if (ipa3_usb_ctx->teth_prot_ctx[params->teth_prot].state == IPA_USB_TETH_PROT_INVALID) { Loading Loading @@ -1319,7 +1370,6 @@ static int ipa3_usb_smmu_map_xdci_channel( ipa3_usb_ctx->smmu_reg_map.cnt--; } result = ipa3_smmu_map_peer_buff(params->xfer_ring_base_addr_iova, params->xfer_ring_len, map, params->sgt_xfer_rings, IPA_SMMU_CB_AP); Loading Loading @@ -1396,11 +1446,19 @@ static int ipa3_usb_request_xdci_channel( case IPA_USB_RMNET: case IPA_USB_MBIM: chan_params.priv = ipa3_usb_ctx->teth_bridge_params.private_data; ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1].private_data; chan_params.notify = ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1].usb_notify_cb; chan_params.skip_ep_cfg = ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1].skip_ep_cfg; break; case IPA_USB_RMNET_CV2X: chan_params.priv = ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_2].private_data; chan_params.notify = ipa3_usb_ctx->teth_bridge_params.usb_notify_cb; ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_2].usb_notify_cb; chan_params.skip_ep_cfg = ipa3_usb_ctx->teth_bridge_params.skip_ep_cfg; ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_2].skip_ep_cfg; break; case IPA_USB_DIAG: chan_params.priv = NULL; Loading Loading @@ -1703,6 +1761,16 @@ static int ipa3_usb_connect_dpl(void) return 0; } static int ipa3_get_tethering_mode(enum ipa_usb_teth_prot teth_prot) { if (teth_prot == IPA_USB_RMNET) return TETH_TETHERING_MODE_RMNET; else if (teth_prot == IPA_USB_RMNET_CV2X) return TETH_TETHERING_MODE_RMNET_2; else return TETH_TETHERING_MODE_MBIM; } static int ipa3_usb_connect_teth_prot(enum ipa_usb_teth_prot teth_prot) { int result; Loading Loading @@ -1771,6 +1839,7 @@ static int ipa3_usb_connect_teth_prot(enum ipa_usb_teth_prot teth_prot) ipa3_usb_teth_prot_to_string(teth_prot)); break; case IPA_USB_RMNET: case IPA_USB_RMNET_CV2X: case IPA_USB_MBIM: if (teth_prot_ptr->state == IPA_USB_TETH_PROT_CONNECTED) { Loading @@ -1778,7 +1847,8 @@ static int ipa3_usb_connect_teth_prot(enum ipa_usb_teth_prot teth_prot) ipa3_usb_teth_prot_to_string(teth_prot)); break; } result = ipa3_usb_init_teth_bridge(); result = ipa3_usb_init_teth_bridge(teth_prot); if (result) return result; Loading @@ -1789,14 +1859,19 @@ static int ipa3_usb_connect_teth_prot(enum ipa_usb_teth_prot teth_prot) teth_bridge_params.usb_ipa_pipe_hdl = teth_conn_params->usb_to_ipa_clnt_hdl; teth_bridge_params.tethering_mode = (teth_prot == IPA_USB_RMNET) ? (TETH_TETHERING_MODE_RMNET):(TETH_TETHERING_MODE_MBIM); ipa3_get_tethering_mode(teth_prot); if (teth_prot == IPA_USB_RMNET_CV2X) teth_bridge_params.client_type = IPA_CLIENT_USB2_PROD; else teth_bridge_params.client_type = IPA_CLIENT_USB_PROD; result = ipa3_usb_connect_teth_bridge(&teth_bridge_params); if (result) { ipa3_usb_ctx->ttype_ctx[ttype].user_data = NULL; return result; } ipa3_usb_ctx->teth_prot_ctx[teth_prot].state = IPA_USB_TETH_PROT_CONNECTED; ipa3_usb_notify_do(ttype, IPA_USB_DEVICE_READY); Loading Loading @@ -1835,11 +1910,15 @@ static int ipa3_usb_connect_teth_prot(enum ipa_usb_teth_prot teth_prot) return 0; } static int ipa3_usb_disconnect_teth_bridge(void) static int ipa3_usb_disconnect_teth_bridge(enum ipa_usb_teth_prot teth_prot) { int result; if (teth_prot == IPA_USB_RMNET_CV2X) result = teth_bridge_disconnect(IPA_CLIENT_USB2_PROD); else result = teth_bridge_disconnect(IPA_CLIENT_USB_PROD); if (result) { IPA_USB_ERR("failed to disconnect teth_bridge\n"); return result; Loading Loading @@ -1904,6 +1983,7 @@ static int ipa3_usb_disconnect_teth_prot(enum ipa_usb_teth_prot teth_prot) ipa3_usb_teth_prot_to_string(teth_prot)); break; case IPA_USB_RMNET: case IPA_USB_RMNET_CV2X: case IPA_USB_MBIM: if (teth_prot_ptr->state != IPA_USB_TETH_PROT_CONNECTED) { IPA_USB_DBG("%s (%s) is not connected\n", Loading @@ -1911,7 +1991,8 @@ static int ipa3_usb_disconnect_teth_prot(enum ipa_usb_teth_prot teth_prot) ipa3_usb_teth_bridge_prot_to_string(teth_prot)); return -EPERM; } result = ipa3_usb_disconnect_teth_bridge(); result = ipa3_usb_disconnect_teth_bridge(teth_prot); if (result) break; Loading Loading @@ -1957,8 +2038,7 @@ static int ipa3_usb_xdci_connect_internal( return -EINVAL; } ttype = (params->teth_prot == IPA_USB_DIAG) ? IPA_USB_TRANSPORT_DPL : IPA_USB_TRANSPORT_TETH; ttype = IPA3_USB_GET_TTYPE(params->teth_prot); if (!ipa3_usb_check_legal_op(IPA_USB_OP_CONNECT, ttype)) { IPA_USB_ERR("Illegal operation\n"); Loading Loading @@ -2159,7 +2239,9 @@ static int ipa3_usb_get_status_dbg_info(struct ipa3_usb_status_dbg_info *status) for (i = 0 ; i < IPA_USB_MAX_TETH_PROT_SIZE ; i++) { if (ipa3_usb_ctx->teth_prot_ctx[i].state == IPA_USB_TETH_PROT_INITIALIZED) { if ((i == IPA_USB_RMNET) || (i == IPA_USB_MBIM)) if ((i == IPA_USB_RMNET) || (i == IPA_USB_MBIM) || (i == IPA_USB_RMNET_CV2X)) status->inited_prots[status->num_init_prot++] = ipa3_usb_teth_bridge_prot_to_string(i); else Loading @@ -2169,6 +2251,7 @@ static int ipa3_usb_get_status_dbg_info(struct ipa3_usb_status_dbg_info *status) IPA_USB_TETH_PROT_CONNECTED) { switch (i) { case IPA_USB_RMNET: case IPA_USB_RMNET_CV2X: case IPA_USB_MBIM: status->teth_connected_prot = ipa3_usb_teth_bridge_prot_to_string(i); Loading Loading @@ -2652,6 +2735,24 @@ int ipa_usb_deinit_teth_prot(enum ipa_usb_teth_prot teth_prot) ipa3_usb_teth_prot_to_string(teth_prot), ipa3_usb_teth_bridge_prot_to_string(teth_prot)); break; case IPA_USB_RMNET_CV2X: if (ipa3_usb_ctx->teth_prot_ctx[teth_prot].state != IPA_USB_TETH_PROT_INITIALIZED) { IPA_USB_ERR("%s (%s) is not initialized\n", ipa3_usb_teth_prot_to_string(teth_prot), ipa3_usb_teth_bridge_prot_to_string(teth_prot)); result = -EINVAL; goto bad_params; } ipa3_usb_ctx->teth_prot_ctx[teth_prot].user_data = NULL; ipa3_usb_ctx->teth_prot_ctx[teth_prot].state = IPA_USB_TETH_PROT_INVALID; IPA_USB_DBG("deinitialized %s (%s)\n", ipa3_usb_teth_prot_to_string(teth_prot), ipa3_usb_teth_bridge_prot_to_string(teth_prot)); break; case IPA_USB_DIAG: if (teth_prot_ptr->state != IPA_USB_TETH_PROT_INITIALIZED) { Loading @@ -2672,7 +2773,8 @@ int ipa_usb_deinit_teth_prot(enum ipa_usb_teth_prot teth_prot) } if (IPA3_USB_IS_TTYPE_DPL(ttype) || (ipa3_usb_ctx->num_init_prot == 0)) { (ipa3_usb_ctx->num_init_prot == 0) || (teth_prot == IPA_USB_RMNET_CV2X)) { if (!ipa3_usb_set_state(IPA_USB_INVALID, false, ttype)) IPA_USB_ERR( "failed to change state to invalid\n"); Loading Loading @@ -3121,6 +3223,9 @@ static int __init ipa3_usb_init(void) pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH].pm_ctx; pm_ctx->hdl = ~0; pm_ctx->remote_wakeup_work = &ipa3_usb_notify_remote_wakeup_work; pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH_2].pm_ctx; pm_ctx->hdl = ~0; pm_ctx->remote_wakeup_work = &ipa3_usb_notify_remote_wakeup_work; pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_DPL].pm_ctx; pm_ctx->hdl = ~0; pm_ctx->remote_wakeup_work = &ipa3_usb_dpl_notify_remote_wakeup_work; Loading drivers/platform/msm/ipa/ipa_v3/ipa.c +7 −0 Original line number Diff line number Diff line Loading @@ -3602,13 +3602,20 @@ void ipa3_q6_pre_shutdown_cleanup(void) /* Remove delay from Q6 PRODs to avoid pending descriptors * on pipe reset procedure */ if (!ipa3_ctx->ipa_endp_delay_wa) { ipa3_q6_pipe_delay(false); ipa3_set_reset_client_prod_pipe_delay(true, IPA_CLIENT_USB_PROD); if (ipa3_ctx->ipa_config_is_auto) ipa3_set_reset_client_prod_pipe_delay(true, IPA_CLIENT_USB2_PROD); } else { ipa3_start_stop_client_prod_gsi_chnl(IPA_CLIENT_USB_PROD, false); if (ipa3_ctx->ipa_config_is_auto) ipa3_start_stop_client_prod_gsi_chnl( IPA_CLIENT_USB2_PROD, false); } IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); Loading drivers/platform/msm/ipa/ipa_v3/ipa_i.h +1 −1 Original line number Diff line number Diff line Loading @@ -2644,7 +2644,7 @@ int ipa3_teth_bridge_disconnect(enum ipa_client_type client); int ipa3_teth_bridge_connect(struct teth_bridge_connect_params *connect_params); int ipa3_teth_bridge_get_pm_hdl(void); int ipa3_teth_bridge_get_pm_hdl(enum ipa_client_type client); /* * Tethering client info Loading drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +2 −0 Original line number Diff line number Diff line Loading @@ -2998,6 +2998,7 @@ bool ipa3_should_pipe_be_suspended(enum ipa_client_type client) return false; if (client == IPA_CLIENT_USB_CONS || client == IPA_CLIENT_USB2_CONS || client == IPA_CLIENT_USB_DPL_CONS || client == IPA_CLIENT_MHI_CONS || client == IPA_CLIENT_MHI_DPL_CONS || Loading Loading @@ -5077,6 +5078,7 @@ int ipa3_write_qmap_id(struct ipa_ioc_write_qmapid *param_in) meta.qmap_id = param_in->qmap_id; if (param_in->client == IPA_CLIENT_USB_PROD || param_in->client == IPA_CLIENT_USB2_PROD || param_in->client == IPA_CLIENT_HSIC1_PROD || param_in->client == IPA_CLIENT_ODU_PROD || param_in->client == IPA_CLIENT_ETHERNET_PROD || Loading drivers/platform/msm/ipa/ipa_v3/teth_bridge.c +56 −17 Original line number Diff line number Diff line Loading @@ -38,6 +38,12 @@ #define TETH_ERR(fmt, args...) \ pr_err(TETH_BRIDGE_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args) enum ipa_num_teth_iface { IPA_TETH_IFACE_1 = 0, IPA_TETH_IFACE_2 = 1, IPA_TETH_IFACE_MAX }; /** * struct ipa3_teth_bridge_ctx - Tethering bridge driver context information * @class: kernel class pointer Loading @@ -50,7 +56,7 @@ struct ipa3_teth_bridge_ctx { dev_t dev_num; struct device *dev; struct cdev cdev; u32 modem_pm_hdl; u32 modem_pm_hdl[IPA_TETH_IFACE_MAX]; }; static struct ipa3_teth_bridge_ctx *ipa3_teth_ctx; Loading Loading @@ -121,19 +127,25 @@ int ipa3_teth_bridge_init(struct teth_bridge_init_params *params) * Return codes: handle * -EINVAL - Bad parameter */ int ipa3_teth_bridge_get_pm_hdl(void) int ipa3_teth_bridge_get_pm_hdl(enum ipa_client_type client) { u32 pm_hdl; TETH_DBG_FUNC_ENTRY(); if (client == IPA_CLIENT_USB2_PROD) pm_hdl = ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_2]; else pm_hdl = ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_1]; if (ipa3_teth_ctx->modem_pm_hdl == ~0) { if (pm_hdl == ~0) { TETH_ERR("Bad parameter\n"); TETH_DBG_FUNC_EXIT(); return -EINVAL; } TETH_DBG("Return rm-handle %d\n", ipa3_teth_ctx->modem_pm_hdl); TETH_DBG("Return pm-handle %d\n", pm_hdl); TETH_DBG_FUNC_EXIT(); return ipa3_teth_ctx->modem_pm_hdl; return pm_hdl; } /** Loading @@ -142,22 +154,33 @@ int ipa3_teth_bridge_get_pm_hdl(void) int ipa3_teth_bridge_disconnect(enum ipa_client_type client) { int res = 0; int *pm_hdl = NULL; TETH_DBG_FUNC_ENTRY(); if (ipa_pm_is_used()) { res = ipa_pm_deactivate_sync(ipa3_teth_ctx->modem_pm_hdl); if (client == IPA_CLIENT_USB2_PROD) pm_hdl = &ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_2]; else pm_hdl = &ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_1]; res = ipa_pm_deactivate_sync(*pm_hdl); if (res) { TETH_ERR("fail to deactivate modem %d\n", res); return res; } res = ipa_pm_deregister(ipa3_teth_ctx->modem_pm_hdl); ipa3_teth_ctx->modem_pm_hdl = ~0; res = ipa_pm_deregister(*pm_hdl); *pm_hdl = ~0; } else { if (client == IPA_CLIENT_USB2_PROD) { TETH_ERR("No support for rm added/validated.\n"); } else { ipa_rm_delete_dependency(IPA_RM_RESOURCE_USB_PROD, IPA_RM_RESOURCE_Q6_CONS); ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD, IPA_RM_RESOURCE_USB_CONS); } } TETH_DBG_FUNC_EXIT(); return res; Loading @@ -176,22 +199,36 @@ int ipa3_teth_bridge_connect(struct teth_bridge_connect_params *connect_params) { int res = 0; struct ipa_pm_register_params reg_params; u32 *pm = NULL; memset(®_params, 0, sizeof(reg_params)); TETH_DBG_FUNC_ENTRY(); if (ipa_pm_is_used()) { if (connect_params->tethering_mode == TETH_TETHERING_MODE_RMNET_2) { reg_params.name = "MODEM (USB RMNET_CV2X)"; pm = &ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_2]; } else { reg_params.name = "MODEM (USB RMNET)"; pm = &ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_1]; } reg_params.group = IPA_PM_GROUP_MODEM; reg_params.skip_clk_vote = true; res = ipa_pm_register(®_params, &ipa3_teth_ctx->modem_pm_hdl); pm); if (res) { TETH_ERR("fail to register with PM %d\n", res); return res; } res = ipa_pm_activate_sync(ipa3_teth_ctx->modem_pm_hdl); res = ipa_pm_activate_sync(*pm); goto bail; } if (connect_params->tethering_mode == TETH_TETHERING_MODE_RMNET_2) { res = -EINVAL; TETH_ERR("No support for rm added/validated.\n"); goto bail; } Loading Loading @@ -246,7 +283,7 @@ static const struct file_operations ipa3_teth_bridge_drv_fops = { */ int ipa3_teth_bridge_driver_init(void) { int res; int res, i; TETH_DBG("Tethering bridge driver init\n"); ipa3_teth_ctx = kzalloc(sizeof(*ipa3_teth_ctx), GFP_KERNEL); Loading Loading @@ -285,7 +322,9 @@ int ipa3_teth_bridge_driver_init(void) goto fail_cdev_add; } ipa3_teth_ctx->modem_pm_hdl = ~0; for (i = 0; i < IPA_TETH_IFACE_MAX; i++) ipa3_teth_ctx->modem_pm_hdl[i] = ~0; TETH_DBG("Tethering bridge driver init OK\n"); return 0; Loading Loading
drivers/platform/msm/ipa/ipa_clients/ipa_usb.c +132 −27 Original line number Diff line number Diff line Loading @@ -144,13 +144,15 @@ enum ipa3_usb_state { enum ipa3_usb_transport_type { IPA_USB_TRANSPORT_TETH, IPA_USB_TRANSPORT_DPL, IPA_USB_TRANSPORT_TETH_2, IPA_USB_TRANSPORT_MAX }; /* Get transport type from tethering protocol */ #define IPA3_USB_GET_TTYPE(__teth_prot) \ (((__teth_prot) == IPA_USB_DIAG) ? \ IPA_USB_TRANSPORT_DPL : IPA_USB_TRANSPORT_TETH) IPA_USB_TRANSPORT_DPL : (((__teth_prot) == IPA_USB_RMNET_CV2X) ? \ IPA_USB_TRANSPORT_TETH_2 : IPA_USB_TRANSPORT_TETH)) /* Does the given transport type is DPL? */ #define IPA3_USB_IS_TTYPE_DPL(__ttype) \ Loading Loading @@ -204,7 +206,7 @@ struct ipa3_usb_context { struct ipa3_usb_teth_prot_context teth_prot_ctx[IPA_USB_MAX_TETH_PROT_SIZE]; int num_init_prot; /* without dpl */ struct teth_bridge_init_params teth_bridge_params; struct teth_bridge_init_params teth_bridge_params[IPA_TETH_BRIDGE_MAX]; struct completion dev_ready_comp; u32 qmi_req_id; spinlock_t state_lock; Loading Loading @@ -770,6 +772,8 @@ static char *ipa3_usb_teth_prot_to_string(enum ipa_usb_teth_prot teth_prot) case IPA_USB_RMNET: case IPA_USB_MBIM: return "teth_bridge"; case IPA_USB_RMNET_CV2X: return "teth_bridge_cv2x"; case IPA_USB_DIAG: return "dpl"; default: Loading @@ -785,6 +789,8 @@ static char *ipa3_usb_teth_bridge_prot_to_string( switch (teth_prot) { case IPA_USB_RMNET: return "rmnet"; case IPA_USB_RMNET_CV2X: return "rmnet_cv2x"; case IPA_USB_MBIM: return "mbim"; default: Loading @@ -794,11 +800,18 @@ static char *ipa3_usb_teth_bridge_prot_to_string( return "unsupported"; } static int ipa3_usb_init_teth_bridge(void) static int ipa3_usb_init_teth_bridge(enum ipa_usb_teth_prot teth_prot) { int result; result = teth_bridge_init(&ipa3_usb_ctx->teth_bridge_params); if (teth_prot == IPA_USB_RMNET_CV2X) result = teth_bridge_init( &ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_2]); else result = teth_bridge_init( &ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1]); if (result) { IPA_USB_ERR("Failed to initialize teth_bridge\n"); return result; Loading @@ -812,15 +825,26 @@ static int ipa3_usb_register_pm(enum ipa3_usb_transport_type ttype) struct ipa3_usb_transport_type_ctx *ttype_ctx = &ipa3_usb_ctx->ttype_ctx[ttype]; int result; enum ipa_client_type consumer; /* * One PM resource for teth1, * One PM resource for teth2 (CV2X), * One for DPL, */ /* there is one PM resource for teth and one for DPL */ if (!IPA3_USB_IS_TTYPE_DPL(ttype) && ipa3_usb_ctx->num_init_prot > 0) if (!IPA3_USB_IS_TTYPE_DPL(ttype) && (ipa3_usb_ctx->num_init_prot > 0) && (ttype != IPA_USB_TRANSPORT_TETH_2)) return 0; memset(&ttype_ctx->pm_ctx.reg_params, 0, sizeof(ttype_ctx->pm_ctx.reg_params)); ttype_ctx->pm_ctx.reg_params.name = (ttype == IPA_USB_TRANSPORT_DPL) ? "USB DPL" : "USB"; ttype_ctx->pm_ctx.reg_params.name = (ttype == IPA_USB_TRANSPORT_DPL) ? "USB DPL" : (ttype == IPA_USB_TRANSPORT_TETH_2) ? "USB2" : "USB"; ttype_ctx->pm_ctx.reg_params.callback = ipa3_usb_pm_cb; ttype_ctx->pm_ctx.reg_params.user_data = ttype_ctx; ttype_ctx->pm_ctx.reg_params.group = IPA_PM_GROUP_DEFAULT; Loading @@ -832,9 +856,12 @@ static int ipa3_usb_register_pm(enum ipa3_usb_transport_type ttype) goto fail_pm_reg; } consumer = (ttype == IPA_USB_TRANSPORT_DPL) ? IPA_CLIENT_USB_DPL_CONS : (ttype == IPA_USB_TRANSPORT_TETH_2) ? IPA_CLIENT_USB2_CONS : IPA_CLIENT_USB_CONS; result = ipa_pm_associate_ipa_cons_to_client(ttype_ctx->pm_ctx.hdl, (ttype == IPA_USB_TRANSPORT_DPL) ? IPA_CLIENT_USB_DPL_CONS : IPA_CLIENT_USB_CONS); consumer); if (result) { IPA_USB_ERR("fail to associate cons with PM %d\n", result); goto fail_pm_cons; Loading Loading @@ -1121,9 +1148,11 @@ int ipa_usb_init_teth_prot(enum ipa_usb_teth_prot teth_prot, goto bad_params; } ipa3_usb_ctx->teth_prot_ctx[teth_prot].user_data = user_data; result = ipa3_usb_init_teth_bridge(); result = ipa3_usb_init_teth_bridge(teth_prot); if (result) goto teth_prot_init_fail; ipa3_usb_ctx->teth_prot_ctx[teth_prot].state = IPA_USB_TETH_PROT_INITIALIZED; ipa3_usb_ctx->num_init_prot++; Loading @@ -1139,6 +1168,26 @@ int ipa_usb_init_teth_prot(enum ipa_usb_teth_prot teth_prot, ipa3_register_client_callback(&ipa_usb_set_lock_unlock, &ipa3_usb_get_teth_port_state, IPA_CLIENT_USB_PROD); break; case IPA_USB_RMNET_CV2X: if (ipa3_usb_ctx->teth_prot_ctx[teth_prot].state != IPA_USB_TETH_PROT_INVALID) { IPA_USB_DBG("%s already initialized\n", ipa3_usb_teth_prot_to_string(teth_prot)); result = -EPERM; goto bad_params; } ipa3_usb_ctx->teth_prot_ctx[teth_prot].user_data = user_data; result = ipa3_usb_init_teth_bridge(teth_prot); if (result) goto teth_prot_init_fail; ipa3_usb_ctx->teth_prot_ctx[teth_prot].state = IPA_USB_TETH_PROT_INITIALIZED; IPA_USB_DBG("initialized %s %s\n", ipa3_usb_teth_prot_to_string(teth_prot), ipa3_usb_teth_bridge_prot_to_string(teth_prot)); break; case IPA_USB_DIAG: if (ipa3_usb_ctx->teth_prot_ctx[teth_prot].state != IPA_USB_TETH_PROT_INVALID) { Loading Loading @@ -1166,7 +1215,8 @@ int ipa_usb_init_teth_prot(enum ipa_usb_teth_prot teth_prot, teth_prot_init_fail: if ((IPA3_USB_IS_TTYPE_DPL(ttype)) || (ipa3_usb_ctx->num_init_prot == 0)) { || (ipa3_usb_ctx->num_init_prot == 0) || (teth_prot == IPA_USB_RMNET_CV2X)) { if (ipa_pm_is_used()) { ipa3_usb_deregister_pm(ttype); } else { Loading Loading @@ -1249,6 +1299,7 @@ static bool ipa3_usb_check_chan_params(struct ipa_usb_xdci_chan_params *params) } break; case IPA_USB_RMNET: case IPA_USB_RMNET_CV2X: case IPA_USB_MBIM: if (ipa3_usb_ctx->teth_prot_ctx[params->teth_prot].state == IPA_USB_TETH_PROT_INVALID) { Loading Loading @@ -1319,7 +1370,6 @@ static int ipa3_usb_smmu_map_xdci_channel( ipa3_usb_ctx->smmu_reg_map.cnt--; } result = ipa3_smmu_map_peer_buff(params->xfer_ring_base_addr_iova, params->xfer_ring_len, map, params->sgt_xfer_rings, IPA_SMMU_CB_AP); Loading Loading @@ -1396,11 +1446,19 @@ static int ipa3_usb_request_xdci_channel( case IPA_USB_RMNET: case IPA_USB_MBIM: chan_params.priv = ipa3_usb_ctx->teth_bridge_params.private_data; ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1].private_data; chan_params.notify = ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1].usb_notify_cb; chan_params.skip_ep_cfg = ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1].skip_ep_cfg; break; case IPA_USB_RMNET_CV2X: chan_params.priv = ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_2].private_data; chan_params.notify = ipa3_usb_ctx->teth_bridge_params.usb_notify_cb; ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_2].usb_notify_cb; chan_params.skip_ep_cfg = ipa3_usb_ctx->teth_bridge_params.skip_ep_cfg; ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_2].skip_ep_cfg; break; case IPA_USB_DIAG: chan_params.priv = NULL; Loading Loading @@ -1703,6 +1761,16 @@ static int ipa3_usb_connect_dpl(void) return 0; } static int ipa3_get_tethering_mode(enum ipa_usb_teth_prot teth_prot) { if (teth_prot == IPA_USB_RMNET) return TETH_TETHERING_MODE_RMNET; else if (teth_prot == IPA_USB_RMNET_CV2X) return TETH_TETHERING_MODE_RMNET_2; else return TETH_TETHERING_MODE_MBIM; } static int ipa3_usb_connect_teth_prot(enum ipa_usb_teth_prot teth_prot) { int result; Loading Loading @@ -1771,6 +1839,7 @@ static int ipa3_usb_connect_teth_prot(enum ipa_usb_teth_prot teth_prot) ipa3_usb_teth_prot_to_string(teth_prot)); break; case IPA_USB_RMNET: case IPA_USB_RMNET_CV2X: case IPA_USB_MBIM: if (teth_prot_ptr->state == IPA_USB_TETH_PROT_CONNECTED) { Loading @@ -1778,7 +1847,8 @@ static int ipa3_usb_connect_teth_prot(enum ipa_usb_teth_prot teth_prot) ipa3_usb_teth_prot_to_string(teth_prot)); break; } result = ipa3_usb_init_teth_bridge(); result = ipa3_usb_init_teth_bridge(teth_prot); if (result) return result; Loading @@ -1789,14 +1859,19 @@ static int ipa3_usb_connect_teth_prot(enum ipa_usb_teth_prot teth_prot) teth_bridge_params.usb_ipa_pipe_hdl = teth_conn_params->usb_to_ipa_clnt_hdl; teth_bridge_params.tethering_mode = (teth_prot == IPA_USB_RMNET) ? (TETH_TETHERING_MODE_RMNET):(TETH_TETHERING_MODE_MBIM); ipa3_get_tethering_mode(teth_prot); if (teth_prot == IPA_USB_RMNET_CV2X) teth_bridge_params.client_type = IPA_CLIENT_USB2_PROD; else teth_bridge_params.client_type = IPA_CLIENT_USB_PROD; result = ipa3_usb_connect_teth_bridge(&teth_bridge_params); if (result) { ipa3_usb_ctx->ttype_ctx[ttype].user_data = NULL; return result; } ipa3_usb_ctx->teth_prot_ctx[teth_prot].state = IPA_USB_TETH_PROT_CONNECTED; ipa3_usb_notify_do(ttype, IPA_USB_DEVICE_READY); Loading Loading @@ -1835,11 +1910,15 @@ static int ipa3_usb_connect_teth_prot(enum ipa_usb_teth_prot teth_prot) return 0; } static int ipa3_usb_disconnect_teth_bridge(void) static int ipa3_usb_disconnect_teth_bridge(enum ipa_usb_teth_prot teth_prot) { int result; if (teth_prot == IPA_USB_RMNET_CV2X) result = teth_bridge_disconnect(IPA_CLIENT_USB2_PROD); else result = teth_bridge_disconnect(IPA_CLIENT_USB_PROD); if (result) { IPA_USB_ERR("failed to disconnect teth_bridge\n"); return result; Loading Loading @@ -1904,6 +1983,7 @@ static int ipa3_usb_disconnect_teth_prot(enum ipa_usb_teth_prot teth_prot) ipa3_usb_teth_prot_to_string(teth_prot)); break; case IPA_USB_RMNET: case IPA_USB_RMNET_CV2X: case IPA_USB_MBIM: if (teth_prot_ptr->state != IPA_USB_TETH_PROT_CONNECTED) { IPA_USB_DBG("%s (%s) is not connected\n", Loading @@ -1911,7 +1991,8 @@ static int ipa3_usb_disconnect_teth_prot(enum ipa_usb_teth_prot teth_prot) ipa3_usb_teth_bridge_prot_to_string(teth_prot)); return -EPERM; } result = ipa3_usb_disconnect_teth_bridge(); result = ipa3_usb_disconnect_teth_bridge(teth_prot); if (result) break; Loading Loading @@ -1957,8 +2038,7 @@ static int ipa3_usb_xdci_connect_internal( return -EINVAL; } ttype = (params->teth_prot == IPA_USB_DIAG) ? IPA_USB_TRANSPORT_DPL : IPA_USB_TRANSPORT_TETH; ttype = IPA3_USB_GET_TTYPE(params->teth_prot); if (!ipa3_usb_check_legal_op(IPA_USB_OP_CONNECT, ttype)) { IPA_USB_ERR("Illegal operation\n"); Loading Loading @@ -2159,7 +2239,9 @@ static int ipa3_usb_get_status_dbg_info(struct ipa3_usb_status_dbg_info *status) for (i = 0 ; i < IPA_USB_MAX_TETH_PROT_SIZE ; i++) { if (ipa3_usb_ctx->teth_prot_ctx[i].state == IPA_USB_TETH_PROT_INITIALIZED) { if ((i == IPA_USB_RMNET) || (i == IPA_USB_MBIM)) if ((i == IPA_USB_RMNET) || (i == IPA_USB_MBIM) || (i == IPA_USB_RMNET_CV2X)) status->inited_prots[status->num_init_prot++] = ipa3_usb_teth_bridge_prot_to_string(i); else Loading @@ -2169,6 +2251,7 @@ static int ipa3_usb_get_status_dbg_info(struct ipa3_usb_status_dbg_info *status) IPA_USB_TETH_PROT_CONNECTED) { switch (i) { case IPA_USB_RMNET: case IPA_USB_RMNET_CV2X: case IPA_USB_MBIM: status->teth_connected_prot = ipa3_usb_teth_bridge_prot_to_string(i); Loading Loading @@ -2652,6 +2735,24 @@ int ipa_usb_deinit_teth_prot(enum ipa_usb_teth_prot teth_prot) ipa3_usb_teth_prot_to_string(teth_prot), ipa3_usb_teth_bridge_prot_to_string(teth_prot)); break; case IPA_USB_RMNET_CV2X: if (ipa3_usb_ctx->teth_prot_ctx[teth_prot].state != IPA_USB_TETH_PROT_INITIALIZED) { IPA_USB_ERR("%s (%s) is not initialized\n", ipa3_usb_teth_prot_to_string(teth_prot), ipa3_usb_teth_bridge_prot_to_string(teth_prot)); result = -EINVAL; goto bad_params; } ipa3_usb_ctx->teth_prot_ctx[teth_prot].user_data = NULL; ipa3_usb_ctx->teth_prot_ctx[teth_prot].state = IPA_USB_TETH_PROT_INVALID; IPA_USB_DBG("deinitialized %s (%s)\n", ipa3_usb_teth_prot_to_string(teth_prot), ipa3_usb_teth_bridge_prot_to_string(teth_prot)); break; case IPA_USB_DIAG: if (teth_prot_ptr->state != IPA_USB_TETH_PROT_INITIALIZED) { Loading @@ -2672,7 +2773,8 @@ int ipa_usb_deinit_teth_prot(enum ipa_usb_teth_prot teth_prot) } if (IPA3_USB_IS_TTYPE_DPL(ttype) || (ipa3_usb_ctx->num_init_prot == 0)) { (ipa3_usb_ctx->num_init_prot == 0) || (teth_prot == IPA_USB_RMNET_CV2X)) { if (!ipa3_usb_set_state(IPA_USB_INVALID, false, ttype)) IPA_USB_ERR( "failed to change state to invalid\n"); Loading Loading @@ -3121,6 +3223,9 @@ static int __init ipa3_usb_init(void) pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH].pm_ctx; pm_ctx->hdl = ~0; pm_ctx->remote_wakeup_work = &ipa3_usb_notify_remote_wakeup_work; pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH_2].pm_ctx; pm_ctx->hdl = ~0; pm_ctx->remote_wakeup_work = &ipa3_usb_notify_remote_wakeup_work; pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_DPL].pm_ctx; pm_ctx->hdl = ~0; pm_ctx->remote_wakeup_work = &ipa3_usb_dpl_notify_remote_wakeup_work; Loading
drivers/platform/msm/ipa/ipa_v3/ipa.c +7 −0 Original line number Diff line number Diff line Loading @@ -3602,13 +3602,20 @@ void ipa3_q6_pre_shutdown_cleanup(void) /* Remove delay from Q6 PRODs to avoid pending descriptors * on pipe reset procedure */ if (!ipa3_ctx->ipa_endp_delay_wa) { ipa3_q6_pipe_delay(false); ipa3_set_reset_client_prod_pipe_delay(true, IPA_CLIENT_USB_PROD); if (ipa3_ctx->ipa_config_is_auto) ipa3_set_reset_client_prod_pipe_delay(true, IPA_CLIENT_USB2_PROD); } else { ipa3_start_stop_client_prod_gsi_chnl(IPA_CLIENT_USB_PROD, false); if (ipa3_ctx->ipa_config_is_auto) ipa3_start_stop_client_prod_gsi_chnl( IPA_CLIENT_USB2_PROD, false); } IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); Loading
drivers/platform/msm/ipa/ipa_v3/ipa_i.h +1 −1 Original line number Diff line number Diff line Loading @@ -2644,7 +2644,7 @@ int ipa3_teth_bridge_disconnect(enum ipa_client_type client); int ipa3_teth_bridge_connect(struct teth_bridge_connect_params *connect_params); int ipa3_teth_bridge_get_pm_hdl(void); int ipa3_teth_bridge_get_pm_hdl(enum ipa_client_type client); /* * Tethering client info Loading
drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +2 −0 Original line number Diff line number Diff line Loading @@ -2998,6 +2998,7 @@ bool ipa3_should_pipe_be_suspended(enum ipa_client_type client) return false; if (client == IPA_CLIENT_USB_CONS || client == IPA_CLIENT_USB2_CONS || client == IPA_CLIENT_USB_DPL_CONS || client == IPA_CLIENT_MHI_CONS || client == IPA_CLIENT_MHI_DPL_CONS || Loading Loading @@ -5077,6 +5078,7 @@ int ipa3_write_qmap_id(struct ipa_ioc_write_qmapid *param_in) meta.qmap_id = param_in->qmap_id; if (param_in->client == IPA_CLIENT_USB_PROD || param_in->client == IPA_CLIENT_USB2_PROD || param_in->client == IPA_CLIENT_HSIC1_PROD || param_in->client == IPA_CLIENT_ODU_PROD || param_in->client == IPA_CLIENT_ETHERNET_PROD || Loading
drivers/platform/msm/ipa/ipa_v3/teth_bridge.c +56 −17 Original line number Diff line number Diff line Loading @@ -38,6 +38,12 @@ #define TETH_ERR(fmt, args...) \ pr_err(TETH_BRIDGE_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args) enum ipa_num_teth_iface { IPA_TETH_IFACE_1 = 0, IPA_TETH_IFACE_2 = 1, IPA_TETH_IFACE_MAX }; /** * struct ipa3_teth_bridge_ctx - Tethering bridge driver context information * @class: kernel class pointer Loading @@ -50,7 +56,7 @@ struct ipa3_teth_bridge_ctx { dev_t dev_num; struct device *dev; struct cdev cdev; u32 modem_pm_hdl; u32 modem_pm_hdl[IPA_TETH_IFACE_MAX]; }; static struct ipa3_teth_bridge_ctx *ipa3_teth_ctx; Loading Loading @@ -121,19 +127,25 @@ int ipa3_teth_bridge_init(struct teth_bridge_init_params *params) * Return codes: handle * -EINVAL - Bad parameter */ int ipa3_teth_bridge_get_pm_hdl(void) int ipa3_teth_bridge_get_pm_hdl(enum ipa_client_type client) { u32 pm_hdl; TETH_DBG_FUNC_ENTRY(); if (client == IPA_CLIENT_USB2_PROD) pm_hdl = ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_2]; else pm_hdl = ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_1]; if (ipa3_teth_ctx->modem_pm_hdl == ~0) { if (pm_hdl == ~0) { TETH_ERR("Bad parameter\n"); TETH_DBG_FUNC_EXIT(); return -EINVAL; } TETH_DBG("Return rm-handle %d\n", ipa3_teth_ctx->modem_pm_hdl); TETH_DBG("Return pm-handle %d\n", pm_hdl); TETH_DBG_FUNC_EXIT(); return ipa3_teth_ctx->modem_pm_hdl; return pm_hdl; } /** Loading @@ -142,22 +154,33 @@ int ipa3_teth_bridge_get_pm_hdl(void) int ipa3_teth_bridge_disconnect(enum ipa_client_type client) { int res = 0; int *pm_hdl = NULL; TETH_DBG_FUNC_ENTRY(); if (ipa_pm_is_used()) { res = ipa_pm_deactivate_sync(ipa3_teth_ctx->modem_pm_hdl); if (client == IPA_CLIENT_USB2_PROD) pm_hdl = &ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_2]; else pm_hdl = &ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_1]; res = ipa_pm_deactivate_sync(*pm_hdl); if (res) { TETH_ERR("fail to deactivate modem %d\n", res); return res; } res = ipa_pm_deregister(ipa3_teth_ctx->modem_pm_hdl); ipa3_teth_ctx->modem_pm_hdl = ~0; res = ipa_pm_deregister(*pm_hdl); *pm_hdl = ~0; } else { if (client == IPA_CLIENT_USB2_PROD) { TETH_ERR("No support for rm added/validated.\n"); } else { ipa_rm_delete_dependency(IPA_RM_RESOURCE_USB_PROD, IPA_RM_RESOURCE_Q6_CONS); ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD, IPA_RM_RESOURCE_USB_CONS); } } TETH_DBG_FUNC_EXIT(); return res; Loading @@ -176,22 +199,36 @@ int ipa3_teth_bridge_connect(struct teth_bridge_connect_params *connect_params) { int res = 0; struct ipa_pm_register_params reg_params; u32 *pm = NULL; memset(®_params, 0, sizeof(reg_params)); TETH_DBG_FUNC_ENTRY(); if (ipa_pm_is_used()) { if (connect_params->tethering_mode == TETH_TETHERING_MODE_RMNET_2) { reg_params.name = "MODEM (USB RMNET_CV2X)"; pm = &ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_2]; } else { reg_params.name = "MODEM (USB RMNET)"; pm = &ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_1]; } reg_params.group = IPA_PM_GROUP_MODEM; reg_params.skip_clk_vote = true; res = ipa_pm_register(®_params, &ipa3_teth_ctx->modem_pm_hdl); pm); if (res) { TETH_ERR("fail to register with PM %d\n", res); return res; } res = ipa_pm_activate_sync(ipa3_teth_ctx->modem_pm_hdl); res = ipa_pm_activate_sync(*pm); goto bail; } if (connect_params->tethering_mode == TETH_TETHERING_MODE_RMNET_2) { res = -EINVAL; TETH_ERR("No support for rm added/validated.\n"); goto bail; } Loading Loading @@ -246,7 +283,7 @@ static const struct file_operations ipa3_teth_bridge_drv_fops = { */ int ipa3_teth_bridge_driver_init(void) { int res; int res, i; TETH_DBG("Tethering bridge driver init\n"); ipa3_teth_ctx = kzalloc(sizeof(*ipa3_teth_ctx), GFP_KERNEL); Loading Loading @@ -285,7 +322,9 @@ int ipa3_teth_bridge_driver_init(void) goto fail_cdev_add; } ipa3_teth_ctx->modem_pm_hdl = ~0; for (i = 0; i < IPA_TETH_IFACE_MAX; i++) ipa3_teth_ctx->modem_pm_hdl[i] = ~0; TETH_DBG("Tethering bridge driver init OK\n"); return 0; Loading