From ecf3b98c7c016ac9244d6bf9c1cb1de78e2c0524 Mon Sep 17 00:00:00 2001 From: Ashok Vuyyuru Date: Thu, 30 Jan 2020 19:59:05 +0530 Subject: [PATCH] msm: ipa3: Update the channel mode before start channel Observing the race condition if channel mode configured after channel start. To avoid these race conditions configuring the channel mode and starting the channel. Change-Id: I8f8ec2d9faed320539e2b18de90ab24059a5616c --- drivers/platform/msm/gsi/gsi.c | 6 ++++-- drivers/platform/msm/ipa/ipa_v3/ipa_dp.c | 11 ++++++++--- drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 2 ++ drivers/platform/msm/ipa/ipa_v3/ipa_utils.c | 15 ++++++++++----- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 98edaf21c748..b070a36c0f74 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -3979,17 +3979,19 @@ int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode) return -GSI_STATUS_UNSUPPORTED_OP; } + spin_lock_irqsave(&gsi_ctx->slock, flags); + if (atomic_read(&ctx->poll_mode)) curr = GSI_CHAN_MODE_POLL; else curr = GSI_CHAN_MODE_CALLBACK; if (mode == curr) { - GSIDBG("already in requested mode %u chan_hdl=%lu\n", + GSIERR("already in requested mode %u chan_hdl=%lu\n", curr, chan_hdl); + spin_unlock_irqrestore(&gsi_ctx->slock, flags); return -GSI_STATUS_UNSUPPORTED_OP; } - spin_lock_irqsave(&gsi_ctx->slock, flags); if (curr == GSI_CHAN_MODE_CALLBACK && mode == GSI_CHAN_MODE_POLL) { __gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->evtr->id, 0); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index 8bd99389e5c8..c696707f419c 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -1937,6 +1937,7 @@ static void ipa3_wq_handle_rx(struct work_struct *work) if (sys->napi_obj) { ipa_pm_activate_sync(sys->pm_hdl); napi_schedule(sys->napi_obj); + IPA_STATS_INC_CNT(sys->napi_sch_cnt); } else if (IPA_CLIENT_IS_LOW_LAT_CONS(sys->ep->client)) { ipa_pm_activate_sync(sys->pm_hdl); tasklet_schedule(&sys->tasklet); @@ -4590,13 +4591,16 @@ void __ipa_gsi_irq_rx_scedule_poll(struct ipa3_sys_context *sys) * or after NAPI poll */ clk_off = ipa_pm_activate(sys->pm_hdl); - if (!clk_off && sys->napi_obj) + if (!clk_off && sys->napi_obj) { napi_schedule(sys->napi_obj); - else if (!clk_off && + IPA_STATS_INC_CNT(sys->napi_sch_cnt); + } else if (!clk_off && IPA_CLIENT_IS_LOW_LAT_CONS(sys->ep->client)) { tasklet_schedule(&sys->tasklet); - } else + } else { queue_work(sys->wq, &sys->work); + } + } static void ipa_gsi_irq_rx_notify_cb(struct gsi_chan_xfer_notify *notify) @@ -5312,6 +5316,7 @@ start_poll: if (cnt < weight && ep->sys->len > IPA_DEFAULT_SYS_YELLOW_WM && wan_def_sys->len > IPA_DEFAULT_SYS_YELLOW_WM) { napi_complete(ep->sys->napi_obj); + IPA_STATS_INC_CNT(ep->sys->napi_comp_cnt); ret = ipa3_rx_switch_to_intr_mode(ep->sys); if (ret == -GSI_STATUS_PENDING_IRQ && napi_reschedule(ep->sys->napi_obj)) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index e00ee682e10f..435550eb21f6 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -1100,6 +1100,8 @@ struct ipa3_sys_context { struct workqueue_struct *repl_wq; struct ipa3_status_stats *status_stat; u32 pm_hdl; + unsigned int napi_sch_cnt; + unsigned int napi_comp_cnt; /* ordering is important - other immutable fields go below */ }; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 26a0b75a9109..06e22beba7ef 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -8507,6 +8507,16 @@ static int _ipa_suspend_resume_pipe(enum ipa_client_type client, bool suspend) ipa_assert(); } } else { + if (IPA_CLIENT_IS_APPS_PROD(client) || + (client == IPA_CLIENT_APPS_WAN_CONS && + coal_ep_idx != IPA_EP_NOT_ALLOCATED)) + goto chan_statrt; + if (!atomic_read(&ep->sys->curr_polling_state)) { + IPADBG("switch ch %ld to callback\n", ep->gsi_chan_hdl); + gsi_config_channel_mode(ep->gsi_chan_hdl, + GSI_CHAN_MODE_CALLBACK); + } +chan_statrt: res = gsi_start_channel(ep->gsi_chan_hdl); if (res) { IPAERR("failed to start LAN channel\n"); @@ -8533,12 +8543,7 @@ static int _ipa_suspend_resume_pipe(enum ipa_client_type client, bool suspend) gsi_config_channel_mode(ep->gsi_chan_hdl, GSI_CHAN_MODE_POLL); if (!ipa3_gsi_channel_is_quite(ep)) return -EAGAIN; - } else if (!atomic_read(&ep->sys->curr_polling_state)) { - IPADBG("switch ch %ld to callback\n", ep->gsi_chan_hdl); - gsi_config_channel_mode(ep->gsi_chan_hdl, - GSI_CHAN_MODE_CALLBACK); } - return 0; }