Loading drivers/platform/msm/gsi/gsi.c +18 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #define GSI_CMD_POLL_CNT 5 #define GSI_STOP_CMD_TIMEOUT_MS 200 #define GSI_MAX_CH_LOW_WEIGHT 15 #define GSI_IRQ_STORM_THR 5 #define GSI_STOP_CMD_POLL_CNT 4 #define GSI_STOP_IN_PROC_CMD_POLL_CNT 2 Loading Loading @@ -754,6 +755,8 @@ static void gsi_handle_irq(void) unsigned long cnt = 0; while (1) { if (!gsi_ctx->per.clk_status_cb()) break; type = gsi_readl(gsi_ctx->base + GSI_EE_n_CNTXT_TYPE_IRQ_OFFS(ee)); Loading Loading @@ -806,8 +809,14 @@ static irqreturn_t gsi_isr(int irq, void *ctxt) gsi_ctx->per.rel_clk_cb(gsi_ctx->per.user_data); } } else if (!gsi_ctx->per.clk_status_cb()) { /* we only want to capture the gsi isr storm here */ if (atomic_read(&gsi_ctx->num_unclock_irq) == GSI_IRQ_STORM_THR) gsi_ctx->per.enable_clk_bug_on(); atomic_inc(&gsi_ctx->num_unclock_irq); return IRQ_HANDLED; } else { atomic_set(&gsi_ctx->num_unclock_irq, 0); gsi_handle_irq(); } return IRQ_HANDLED; Loading Loading @@ -2775,6 +2784,15 @@ int gsi_query_channel_db_addr(unsigned long chan_hdl, } EXPORT_SYMBOL(gsi_query_channel_db_addr); int gsi_pending_irq_type(void) { int ee = gsi_ctx->per.ee; return gsi_readl(gsi_ctx->base + GSI_EE_n_CNTXT_TYPE_IRQ_OFFS(ee)); } EXPORT_SYMBOL(gsi_pending_irq_type); int gsi_start_channel(unsigned long chan_hdl) { enum gsi_ch_cmd_opcode op = GSI_CH_START; Loading drivers/platform/msm/gsi/gsi.h +2 −0 Original line number Diff line number Diff line Loading @@ -237,6 +237,8 @@ struct gsi_ctx { u32 intcntrlr_mem_size; irq_handler_t intcntrlr_gsi_isr; irq_handler_t intcntrlr_client_isr; atomic_t num_unclock_irq; }; enum gsi_re_type { Loading drivers/platform/msm/ipa/ipa_v3/ipa.c +37 −1 Original line number Diff line number Diff line Loading @@ -124,6 +124,10 @@ static void ipa_dec_clients_disable_clks_on_wq(struct work_struct *work); static DECLARE_DELAYED_WORK(ipa_dec_clients_disable_clks_on_wq_work, ipa_dec_clients_disable_clks_on_wq); static void ipa_inc_clients_enable_clks_on_wq(struct work_struct *work); static DECLARE_WORK(ipa_inc_clients_enable_clks_on_wq_work, ipa_inc_clients_enable_clks_on_wq); static int ipa3_ioctl_add_rt_rule_v2(unsigned long arg); static int ipa3_ioctl_add_rt_rule_ext_v2(unsigned long arg); static int ipa3_ioctl_add_rt_rule_after_v2(unsigned long arg); Loading Loading @@ -4827,6 +4831,8 @@ void _ipa_disable_clks_v3_0(void) */ void ipa3_disable_clks(void) { int type; if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL) { IPAERR("not supported in this mode\n"); return; Loading @@ -4834,13 +4840,29 @@ void ipa3_disable_clks(void) IPADBG("disabling IPA clocks and bus voting\n"); /* * We see a NoC error on GSI on this flag sequence. * Need to set this flag first before clock off. */ atomic_set(&ipa3_ctx->ipa_clk_vote, 0); /* * If there is still pending gsi irq, this indicate * issue on GSI FW side. We need to capture before * turn off the ipa clock. */ type = gsi_pending_irq_type(); if (type) { IPAERR("unexpected gsi irq type: %d\n", type); ipa_assert(); } ipa3_ctx->ctrl->ipa3_disable_clks(); ipa_pm_set_clock_index(0); if (msm_bus_scale_client_update_request(ipa3_ctx->ipa_bus_hdl, 0)) WARN(1, "bus scaling failed"); atomic_set(&ipa3_ctx->ipa_clk_vote, 0); } /** Loading Loading @@ -5013,6 +5035,12 @@ void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id) mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); } void ipa3_handle_gsi_differ_irq(void) { queue_work(ipa3_ctx->power_mgmt_wq, &ipa_inc_clients_enable_clks_on_wq_work); } /** * ipa3_active_clks_status() - update the current msm bus clock vote * status Loading Loading @@ -5129,6 +5157,13 @@ static void ipa_dec_clients_disable_clks_on_wq(struct work_struct *work) __ipa3_dec_client_disable_clks(); } static void ipa_inc_clients_enable_clks_on_wq(struct work_struct *work) { ipa3_enable_clks(); IPAERR("unexpected clk access, clock on IPA to save reg"); ipa_assert(); } /** * ipa3_dec_client_disable_clks_no_block() - Decrease active clients counter * if possible without blocking. If this is the last client then the desrease Loading Loading @@ -5924,6 +5959,7 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p, gsi_props.req_clk_cb = NULL; gsi_props.rel_clk_cb = NULL; gsi_props.clk_status_cb = ipa3_active_clks_status; gsi_props.enable_clk_bug_on = ipa3_handle_gsi_differ_irq; if (ipa3_ctx->ipa_config_is_mhi) { gsi_props.mhi_er_id_limits_valid = true; Loading include/linux/msm_gsi.h +16 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ enum gsi_intr_type { * @rel_clk_cb: callback to release peripheral clock * @user_data: cookie used for notifications * @clk_status_cb: callback to update the current msm bus clock vote * @enable_clk_bug_on: enable IPA clock for dump saving before assert * @skip_ieob_mask_wa: flag for skipping ieob_mask_wa * All the callbacks are in interrupt context * Loading @@ -120,6 +121,7 @@ struct gsi_per_props { int (*rel_clk_cb)(void *user_data); void *user_data; int (*clk_status_cb)(void); void (*enable_clk_bug_on)(void); bool skip_ieob_mask_wa; }; Loading Loading @@ -1314,6 +1316,16 @@ int gsi_write_channel_scratch2_reg(unsigned long chan_hdl, int gsi_read_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch *val); /** * gsi_pending_irq_type - Peripheral should call this function to * check if there is any pending irq * * This function can sleep * * @Return gsi_irq_type */ int gsi_pending_irq_type(void); /** * gsi_update_mhi_channel_scratch - MHI Peripheral should call this * function to update the scratch area of the channel context. Updating Loading Loading @@ -1788,6 +1800,10 @@ static inline int gsi_read_channel_scratch(unsigned long chan_hdl, return -GSI_STATUS_UNSUPPORTED_OP; } static inline int gsi_pending_irq_type(void) { } static inline int gsi_update_mhi_channel_scratch(unsigned long chan_hdl, struct __packed gsi_mhi_channel_scratch mscr) { Loading Loading
drivers/platform/msm/gsi/gsi.c +18 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #define GSI_CMD_POLL_CNT 5 #define GSI_STOP_CMD_TIMEOUT_MS 200 #define GSI_MAX_CH_LOW_WEIGHT 15 #define GSI_IRQ_STORM_THR 5 #define GSI_STOP_CMD_POLL_CNT 4 #define GSI_STOP_IN_PROC_CMD_POLL_CNT 2 Loading Loading @@ -754,6 +755,8 @@ static void gsi_handle_irq(void) unsigned long cnt = 0; while (1) { if (!gsi_ctx->per.clk_status_cb()) break; type = gsi_readl(gsi_ctx->base + GSI_EE_n_CNTXT_TYPE_IRQ_OFFS(ee)); Loading Loading @@ -806,8 +809,14 @@ static irqreturn_t gsi_isr(int irq, void *ctxt) gsi_ctx->per.rel_clk_cb(gsi_ctx->per.user_data); } } else if (!gsi_ctx->per.clk_status_cb()) { /* we only want to capture the gsi isr storm here */ if (atomic_read(&gsi_ctx->num_unclock_irq) == GSI_IRQ_STORM_THR) gsi_ctx->per.enable_clk_bug_on(); atomic_inc(&gsi_ctx->num_unclock_irq); return IRQ_HANDLED; } else { atomic_set(&gsi_ctx->num_unclock_irq, 0); gsi_handle_irq(); } return IRQ_HANDLED; Loading Loading @@ -2775,6 +2784,15 @@ int gsi_query_channel_db_addr(unsigned long chan_hdl, } EXPORT_SYMBOL(gsi_query_channel_db_addr); int gsi_pending_irq_type(void) { int ee = gsi_ctx->per.ee; return gsi_readl(gsi_ctx->base + GSI_EE_n_CNTXT_TYPE_IRQ_OFFS(ee)); } EXPORT_SYMBOL(gsi_pending_irq_type); int gsi_start_channel(unsigned long chan_hdl) { enum gsi_ch_cmd_opcode op = GSI_CH_START; Loading
drivers/platform/msm/gsi/gsi.h +2 −0 Original line number Diff line number Diff line Loading @@ -237,6 +237,8 @@ struct gsi_ctx { u32 intcntrlr_mem_size; irq_handler_t intcntrlr_gsi_isr; irq_handler_t intcntrlr_client_isr; atomic_t num_unclock_irq; }; enum gsi_re_type { Loading
drivers/platform/msm/ipa/ipa_v3/ipa.c +37 −1 Original line number Diff line number Diff line Loading @@ -124,6 +124,10 @@ static void ipa_dec_clients_disable_clks_on_wq(struct work_struct *work); static DECLARE_DELAYED_WORK(ipa_dec_clients_disable_clks_on_wq_work, ipa_dec_clients_disable_clks_on_wq); static void ipa_inc_clients_enable_clks_on_wq(struct work_struct *work); static DECLARE_WORK(ipa_inc_clients_enable_clks_on_wq_work, ipa_inc_clients_enable_clks_on_wq); static int ipa3_ioctl_add_rt_rule_v2(unsigned long arg); static int ipa3_ioctl_add_rt_rule_ext_v2(unsigned long arg); static int ipa3_ioctl_add_rt_rule_after_v2(unsigned long arg); Loading Loading @@ -4827,6 +4831,8 @@ void _ipa_disable_clks_v3_0(void) */ void ipa3_disable_clks(void) { int type; if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL) { IPAERR("not supported in this mode\n"); return; Loading @@ -4834,13 +4840,29 @@ void ipa3_disable_clks(void) IPADBG("disabling IPA clocks and bus voting\n"); /* * We see a NoC error on GSI on this flag sequence. * Need to set this flag first before clock off. */ atomic_set(&ipa3_ctx->ipa_clk_vote, 0); /* * If there is still pending gsi irq, this indicate * issue on GSI FW side. We need to capture before * turn off the ipa clock. */ type = gsi_pending_irq_type(); if (type) { IPAERR("unexpected gsi irq type: %d\n", type); ipa_assert(); } ipa3_ctx->ctrl->ipa3_disable_clks(); ipa_pm_set_clock_index(0); if (msm_bus_scale_client_update_request(ipa3_ctx->ipa_bus_hdl, 0)) WARN(1, "bus scaling failed"); atomic_set(&ipa3_ctx->ipa_clk_vote, 0); } /** Loading Loading @@ -5013,6 +5035,12 @@ void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id) mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); } void ipa3_handle_gsi_differ_irq(void) { queue_work(ipa3_ctx->power_mgmt_wq, &ipa_inc_clients_enable_clks_on_wq_work); } /** * ipa3_active_clks_status() - update the current msm bus clock vote * status Loading Loading @@ -5129,6 +5157,13 @@ static void ipa_dec_clients_disable_clks_on_wq(struct work_struct *work) __ipa3_dec_client_disable_clks(); } static void ipa_inc_clients_enable_clks_on_wq(struct work_struct *work) { ipa3_enable_clks(); IPAERR("unexpected clk access, clock on IPA to save reg"); ipa_assert(); } /** * ipa3_dec_client_disable_clks_no_block() - Decrease active clients counter * if possible without blocking. If this is the last client then the desrease Loading Loading @@ -5924,6 +5959,7 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p, gsi_props.req_clk_cb = NULL; gsi_props.rel_clk_cb = NULL; gsi_props.clk_status_cb = ipa3_active_clks_status; gsi_props.enable_clk_bug_on = ipa3_handle_gsi_differ_irq; if (ipa3_ctx->ipa_config_is_mhi) { gsi_props.mhi_er_id_limits_valid = true; Loading
include/linux/msm_gsi.h +16 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ enum gsi_intr_type { * @rel_clk_cb: callback to release peripheral clock * @user_data: cookie used for notifications * @clk_status_cb: callback to update the current msm bus clock vote * @enable_clk_bug_on: enable IPA clock for dump saving before assert * @skip_ieob_mask_wa: flag for skipping ieob_mask_wa * All the callbacks are in interrupt context * Loading @@ -120,6 +121,7 @@ struct gsi_per_props { int (*rel_clk_cb)(void *user_data); void *user_data; int (*clk_status_cb)(void); void (*enable_clk_bug_on)(void); bool skip_ieob_mask_wa; }; Loading Loading @@ -1314,6 +1316,16 @@ int gsi_write_channel_scratch2_reg(unsigned long chan_hdl, int gsi_read_channel_scratch(unsigned long chan_hdl, union __packed gsi_channel_scratch *val); /** * gsi_pending_irq_type - Peripheral should call this function to * check if there is any pending irq * * This function can sleep * * @Return gsi_irq_type */ int gsi_pending_irq_type(void); /** * gsi_update_mhi_channel_scratch - MHI Peripheral should call this * function to update the scratch area of the channel context. Updating Loading Loading @@ -1788,6 +1800,10 @@ static inline int gsi_read_channel_scratch(unsigned long chan_hdl, return -GSI_STATUS_UNSUPPORTED_OP; } static inline int gsi_pending_irq_type(void) { } static inline int gsi_update_mhi_channel_scratch(unsigned long chan_hdl, struct __packed gsi_mhi_channel_scratch mscr) { Loading