Loading arch/arm/mm/init.c +0 −1 Original line number Diff line number Diff line Loading @@ -623,7 +623,6 @@ void __init mem_init(void) #undef MLM #undef MLK_ROUNDUP #ifdef CONFIG_ARM_KERNMEM_PERMS struct section_perm { const char *name; unsigned long start; Loading drivers/platform/msm/ipa/ipa_v3/ipa.c +118 −66 Original line number Diff line number Diff line Loading @@ -235,6 +235,10 @@ static void ipa_gsi_notify_cb(struct gsi_per_notify *notify); static void ipa3_post_init_wq(struct work_struct *work); static DECLARE_WORK(ipa3_post_init_work, ipa3_post_init_wq); static void ipa_dec_clients_disable_clks_on_wq(struct work_struct *work); static DECLARE_WORK(ipa_dec_clients_disable_clks_on_wq_work, ipa_dec_clients_disable_clks_on_wq); static struct ipa3_plat_drv_res ipa3_res = {0, }; struct msm_bus_scale_pdata *ipa3_bus_scale_table; Loading Loading @@ -314,7 +318,7 @@ int ipa3_active_clients_log_print_table(char *buf, int size) } cnt += scnprintf(buf + cnt, size - cnt, "\nTotal active clients count: %d\n", ipa3_ctx->ipa3_active_clients.cnt); atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)); return cnt; } Loading @@ -322,11 +326,11 @@ int ipa3_active_clients_log_print_table(char *buf, int size) static int ipa3_active_clients_panic_notifier(struct notifier_block *this, unsigned long event, void *ptr) { ipa3_active_clients_lock(); mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex); ipa3_active_clients_log_print_table(active_clients_table_buf, IPA3_ACTIVE_CLIENTS_TABLE_BUF_SIZE); IPAERR("%s", active_clients_table_buf); ipa3_active_clients_unlock(); mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); return NOTIFY_DONE; } Loading Loading @@ -395,11 +399,11 @@ static int ipa3_active_clients_log_init(void) void ipa3_active_clients_log_clear(void) { ipa3_active_clients_lock(); mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex); ipa3_ctx->ipa3_active_clients_logging.log_head = 0; ipa3_ctx->ipa3_active_clients_logging.log_tail = IPA3_ACTIVE_CLIENTS_LOG_BUFFER_SIZE_LINES - 1; ipa3_active_clients_unlock(); mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); } static void ipa3_active_clients_log_destroy(void) Loading Loading @@ -3267,7 +3271,6 @@ void _ipa_enable_clks_v3_0(void) } ipa3_uc_notify_clk_state(true); ipa3_suspend_apps_pipes(false); } static unsigned int ipa3_get_bus_vote(void) Loading Loading @@ -3466,13 +3469,33 @@ void ipa3_active_clients_log_inc(struct ipa_active_client_logging_info *id, */ void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id) { ipa3_active_clients_lock(); int ret; ipa3_active_clients_log_inc(id, false); ipa3_ctx->ipa3_active_clients.cnt++; if (ipa3_ctx->ipa3_active_clients.cnt == 1) ret = atomic_inc_not_zero(&ipa3_ctx->ipa3_active_clients.cnt); if (ret) { IPADBG_LOW("active clients = %d\n", atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)); return; } mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex); /* somebody might voted to clocks meanwhile */ ret = atomic_inc_not_zero(&ipa3_ctx->ipa3_active_clients.cnt); if (ret) { mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); IPADBG_LOW("active clients = %d\n", atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)); return; } ipa3_enable_clks(); IPADBG_LOW("active clients = %d\n", ipa3_ctx->ipa3_active_clients.cnt); ipa3_active_clients_unlock(); atomic_inc(&ipa3_ctx->ipa3_active_clients.cnt); IPADBG_LOW("active clients = %d\n", atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)); ipa3_suspend_apps_pipes(false); mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); } /** Loading @@ -3486,23 +3509,57 @@ void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id) int ipa3_inc_client_enable_clks_no_block(struct ipa_active_client_logging_info *id) { int res = 0; unsigned long flags; int ret; ret = atomic_inc_not_zero(&ipa3_ctx->ipa3_active_clients.cnt); if (ret) { ipa3_active_clients_log_inc(id, true); IPADBG_LOW("active clients = %d\n", atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)); return 0; } if (ipa3_active_clients_trylock(&flags) == 0) return -EPERM; } static void __ipa3_dec_client_disable_clks(void) { int ret; if (!atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)) { IPAERR("trying to disable clocks with refcnt is 0!\n"); ipa_assert(); return; } if (ipa3_ctx->ipa3_active_clients.cnt == 0) { res = -EPERM; ret = atomic_add_unless(&ipa3_ctx->ipa3_active_clients.cnt, -1, 1); if (ret) goto bail; /* seems like this is the only client holding the clocks */ mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex); if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt) == 1 && ipa3_ctx->tag_process_before_gating) { ipa3_ctx->tag_process_before_gating = false; /* * When TAG process ends, active clients will be * decreased */ queue_work(ipa3_ctx->power_mgmt_wq, &ipa3_tag_work); goto unlock_mutex; } ipa3_active_clients_log_inc(id, true); ipa3_ctx->ipa3_active_clients.cnt++; IPADBG_LOW("active clients = %d\n", ipa3_ctx->ipa3_active_clients.cnt); bail: ipa3_active_clients_trylock_unlock(&flags); return res; /* a different context might increase the clock reference meanwhile */ ret = atomic_sub_return(1, &ipa3_ctx->ipa3_active_clients.cnt); if (ret > 0) goto unlock_mutex; ipa3_disable_clks(); unlock_mutex: mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); bail: IPADBG_LOW("active clients = %d\n", atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)); } /** Loading @@ -3518,29 +3575,39 @@ int ipa3_inc_client_enable_clks_no_block(struct ipa_active_client_logging_info */ void ipa3_dec_client_disable_clks(struct ipa_active_client_logging_info *id) { struct ipa_active_client_logging_info log_info; ipa3_active_clients_lock(); ipa3_active_clients_log_dec(id, false); ipa3_ctx->ipa3_active_clients.cnt--; IPADBG_LOW("active clients = %d\n", ipa3_ctx->ipa3_active_clients.cnt); if (ipa3_ctx->ipa3_active_clients.cnt == 0) { if (ipa3_ctx->tag_process_before_gating) { ipa3_ctx->tag_process_before_gating = false; /* * When TAG process ends, active clients will be * decreased */ IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, "TAG_PROCESS"); ipa3_active_clients_log_inc(&log_info, false); ipa3_ctx->ipa3_active_clients.cnt = 1; queue_work(ipa3_ctx->power_mgmt_wq, &ipa3_tag_work); } else { ipa3_disable_clks(); __ipa3_dec_client_disable_clks(); } static void ipa_dec_clients_disable_clks_on_wq(struct work_struct *work) { __ipa3_dec_client_disable_clks(); } ipa3_active_clients_unlock(); /** * ipa3_dec_client_disable_clks_no_block() - Decrease active clients counter * if possible without blocking. If this is the last client then the desrease * will happen from work queue context. * * Return codes: * None */ void ipa3_dec_client_disable_clks_no_block( struct ipa_active_client_logging_info *id) { int ret; ipa3_active_clients_log_dec(id, true); ret = atomic_add_unless(&ipa3_ctx->ipa3_active_clients.cnt, -1, 1); if (ret) { IPADBG_LOW("active clients = %d\n", atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)); return; } /* seems like this is the only client holding the clocks */ queue_work(ipa3_ctx->power_mgmt_wq, &ipa_dec_clients_disable_clks_on_wq_work); } /** Loading Loading @@ -3636,34 +3703,20 @@ int ipa3_set_required_perf_profile(enum ipa_voltage_level floor_voltage, return 0; } ipa3_active_clients_lock(); /* Hold the mutex to avoid race conditions with ipa3_enable_clocks() */ mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex); ipa3_ctx->curr_ipa_clk_rate = clk_rate; IPADBG_LOW("setting clock rate to %u\n", ipa3_ctx->curr_ipa_clk_rate); if (ipa3_ctx->ipa3_active_clients.cnt > 0) { struct ipa_active_client_logging_info log_info; /* * clk_set_rate should be called with unlocked lock to allow * clients to get a reference to IPA clock synchronously. * Hold a reference to IPA clock here to make sure clock * state does not change during set_rate. */ IPA_ACTIVE_CLIENTS_PREP_SIMPLE(log_info); ipa3_ctx->ipa3_active_clients.cnt++; ipa3_active_clients_log_inc(&log_info, false); ipa3_active_clients_unlock(); if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt) > 0) { if (ipa3_clk) clk_set_rate(ipa3_clk, ipa3_ctx->curr_ipa_clk_rate); if (msm_bus_scale_client_update_request(ipa3_ctx->ipa_bus_hdl, ipa3_get_bus_vote())) WARN_ON(1); /* remove the vote added here */ IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); } else { IPADBG_LOW("clocks are gated, not setting rate\n"); ipa3_active_clients_unlock(); } mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); IPADBG_LOW("Done\n"); return 0; Loading Loading @@ -4625,10 +4678,9 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, } mutex_init(&ipa3_ctx->ipa3_active_clients.mutex); spin_lock_init(&ipa3_ctx->ipa3_active_clients.spinlock); IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, "PROXY_CLK_VOTE"); ipa3_active_clients_log_inc(&log_info, false); ipa3_ctx->ipa3_active_clients.cnt = 1; atomic_set(&ipa3_ctx->ipa3_active_clients.cnt, 1); /* Create workqueues for power management */ ipa3_ctx->power_mgmt_wq = Loading drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +6 −6 Original line number Diff line number Diff line Loading @@ -363,14 +363,14 @@ static ssize_t ipa3_read_keep_awake(struct file *file, char __user *ubuf, { int nbytes; ipa3_active_clients_lock(); if (ipa3_ctx->ipa3_active_clients.cnt) mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex); if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)) nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN, "IPA APPS power state is ON\n"); else nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN, "IPA APPS power state is OFF\n"); ipa3_active_clients_unlock(); mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes); } Loading Loading @@ -1064,7 +1064,7 @@ static ssize_t ipa3_read_stats(struct file *file, char __user *ubuf, ipa3_ctx->stats.stat_compl, ipa3_ctx->stats.aggr_close, ipa3_ctx->stats.wan_aggr_close, ipa3_ctx->ipa3_active_clients.cnt, atomic_read(&ipa3_ctx->ipa3_active_clients.cnt), connect, ipa3_ctx->stats.wan_rx_empty, ipa3_ctx->stats.wan_repl_rx_empty, Loading Loading @@ -1785,12 +1785,12 @@ static ssize_t ipa3_print_active_clients_log(struct file *file, return 0; } memset(active_clients_buf, 0, IPA_DBG_ACTIVE_CLIENT_BUF_SIZE); ipa3_active_clients_lock(); mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex); cnt = ipa3_active_clients_log_print_buffer(active_clients_buf, IPA_DBG_ACTIVE_CLIENT_BUF_SIZE - IPA_MAX_MSG_LEN); table_size = ipa3_active_clients_log_print_table(active_clients_buf + cnt, IPA_MAX_MSG_LEN); ipa3_active_clients_unlock(); mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); return simple_read_from_buffer(ubuf, count, ppos, active_clients_buf, cnt + table_size); Loading drivers/platform/msm/ipa/ipa_v3/ipa_i.h +3 −6 Original line number Diff line number Diff line Loading @@ -850,9 +850,7 @@ struct ipa3_stats { struct ipa3_active_clients { struct mutex mutex; spinlock_t spinlock; bool mutex_locked; int cnt; atomic_t cnt; }; struct ipa3_wakelock_ref_cnt { Loading Loading @@ -1851,6 +1849,8 @@ void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id); int ipa3_inc_client_enable_clks_no_block(struct ipa_active_client_logging_info *id); void ipa3_dec_client_disable_clks(struct ipa_active_client_logging_info *id); void ipa3_dec_client_disable_clks_no_block( struct ipa_active_client_logging_info *id); void ipa3_active_clients_log_dec(struct ipa_active_client_logging_info *id, bool int_ctx); void ipa3_active_clients_log_inc(struct ipa_active_client_logging_info *id, Loading Loading @@ -1927,10 +1927,7 @@ int ipa3_resume_resource(enum ipa_rm_resource_name name); bool ipa3_should_pipe_be_suspended(enum ipa_client_type client); int ipa3_tag_aggr_force_close(int pipe_num); void ipa3_active_clients_lock(void); int ipa3_active_clients_trylock(unsigned long *flags); void ipa3_active_clients_unlock(void); void ipa3_active_clients_trylock_unlock(unsigned long *flags); int ipa3_wdi_init(void); int ipa3_write_qmapid_wdi_pipe(u32 clnt_hdl, u8 qmap_id); int ipa3_tag_process(struct ipa3_desc *desc, int num_descs, Loading drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c +4 −10 Original line number Diff line number Diff line Loading @@ -322,27 +322,21 @@ static void ipa3_interrupt_defer(struct work_struct *work) static irqreturn_t ipa3_isr(int irq, void *ctxt) { unsigned long flags; struct ipa_active_client_logging_info log_info; IPA_ACTIVE_CLIENTS_PREP_SIMPLE(log_info); IPADBG_LOW("Enter\n"); /* defer interrupt handling in case IPA is not clocked on */ if (ipa3_active_clients_trylock(&flags) == 0) { if (ipa3_inc_client_enable_clks_no_block(&log_info)) { IPADBG("defer interrupt processing\n"); queue_work(ipa3_ctx->power_mgmt_wq, &ipa3_interrupt_defer_work); return IRQ_HANDLED; } if (ipa3_ctx->ipa3_active_clients.cnt == 0) { IPADBG("defer interrupt processing\n"); queue_work(ipa3_ctx->power_mgmt_wq, &ipa3_interrupt_defer_work); goto bail; } ipa3_process_interrupts(true); IPADBG_LOW("Exit\n"); bail: ipa3_active_clients_trylock_unlock(&flags); ipa3_dec_client_disable_clks(&log_info); return IRQ_HANDLED; } /** Loading Loading
arch/arm/mm/init.c +0 −1 Original line number Diff line number Diff line Loading @@ -623,7 +623,6 @@ void __init mem_init(void) #undef MLM #undef MLK_ROUNDUP #ifdef CONFIG_ARM_KERNMEM_PERMS struct section_perm { const char *name; unsigned long start; Loading
drivers/platform/msm/ipa/ipa_v3/ipa.c +118 −66 Original line number Diff line number Diff line Loading @@ -235,6 +235,10 @@ static void ipa_gsi_notify_cb(struct gsi_per_notify *notify); static void ipa3_post_init_wq(struct work_struct *work); static DECLARE_WORK(ipa3_post_init_work, ipa3_post_init_wq); static void ipa_dec_clients_disable_clks_on_wq(struct work_struct *work); static DECLARE_WORK(ipa_dec_clients_disable_clks_on_wq_work, ipa_dec_clients_disable_clks_on_wq); static struct ipa3_plat_drv_res ipa3_res = {0, }; struct msm_bus_scale_pdata *ipa3_bus_scale_table; Loading Loading @@ -314,7 +318,7 @@ int ipa3_active_clients_log_print_table(char *buf, int size) } cnt += scnprintf(buf + cnt, size - cnt, "\nTotal active clients count: %d\n", ipa3_ctx->ipa3_active_clients.cnt); atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)); return cnt; } Loading @@ -322,11 +326,11 @@ int ipa3_active_clients_log_print_table(char *buf, int size) static int ipa3_active_clients_panic_notifier(struct notifier_block *this, unsigned long event, void *ptr) { ipa3_active_clients_lock(); mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex); ipa3_active_clients_log_print_table(active_clients_table_buf, IPA3_ACTIVE_CLIENTS_TABLE_BUF_SIZE); IPAERR("%s", active_clients_table_buf); ipa3_active_clients_unlock(); mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); return NOTIFY_DONE; } Loading Loading @@ -395,11 +399,11 @@ static int ipa3_active_clients_log_init(void) void ipa3_active_clients_log_clear(void) { ipa3_active_clients_lock(); mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex); ipa3_ctx->ipa3_active_clients_logging.log_head = 0; ipa3_ctx->ipa3_active_clients_logging.log_tail = IPA3_ACTIVE_CLIENTS_LOG_BUFFER_SIZE_LINES - 1; ipa3_active_clients_unlock(); mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); } static void ipa3_active_clients_log_destroy(void) Loading Loading @@ -3267,7 +3271,6 @@ void _ipa_enable_clks_v3_0(void) } ipa3_uc_notify_clk_state(true); ipa3_suspend_apps_pipes(false); } static unsigned int ipa3_get_bus_vote(void) Loading Loading @@ -3466,13 +3469,33 @@ void ipa3_active_clients_log_inc(struct ipa_active_client_logging_info *id, */ void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id) { ipa3_active_clients_lock(); int ret; ipa3_active_clients_log_inc(id, false); ipa3_ctx->ipa3_active_clients.cnt++; if (ipa3_ctx->ipa3_active_clients.cnt == 1) ret = atomic_inc_not_zero(&ipa3_ctx->ipa3_active_clients.cnt); if (ret) { IPADBG_LOW("active clients = %d\n", atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)); return; } mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex); /* somebody might voted to clocks meanwhile */ ret = atomic_inc_not_zero(&ipa3_ctx->ipa3_active_clients.cnt); if (ret) { mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); IPADBG_LOW("active clients = %d\n", atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)); return; } ipa3_enable_clks(); IPADBG_LOW("active clients = %d\n", ipa3_ctx->ipa3_active_clients.cnt); ipa3_active_clients_unlock(); atomic_inc(&ipa3_ctx->ipa3_active_clients.cnt); IPADBG_LOW("active clients = %d\n", atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)); ipa3_suspend_apps_pipes(false); mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); } /** Loading @@ -3486,23 +3509,57 @@ void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id) int ipa3_inc_client_enable_clks_no_block(struct ipa_active_client_logging_info *id) { int res = 0; unsigned long flags; int ret; ret = atomic_inc_not_zero(&ipa3_ctx->ipa3_active_clients.cnt); if (ret) { ipa3_active_clients_log_inc(id, true); IPADBG_LOW("active clients = %d\n", atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)); return 0; } if (ipa3_active_clients_trylock(&flags) == 0) return -EPERM; } static void __ipa3_dec_client_disable_clks(void) { int ret; if (!atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)) { IPAERR("trying to disable clocks with refcnt is 0!\n"); ipa_assert(); return; } if (ipa3_ctx->ipa3_active_clients.cnt == 0) { res = -EPERM; ret = atomic_add_unless(&ipa3_ctx->ipa3_active_clients.cnt, -1, 1); if (ret) goto bail; /* seems like this is the only client holding the clocks */ mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex); if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt) == 1 && ipa3_ctx->tag_process_before_gating) { ipa3_ctx->tag_process_before_gating = false; /* * When TAG process ends, active clients will be * decreased */ queue_work(ipa3_ctx->power_mgmt_wq, &ipa3_tag_work); goto unlock_mutex; } ipa3_active_clients_log_inc(id, true); ipa3_ctx->ipa3_active_clients.cnt++; IPADBG_LOW("active clients = %d\n", ipa3_ctx->ipa3_active_clients.cnt); bail: ipa3_active_clients_trylock_unlock(&flags); return res; /* a different context might increase the clock reference meanwhile */ ret = atomic_sub_return(1, &ipa3_ctx->ipa3_active_clients.cnt); if (ret > 0) goto unlock_mutex; ipa3_disable_clks(); unlock_mutex: mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); bail: IPADBG_LOW("active clients = %d\n", atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)); } /** Loading @@ -3518,29 +3575,39 @@ int ipa3_inc_client_enable_clks_no_block(struct ipa_active_client_logging_info */ void ipa3_dec_client_disable_clks(struct ipa_active_client_logging_info *id) { struct ipa_active_client_logging_info log_info; ipa3_active_clients_lock(); ipa3_active_clients_log_dec(id, false); ipa3_ctx->ipa3_active_clients.cnt--; IPADBG_LOW("active clients = %d\n", ipa3_ctx->ipa3_active_clients.cnt); if (ipa3_ctx->ipa3_active_clients.cnt == 0) { if (ipa3_ctx->tag_process_before_gating) { ipa3_ctx->tag_process_before_gating = false; /* * When TAG process ends, active clients will be * decreased */ IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, "TAG_PROCESS"); ipa3_active_clients_log_inc(&log_info, false); ipa3_ctx->ipa3_active_clients.cnt = 1; queue_work(ipa3_ctx->power_mgmt_wq, &ipa3_tag_work); } else { ipa3_disable_clks(); __ipa3_dec_client_disable_clks(); } static void ipa_dec_clients_disable_clks_on_wq(struct work_struct *work) { __ipa3_dec_client_disable_clks(); } ipa3_active_clients_unlock(); /** * ipa3_dec_client_disable_clks_no_block() - Decrease active clients counter * if possible without blocking. If this is the last client then the desrease * will happen from work queue context. * * Return codes: * None */ void ipa3_dec_client_disable_clks_no_block( struct ipa_active_client_logging_info *id) { int ret; ipa3_active_clients_log_dec(id, true); ret = atomic_add_unless(&ipa3_ctx->ipa3_active_clients.cnt, -1, 1); if (ret) { IPADBG_LOW("active clients = %d\n", atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)); return; } /* seems like this is the only client holding the clocks */ queue_work(ipa3_ctx->power_mgmt_wq, &ipa_dec_clients_disable_clks_on_wq_work); } /** Loading Loading @@ -3636,34 +3703,20 @@ int ipa3_set_required_perf_profile(enum ipa_voltage_level floor_voltage, return 0; } ipa3_active_clients_lock(); /* Hold the mutex to avoid race conditions with ipa3_enable_clocks() */ mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex); ipa3_ctx->curr_ipa_clk_rate = clk_rate; IPADBG_LOW("setting clock rate to %u\n", ipa3_ctx->curr_ipa_clk_rate); if (ipa3_ctx->ipa3_active_clients.cnt > 0) { struct ipa_active_client_logging_info log_info; /* * clk_set_rate should be called with unlocked lock to allow * clients to get a reference to IPA clock synchronously. * Hold a reference to IPA clock here to make sure clock * state does not change during set_rate. */ IPA_ACTIVE_CLIENTS_PREP_SIMPLE(log_info); ipa3_ctx->ipa3_active_clients.cnt++; ipa3_active_clients_log_inc(&log_info, false); ipa3_active_clients_unlock(); if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt) > 0) { if (ipa3_clk) clk_set_rate(ipa3_clk, ipa3_ctx->curr_ipa_clk_rate); if (msm_bus_scale_client_update_request(ipa3_ctx->ipa_bus_hdl, ipa3_get_bus_vote())) WARN_ON(1); /* remove the vote added here */ IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); } else { IPADBG_LOW("clocks are gated, not setting rate\n"); ipa3_active_clients_unlock(); } mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); IPADBG_LOW("Done\n"); return 0; Loading Loading @@ -4625,10 +4678,9 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, } mutex_init(&ipa3_ctx->ipa3_active_clients.mutex); spin_lock_init(&ipa3_ctx->ipa3_active_clients.spinlock); IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, "PROXY_CLK_VOTE"); ipa3_active_clients_log_inc(&log_info, false); ipa3_ctx->ipa3_active_clients.cnt = 1; atomic_set(&ipa3_ctx->ipa3_active_clients.cnt, 1); /* Create workqueues for power management */ ipa3_ctx->power_mgmt_wq = Loading
drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +6 −6 Original line number Diff line number Diff line Loading @@ -363,14 +363,14 @@ static ssize_t ipa3_read_keep_awake(struct file *file, char __user *ubuf, { int nbytes; ipa3_active_clients_lock(); if (ipa3_ctx->ipa3_active_clients.cnt) mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex); if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt)) nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN, "IPA APPS power state is ON\n"); else nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN, "IPA APPS power state is OFF\n"); ipa3_active_clients_unlock(); mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes); } Loading Loading @@ -1064,7 +1064,7 @@ static ssize_t ipa3_read_stats(struct file *file, char __user *ubuf, ipa3_ctx->stats.stat_compl, ipa3_ctx->stats.aggr_close, ipa3_ctx->stats.wan_aggr_close, ipa3_ctx->ipa3_active_clients.cnt, atomic_read(&ipa3_ctx->ipa3_active_clients.cnt), connect, ipa3_ctx->stats.wan_rx_empty, ipa3_ctx->stats.wan_repl_rx_empty, Loading Loading @@ -1785,12 +1785,12 @@ static ssize_t ipa3_print_active_clients_log(struct file *file, return 0; } memset(active_clients_buf, 0, IPA_DBG_ACTIVE_CLIENT_BUF_SIZE); ipa3_active_clients_lock(); mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex); cnt = ipa3_active_clients_log_print_buffer(active_clients_buf, IPA_DBG_ACTIVE_CLIENT_BUF_SIZE - IPA_MAX_MSG_LEN); table_size = ipa3_active_clients_log_print_table(active_clients_buf + cnt, IPA_MAX_MSG_LEN); ipa3_active_clients_unlock(); mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); return simple_read_from_buffer(ubuf, count, ppos, active_clients_buf, cnt + table_size); Loading
drivers/platform/msm/ipa/ipa_v3/ipa_i.h +3 −6 Original line number Diff line number Diff line Loading @@ -850,9 +850,7 @@ struct ipa3_stats { struct ipa3_active_clients { struct mutex mutex; spinlock_t spinlock; bool mutex_locked; int cnt; atomic_t cnt; }; struct ipa3_wakelock_ref_cnt { Loading Loading @@ -1851,6 +1849,8 @@ void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id); int ipa3_inc_client_enable_clks_no_block(struct ipa_active_client_logging_info *id); void ipa3_dec_client_disable_clks(struct ipa_active_client_logging_info *id); void ipa3_dec_client_disable_clks_no_block( struct ipa_active_client_logging_info *id); void ipa3_active_clients_log_dec(struct ipa_active_client_logging_info *id, bool int_ctx); void ipa3_active_clients_log_inc(struct ipa_active_client_logging_info *id, Loading Loading @@ -1927,10 +1927,7 @@ int ipa3_resume_resource(enum ipa_rm_resource_name name); bool ipa3_should_pipe_be_suspended(enum ipa_client_type client); int ipa3_tag_aggr_force_close(int pipe_num); void ipa3_active_clients_lock(void); int ipa3_active_clients_trylock(unsigned long *flags); void ipa3_active_clients_unlock(void); void ipa3_active_clients_trylock_unlock(unsigned long *flags); int ipa3_wdi_init(void); int ipa3_write_qmapid_wdi_pipe(u32 clnt_hdl, u8 qmap_id); int ipa3_tag_process(struct ipa3_desc *desc, int num_descs, Loading
drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c +4 −10 Original line number Diff line number Diff line Loading @@ -322,27 +322,21 @@ static void ipa3_interrupt_defer(struct work_struct *work) static irqreturn_t ipa3_isr(int irq, void *ctxt) { unsigned long flags; struct ipa_active_client_logging_info log_info; IPA_ACTIVE_CLIENTS_PREP_SIMPLE(log_info); IPADBG_LOW("Enter\n"); /* defer interrupt handling in case IPA is not clocked on */ if (ipa3_active_clients_trylock(&flags) == 0) { if (ipa3_inc_client_enable_clks_no_block(&log_info)) { IPADBG("defer interrupt processing\n"); queue_work(ipa3_ctx->power_mgmt_wq, &ipa3_interrupt_defer_work); return IRQ_HANDLED; } if (ipa3_ctx->ipa3_active_clients.cnt == 0) { IPADBG("defer interrupt processing\n"); queue_work(ipa3_ctx->power_mgmt_wq, &ipa3_interrupt_defer_work); goto bail; } ipa3_process_interrupts(true); IPADBG_LOW("Exit\n"); bail: ipa3_active_clients_trylock_unlock(&flags); ipa3_dec_client_disable_clks(&log_info); return IRQ_HANDLED; } /** Loading