Loading drivers/platform/msm/gsi/gsi.c +82 −33 Original line number Diff line number Diff line Loading @@ -23,7 +23,9 @@ #include "gsi_emulation.h" #define GSI_CMD_TIMEOUT (5*HZ) #define GSI_STOP_CMD_TIMEOUT_MS 50 #define GSI_START_CMD_TIMEOUT_MS 1000 #define GSI_CMD_POLL_CNT 5 #define GSI_STOP_CMD_TIMEOUT_MS 10 #define GSI_MAX_CH_LOW_WEIGHT 15 #define GSI_RESET_WA_MIN_SLEEP 1000 Loading Loading @@ -112,6 +114,65 @@ static void __gsi_config_gen_irq(int ee, uint32_t mask, uint32_t val) GSI_EE_n_CNTXT_GSI_IRQ_EN_OFFS(ee)); } static void gsi_channel_state_change_wait(unsigned long chan_hdl, struct gsi_chan_ctx *ctx, uint32_t tm, enum gsi_chan_state next_state) { int poll_cnt; int gsi_pending_intr; int res; uint32_t ch; uint32_t val; int ee = gsi_ctx->per.ee; /* * Start polling the GSI channel for * duration = tm * poll_cnt. * We need to do polling of gsi state for improving debugability * of gsi hw state. */ for (poll_cnt = 0; poll_cnt < GSI_CMD_POLL_CNT; poll_cnt++) { res = wait_for_completion_timeout(&ctx->compl, msecs_to_jiffies(tm)); /* Interrupt received, return */ if (res != 0) return; /* * Check channel state here in case the channel is * already started but interrupt is not yet received. */ val = gsi_readl(gsi_ctx->base + GSI_EE_n_GSI_CH_k_CNTXT_0_OFFS(chan_hdl, gsi_ctx->per.ee)); ctx->state = (val & GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_BMSK) >> GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_SHFT; ch = gsi_readl(gsi_ctx->base + GSI_EE_n_CNTXT_TYPE_IRQ_OFFS(gsi_ctx->per.ee)); gsi_pending_intr = gsi_readl(gsi_ctx->base + GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_OFFS(ee)); GSIDBG("GSI wait on chan_hld=%lu chan=%lu state=%u intr=%u\n", chan_hdl, ch, ctx->state, gsi_pending_intr); if (ctx->state == next_state) break; } } static void gsi_handle_ch_ctrl(int ee) { uint32_t ch; Loading Loading @@ -2317,7 +2378,6 @@ EXPORT_SYMBOL(gsi_query_channel_db_addr); int gsi_start_channel(unsigned long chan_hdl) { enum gsi_ch_cmd_opcode op = GSI_CH_START; int res; uint32_t val; struct gsi_chan_ctx *ctx; Loading Loading @@ -2350,21 +2410,25 @@ int gsi_start_channel(unsigned long chan_hdl) GSI_EE_n_GSI_CH_CMD_OPCODE_BMSK)); gsi_writel(val, gsi_ctx->base + GSI_EE_n_GSI_CH_CMD_OFFS(gsi_ctx->per.ee)); res = wait_for_completion_timeout(&ctx->compl, GSI_CMD_TIMEOUT); if (res == 0) { GSIERR("chan_hdl=%lu timed out\n", chan_hdl); mutex_unlock(&gsi_ctx->mlock); return -GSI_STATUS_TIMED_OUT; } GSIDBG("GSI Channel Start, waiting for completion\n"); gsi_channel_state_change_wait(chan_hdl, ctx, GSI_START_CMD_TIMEOUT_MS, GSI_CHAN_STATE_STARTED); if (ctx->state != GSI_CHAN_STATE_STARTED) { GSIERR("chan=%lu unexpected state=%u\n", chan_hdl, ctx->state); /* * Hardware returned unexpected status, unexpected * hardware state. */ GSIERR("chan=%lu timed out, unexpected state=%u\n", chan_hdl, ctx->state); BUG(); } GSIDBG("GSI Channel=%lu Start success\n", chan_hdl); /* write order MUST be MSB followed by LSB */ val = ((ctx->ring.wp_local >> 32) & GSI_EE_n_GSI_CH_k_DOORBELL_1_WRITE_PTR_MSB_BMSK) << Loading Loading @@ -2420,27 +2484,12 @@ int gsi_stop_channel(unsigned long chan_hdl) GSI_EE_n_GSI_CH_CMD_OPCODE_BMSK)); gsi_writel(val, gsi_ctx->base + GSI_EE_n_GSI_CH_CMD_OFFS(gsi_ctx->per.ee)); res = wait_for_completion_timeout(&ctx->compl, msecs_to_jiffies(GSI_STOP_CMD_TIMEOUT_MS)); if (res == 0) { /* * check channel state here in case the channel is stopped but * the interrupt was not handled yet. */ val = gsi_readl(gsi_ctx->base + GSI_EE_n_GSI_CH_k_CNTXT_0_OFFS(chan_hdl, gsi_ctx->per.ee)); ctx->state = (val & GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_BMSK) >> GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_SHFT; if (ctx->state == GSI_CHAN_STATE_STOPPED) { res = GSI_STATUS_SUCCESS; goto free_lock; } GSIDBG("chan_hdl=%lu timed out\n", chan_hdl); res = -GSI_STATUS_TIMED_OUT; goto free_lock; } GSIDBG("GSI Channel Stop, waiting for completion\n"); gsi_channel_state_change_wait(chan_hdl, ctx, GSI_STOP_CMD_TIMEOUT_MS, GSI_CHAN_STATE_STOPPED); if (ctx->state != GSI_CHAN_STATE_STOPPED && ctx->state != GSI_CHAN_STATE_STOP_IN_PROC) { Loading Loading
drivers/platform/msm/gsi/gsi.c +82 −33 Original line number Diff line number Diff line Loading @@ -23,7 +23,9 @@ #include "gsi_emulation.h" #define GSI_CMD_TIMEOUT (5*HZ) #define GSI_STOP_CMD_TIMEOUT_MS 50 #define GSI_START_CMD_TIMEOUT_MS 1000 #define GSI_CMD_POLL_CNT 5 #define GSI_STOP_CMD_TIMEOUT_MS 10 #define GSI_MAX_CH_LOW_WEIGHT 15 #define GSI_RESET_WA_MIN_SLEEP 1000 Loading Loading @@ -112,6 +114,65 @@ static void __gsi_config_gen_irq(int ee, uint32_t mask, uint32_t val) GSI_EE_n_CNTXT_GSI_IRQ_EN_OFFS(ee)); } static void gsi_channel_state_change_wait(unsigned long chan_hdl, struct gsi_chan_ctx *ctx, uint32_t tm, enum gsi_chan_state next_state) { int poll_cnt; int gsi_pending_intr; int res; uint32_t ch; uint32_t val; int ee = gsi_ctx->per.ee; /* * Start polling the GSI channel for * duration = tm * poll_cnt. * We need to do polling of gsi state for improving debugability * of gsi hw state. */ for (poll_cnt = 0; poll_cnt < GSI_CMD_POLL_CNT; poll_cnt++) { res = wait_for_completion_timeout(&ctx->compl, msecs_to_jiffies(tm)); /* Interrupt received, return */ if (res != 0) return; /* * Check channel state here in case the channel is * already started but interrupt is not yet received. */ val = gsi_readl(gsi_ctx->base + GSI_EE_n_GSI_CH_k_CNTXT_0_OFFS(chan_hdl, gsi_ctx->per.ee)); ctx->state = (val & GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_BMSK) >> GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_SHFT; ch = gsi_readl(gsi_ctx->base + GSI_EE_n_CNTXT_TYPE_IRQ_OFFS(gsi_ctx->per.ee)); gsi_pending_intr = gsi_readl(gsi_ctx->base + GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_OFFS(ee)); GSIDBG("GSI wait on chan_hld=%lu chan=%lu state=%u intr=%u\n", chan_hdl, ch, ctx->state, gsi_pending_intr); if (ctx->state == next_state) break; } } static void gsi_handle_ch_ctrl(int ee) { uint32_t ch; Loading Loading @@ -2317,7 +2378,6 @@ EXPORT_SYMBOL(gsi_query_channel_db_addr); int gsi_start_channel(unsigned long chan_hdl) { enum gsi_ch_cmd_opcode op = GSI_CH_START; int res; uint32_t val; struct gsi_chan_ctx *ctx; Loading Loading @@ -2350,21 +2410,25 @@ int gsi_start_channel(unsigned long chan_hdl) GSI_EE_n_GSI_CH_CMD_OPCODE_BMSK)); gsi_writel(val, gsi_ctx->base + GSI_EE_n_GSI_CH_CMD_OFFS(gsi_ctx->per.ee)); res = wait_for_completion_timeout(&ctx->compl, GSI_CMD_TIMEOUT); if (res == 0) { GSIERR("chan_hdl=%lu timed out\n", chan_hdl); mutex_unlock(&gsi_ctx->mlock); return -GSI_STATUS_TIMED_OUT; } GSIDBG("GSI Channel Start, waiting for completion\n"); gsi_channel_state_change_wait(chan_hdl, ctx, GSI_START_CMD_TIMEOUT_MS, GSI_CHAN_STATE_STARTED); if (ctx->state != GSI_CHAN_STATE_STARTED) { GSIERR("chan=%lu unexpected state=%u\n", chan_hdl, ctx->state); /* * Hardware returned unexpected status, unexpected * hardware state. */ GSIERR("chan=%lu timed out, unexpected state=%u\n", chan_hdl, ctx->state); BUG(); } GSIDBG("GSI Channel=%lu Start success\n", chan_hdl); /* write order MUST be MSB followed by LSB */ val = ((ctx->ring.wp_local >> 32) & GSI_EE_n_GSI_CH_k_DOORBELL_1_WRITE_PTR_MSB_BMSK) << Loading Loading @@ -2420,27 +2484,12 @@ int gsi_stop_channel(unsigned long chan_hdl) GSI_EE_n_GSI_CH_CMD_OPCODE_BMSK)); gsi_writel(val, gsi_ctx->base + GSI_EE_n_GSI_CH_CMD_OFFS(gsi_ctx->per.ee)); res = wait_for_completion_timeout(&ctx->compl, msecs_to_jiffies(GSI_STOP_CMD_TIMEOUT_MS)); if (res == 0) { /* * check channel state here in case the channel is stopped but * the interrupt was not handled yet. */ val = gsi_readl(gsi_ctx->base + GSI_EE_n_GSI_CH_k_CNTXT_0_OFFS(chan_hdl, gsi_ctx->per.ee)); ctx->state = (val & GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_BMSK) >> GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_SHFT; if (ctx->state == GSI_CHAN_STATE_STOPPED) { res = GSI_STATUS_SUCCESS; goto free_lock; } GSIDBG("chan_hdl=%lu timed out\n", chan_hdl); res = -GSI_STATUS_TIMED_OUT; goto free_lock; } GSIDBG("GSI Channel Stop, waiting for completion\n"); gsi_channel_state_change_wait(chan_hdl, ctx, GSI_STOP_CMD_TIMEOUT_MS, GSI_CHAN_STATE_STOPPED); if (ctx->state != GSI_CHAN_STATE_STOPPED && ctx->state != GSI_CHAN_STATE_STOP_IN_PROC) { Loading