diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 019a666ef9cb..f501fe088731 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -3124,6 +3124,77 @@ int gsi_start_channel(unsigned long chan_hdl) } EXPORT_SYMBOL(gsi_start_channel); +static void gsi_dump_ch(unsigned long chan_hdl) +{ + uint32_t val; + + if (!gsi_ctx) { + pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); + return; + } + + if (chan_hdl >= gsi_ctx->max_ch) { + GSIDBG("invalid chan id %u\n", chan_hdl); + return; + } + + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_CNTXT_0_OFFS(chan_hdl, gsi_ctx->per.ee)); + GSIERR("CH%2d CTX0 0x%x\n", chan_hdl, val); + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_CNTXT_1_OFFS(chan_hdl, gsi_ctx->per.ee)); + GSIERR("CH%2d CTX1 0x%x\n", chan_hdl, val); + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_CNTXT_2_OFFS(chan_hdl, gsi_ctx->per.ee)); + GSIERR("CH%2d CTX2 0x%x\n", chan_hdl, val); + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_CNTXT_3_OFFS(chan_hdl, gsi_ctx->per.ee)); + GSIERR("CH%2d CTX3 0x%x\n", chan_hdl, val); + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_CNTXT_4_OFFS(chan_hdl, gsi_ctx->per.ee)); + GSIERR("CH%2d CTX4 0x%x\n", chan_hdl, val); + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_CNTXT_5_OFFS(chan_hdl, gsi_ctx->per.ee)); + GSIERR("CH%2d CTX5 0x%x\n", chan_hdl, val); + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_CNTXT_6_OFFS(chan_hdl, gsi_ctx->per.ee)); + GSIERR("CH%2d CTX6 0x%x\n", chan_hdl, val); + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_CNTXT_7_OFFS(chan_hdl, gsi_ctx->per.ee)); + GSIERR("CH%2d CTX7 0x%x\n", chan_hdl, val); + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_RE_FETCH_READ_PTR_OFFS(chan_hdl, + gsi_ctx->per.ee)); + GSIERR("CH%2d REFRP 0x%x\n", chan_hdl, val); + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_RE_FETCH_WRITE_PTR_OFFS(chan_hdl, + gsi_ctx->per.ee)); + GSIERR("CH%2d REFWP 0x%x\n", chan_hdl, val); + if (gsi_ctx->per.ver >= GSI_VER_2_5) { + val = gsi_readl(gsi_ctx->base + + GSI_V2_5_EE_n_GSI_CH_k_QOS_OFFS(chan_hdl, gsi_ctx->per.ee)); + } else { + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_QOS_OFFS(chan_hdl, gsi_ctx->per.ee)); + } + GSIERR("CH%2d QOS 0x%x\n", chan_hdl, val); + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_0_OFFS(chan_hdl, gsi_ctx->per.ee)); + GSIERR("CH%2d SCR0 0x%x\n", chan_hdl, val); + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_1_OFFS(chan_hdl, gsi_ctx->per.ee)); + GSIERR("CH%2d SCR1 0x%x\n", chan_hdl, val); + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_2_OFFS(chan_hdl, gsi_ctx->per.ee)); + GSIERR("CH%2d SCR2 0x%x\n", chan_hdl, val); + val = gsi_readl(gsi_ctx->base + + GSI_EE_n_GSI_CH_k_SCRATCH_3_OFFS(chan_hdl, gsi_ctx->per.ee)); + GSIERR("CH%2d SCR3 0x%x\n", chan_hdl, val); + + return; +} + + int gsi_stop_channel(unsigned long chan_hdl) { enum gsi_ch_cmd_opcode op = GSI_CH_STOP; @@ -3176,7 +3247,7 @@ int gsi_stop_channel(unsigned long chan_hdl) gsi_writel(val, gsi_ctx->base + GSI_EE_n_GSI_CH_CMD_OFFS(gsi_ctx->per.ee)); - GSIDBG("GSI Channel Stop, waiting for completion\n"); + GSIDBG("GSI Channel Stop, waiting for completion: 0x%x\n", val); gsi_channel_state_change_wait(chan_hdl, ctx, GSI_STOP_CMD_TIMEOUT_MS, op); @@ -3184,6 +3255,7 @@ int gsi_stop_channel(unsigned long chan_hdl) if (ctx->state != GSI_CHAN_STATE_STOPPED && ctx->state != GSI_CHAN_STATE_STOP_IN_PROC) { GSIERR("chan=%lu unexpected state=%u\n", chan_hdl, ctx->state); + gsi_dump_ch(chan_hdl); res = -GSI_STATUS_BAD_STATE; BUG(); goto free_lock; @@ -3936,6 +4008,12 @@ int gsi_poll_n_channel(unsigned long chan_hdl, return -GSI_STATUS_UNSUPPORTED_OP; } + /* Before going to poll packet make sure it was in allocated state */ + if (unlikely(ctx->state == GSI_CHAN_STATE_NOT_ALLOCATED)) { + GSIERR("bad state %d\n", ctx->state); + return -GSI_STATUS_UNSUPPORTED_OP; + } + if (!ctx->evtr) { GSIERR("no event ring associated chan_hdl=%lu\n", chan_hdl); return -GSI_STATUS_UNSUPPORTED_OP; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 918a037392d5..9632851a331e 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -3965,6 +3965,8 @@ void ipa3_update_ssr_state(bool is_ssr) */ void ipa3_q6_pre_shutdown_cleanup(void) { + bool prod = false; + IPADBG_LOW("ENTER\n"); IPA_ACTIVE_CLIENTS_INC_SIMPLE(); @@ -3973,6 +3975,10 @@ void ipa3_q6_pre_shutdown_cleanup(void) if (!ipa3_ctx->ipa_endp_delay_wa) ipa3_q6_pipe_delay(true); ipa3_q6_avoid_holb(); + if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) { + prod = true; + ipa3_halt_q6_gsi_channels(prod); + } if (ipa3_ctx->ipa_config_is_mhi) ipa3_set_reset_client_cons_pipe_sus_holb(true, IPA_CLIENT_MHI_CONS); @@ -4030,8 +4036,6 @@ void ipa3_q6_post_shutdown_cleanup(void) /* halt both prod and cons channels starting at IPAv4 */ if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) { - prod = true; - ipa3_halt_q6_gsi_channels(prod); IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); IPADBG("Exit without consumer check\n"); return; @@ -6573,6 +6577,7 @@ static void ipa3_load_ipa_fw(struct work_struct *work) if (result) { IPAERR("IPA FW loading process has failed result=%d\n", result); + ipa_assert(); return; } mutex_lock(&ipa3_ctx->fw_load_data.lock); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index 678fb5bc76bf..fcd0160ed462 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -1479,11 +1479,10 @@ int ipa3_teardown_sys_pipe(u32 clnt_hdl) return result; } - if (ep->sys->napi_obj) { - do { - usleep_range(95, 105); - } while (atomic_read(&ep->sys->curr_polling_state)); - } + /* Wait untill end point moving to interrupt mode before teardown */ + do { + usleep_range(95, 105); + } while (atomic_read(&ep->sys->curr_polling_state)); if (IPA_CLIENT_IS_CONS(ep->client)) cancel_delayed_work_sync(&ep->sys->replenish_rx_work); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c index 9e34e69abb5a..fc19614bc2d3 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c @@ -445,7 +445,6 @@ static void activate_work_func(struct work_struct *work) IPA_PM_CLIENT_ACTIVATED); } else { IPA_PM_ERR_RL("client has no callback"); - WARN_ON_RATELIMIT_IPA(1); } mutex_unlock(&ipa_pm_ctx->client_mutex); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c index f379a4fbe0ba..e9d1c84f968b 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c @@ -474,6 +474,7 @@ static int ipa3_qmi_send_req_wait(struct qmi_handle *client_handle, return ret; } + mutex_lock(&ipa3_qmi_lock); ret = qmi_send_request(client_handle, &ipa3_qmi_ctx->server_sq, &txn, @@ -482,6 +483,10 @@ static int ipa3_qmi_send_req_wait(struct qmi_handle *client_handle, req_desc->ei_array, req); + if (unlikely(!ipa_q6_clnt)) + return -EINVAL; + mutex_unlock(&ipa3_qmi_lock); + if (ret < 0) { qmi_txn_cancel(&txn); return ret; @@ -1507,9 +1512,11 @@ static void ipa3_q6_clnt_svc_arrive(struct work_struct *work) IPAWANERR( "ipa3_qmi_init_modem_send_sync_msg failed due to SSR!\n"); /* Cleanup when ipa3_wwan_remove is called */ + mutex_lock(&ipa3_qmi_lock); qmi_handle_release(ipa_q6_clnt); vfree(ipa_q6_clnt); ipa_q6_clnt = NULL; + mutex_unlock(&ipa3_qmi_lock); return; } @@ -1849,6 +1856,7 @@ void ipa3_qmi_service_exit(void) /* qmi-client */ /* Release client handle */ + mutex_lock(&ipa3_qmi_lock); if (ipa_q6_clnt != NULL) { qmi_handle_release(ipa_q6_clnt); vfree(ipa_q6_clnt); @@ -1860,7 +1868,6 @@ void ipa3_qmi_service_exit(void) } /* clean the QMI msg cache */ - mutex_lock(&ipa3_qmi_lock); if (ipa3_qmi_ctx != NULL) { vfree(ipa3_qmi_ctx); ipa3_qmi_ctx = NULL; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c index 6905fd163476..d948dd3eb425 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c @@ -2198,6 +2198,7 @@ int ipa3_enable_gsi_wdi_pipe(u32 clnt_hdl) struct ipa3_ep_context *ep; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; int ipa_ep_idx; + struct ipa_ep_cfg_holb holb_cfg; IPADBG("ep=%d\n", clnt_hdl); @@ -2218,6 +2219,14 @@ int ipa3_enable_gsi_wdi_pipe(u32 clnt_hdl) memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); ipa3_cfg_ep_ctrl(ipa_ep_idx, &ep_cfg_ctrl); + if (IPA_CLIENT_IS_CONS(ep->client)) { + memset(&holb_cfg, 0, sizeof(holb_cfg)); + holb_cfg.en = IPA_HOLB_TMR_DIS; + holb_cfg.tmr_val = 0; + ipa3_cfg_ep_holb(clnt_hdl, &holb_cfg); + } + + IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl)); ep->gsi_offload_state |= IPA_WDI_ENABLED; IPADBG("client (ep: %d) enabled\n", clnt_hdl); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 4d506d38d400..3baff1ed2c5c 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -7058,9 +7058,9 @@ mark_sw_cnt: done: /* get a handle from idr for dealloc */ counter->hdl = __ipa3_alloc_counter_hdl(counter); + memcpy(header, counter, sizeof(struct ipa_ioc_flt_rt_counter_alloc)); spin_unlock(&ipa3_ctx->flt_rt_counters.hdl_lock); idr_preload_end(); - memcpy(header, counter, sizeof(struct ipa_ioc_flt_rt_counter_alloc)); return 0; err: diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c index 81d093b9a3e3..69d9656eb3a5 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c @@ -2857,12 +2857,13 @@ static int ipa3_lcl_mdm_ssr_notifier_cb(struct notifier_block *this, switch (code) { case SUBSYS_BEFORE_SHUTDOWN: IPAWANINFO("IPA received MPSS BEFORE_SHUTDOWN\n"); + /*Stop netdev first to stop queueing pkts to Q6 */ + if (IPA_NETDEV()) + netif_stop_queue(IPA_NETDEV()); /* send SSR before-shutdown notification to IPACM */ rmnet_ipa_send_ssr_notification(false); atomic_set(&rmnet_ipa3_ctx->is_ssr, 1); ipa3_q6_pre_shutdown_cleanup(); - if (IPA_NETDEV()) - netif_stop_queue(IPA_NETDEV()); ipa3_qmi_stop_workqueues(); ipa3_wan_ioctl_stop_qmi_messages(); ipa_stop_polling_stats();