/** * ipa_mhi_start() - Start IPA MHI engine * @params: pcie addresses for MHI * * This function is called by MHI client driver on MHI engine start for * handling MHI accelerated channels. This function is called after * ipa_mhi_init() was called and can be called after MHI reset to restart MHI * engine. When this function returns device can move to M0 state. * This function is doing the following: * - Send command to uC for initialization of MHI engine * - Add dependencies to IPA RM * - Request MHI_PROD in IPA RM * * Return codes: 0 : success * negative : error */ int ipa_mhi_start(struct ipa_mhi_start_params *params) { int res; IPA_MHI_FUNC_ENTRY(); if (!params) { IPA_MHI_ERR("null args\n"); return -EINVAL; } if (unlikely(!ipa_mhi_ctx)) { IPA_MHI_ERR("IPA MHI was not initialized\n"); return -EINVAL; } if (ipa_uc_state_check()) { IPA_MHI_ERR("IPA uc is not loaded\n"); return -EAGAIN; } res = ipa_mhi_set_state(IPA_MHI_STATE_STARTED); if (res) { IPA_MHI_ERR("ipa_mhi_set_state %d\n", res); return res; } ipa_mhi_ctx->host_ctrl_addr = params->host_ctrl_addr; ipa_mhi_ctx->host_data_addr = params->host_data_addr; /* Add MHI <-> Q6 dependencies to IPA RM */ res = ipa_rm_add_dependency(IPA_RM_RESOURCE_MHI_PROD, IPA_RM_RESOURCE_Q6_CONS); if (res && res != -EINPROGRESS) { IPA_MHI_ERR("failed to add dependency %d\n", res); goto fail_add_mhi_q6_dep; } res = ipa_rm_add_dependency(IPA_RM_RESOURCE_Q6_PROD, IPA_RM_RESOURCE_MHI_CONS); if (res && res != -EINPROGRESS) { IPA_MHI_ERR("failed to add dependency %d\n", res); goto fail_add_q6_mhi_dep; } res = ipa_mhi_request_prod(); if (res) { IPA_MHI_ERR("failed request prod %d\n", res); goto fail_request_prod; } /* Initialize IPA MHI engine */ res = ipa_uc_mhi_init_engine(&ipa_mhi_ctx->msi, ipa_mhi_ctx->mmio_addr, ipa_mhi_ctx->host_ctrl_addr, ipa_mhi_ctx->host_data_addr, ipa_mhi_ctx->first_ch_idx, ipa_mhi_ctx->first_er_idx); if (res) { IPA_MHI_ERR("failed to start MHI engine %d\n", res); goto fail_init_engine; } /* Update UL/DL sync if valid */ res = ipa_uc_mhi_send_dl_ul_sync_info(cached_dl_ul_sync_info); if (res) { IPA_MHI_ERR("failed to update ul/dl sync %d\n", res); goto fail_init_engine; } IPA_MHI_FUNC_EXIT(); return 0; fail_init_engine: ipa_mhi_release_prod(); fail_request_prod: ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD, IPA_RM_RESOURCE_MHI_CONS); fail_add_q6_mhi_dep: ipa_rm_delete_dependency(IPA_RM_RESOURCE_MHI_PROD, IPA_RM_RESOURCE_Q6_CONS); fail_add_mhi_q6_dep: ipa_mhi_set_state(IPA_MHI_STATE_INITIALIZED); return res; }
static int __init wwan_init(void) { int ret; struct net_device *dev; struct wwan_private *wwan_ptr; unsigned n; struct ipa_rm_create_params ipa_rm_params; pr_info("%s: WWAN devices[%d]\n", __func__, WWAN_DEVICE_COUNT); for (n = 0; n < WWAN_DEVICE_COUNT; n++) { dev = alloc_netdev(sizeof(struct wwan_private), WWAN_DEV_NAME, wwan_setup); if (!dev) { pr_err("%s: no memory for netdev %d\n", __func__, n); ret = -ENOMEM; goto fail; } netdevs[n] = dev; wwan_ptr = netdev_priv(dev); wwan_ptr->ch_id = n; spin_lock_init(&wwan_ptr->lock); init_completion(&wwan_ptr->resource_granted_completion); memset(&ipa_rm_params, 0, sizeof(struct ipa_rm_create_params)); ipa_rm_params.name = ipa_rm_resource_by_ch_id[n]; ipa_rm_params.reg_params.user_data = dev; ipa_rm_params.reg_params.notify_cb = ipa_rm_notify; ret = ipa_rm_create_resource(&ipa_rm_params); if (ret) { pr_err("%s: unable to create resourse %d in IPA RM\n", __func__, ipa_rm_resource_by_ch_id[n]); goto fail; } ret = ipa_rm_inactivity_timer_init(ipa_rm_resource_by_ch_id[n], IPA_RM_INACTIVITY_TIMER); if (ret) { pr_err("%s: ipa rm timer init failed %d on ins %d\n", __func__, ret, n); goto fail; } ret = ipa_rm_add_dependency(ipa_rm_resource_by_ch_id[n], IPA_RM_RESOURCE_A2_CONS); if (ret) { pr_err("%s: unable to add dependency %d rc=%d\n", __func__, n, ret); goto fail; } ret = register_netdev(dev); if (ret) { pr_err("%s: unable to register netdev %d rc=%d\n", __func__, n, ret); goto fail; } } return 0; fail: for (n = 0; n < WWAN_DEVICE_COUNT; n++) { if (!netdevs[n]) break; unregister_netdev(netdevs[n]); ipa_rm_inactivity_timer_destroy(ipa_rm_resource_by_ch_id[n]); free_netdev(netdevs[n]); netdevs[n] = NULL; } return ret; }