Loading drivers/platform/msm/ipa/ipa_v2/ipa.c +7 −2 Original line number Diff line number Diff line Loading @@ -2544,6 +2544,8 @@ void _ipa_enable_clks_v2_0(void) if (smmu_clk) clk_prepare_enable(smmu_clk); /* Enable the BAM IRQ. */ ipa_sps_irq_control_all(true); ipa_suspend_apps_pipes(false); } Loading Loading @@ -2667,6 +2669,7 @@ void _ipa_disable_clks_v2_0(void) { IPADBG("disabling gcc_ipa_clk\n"); ipa_suspend_apps_pipes(true); ipa_sps_irq_control_all(false); ipa_uc_notify_clk_state(false); if (ipa_clk) clk_disable_unprepare(ipa_clk); Loading Loading @@ -3023,6 +3026,8 @@ void ipa_suspend_handler(enum ipa_irq_type interrupt, &ipa_ctx->sps_pm.dec_clients) ) { ipa_inc_client_enable_clks(); IPADBG("Pipes un-suspended.\n"); IPADBG("Enter poll mode.\n"); atomic_set( &ipa_ctx->sps_pm.dec_clients, 1); Loading Loading @@ -3575,8 +3580,8 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p, } /*add handler for suspend interrupt*/ result = ipa2_add_interrupt_handler(IPA_TX_SUSPEND_IRQ, ipa_suspend_handler, true, NULL); result = ipa_add_interrupt_handler(IPA_TX_SUSPEND_IRQ, ipa_suspend_handler, false, NULL); if (result) { IPAERR("register handler for suspend interrupt failed\n"); result = -ENODEV; Loading drivers/platform/msm/ipa/ipa_v2/ipa_dp.c +71 −0 Original line number Diff line number Diff line Loading @@ -792,6 +792,77 @@ fail: msecs_to_jiffies(1)); } /** * ipa_sps_irq_control() - Function to enable or disable BAM IRQ. */ static void ipa_sps_irq_control(struct ipa_sys_context *sys, bool enable) { int ret; if (enable) { ret = sps_get_config(sys->ep->ep_hdl, &sys->ep->connect); if (ret) { IPAERR("sps_get_config() failed %d\n", ret); return; } sys->event.options = SPS_O_EOT; ret = sps_register_event(sys->ep->ep_hdl, &sys->event); if (ret) { IPAERR("sps_register_event() failed %d\n", ret); return; } sys->ep->connect.options = SPS_O_AUTO_ENABLE | SPS_O_ACK_TRANSFERS | SPS_O_EOT; ret = sps_set_config(sys->ep->ep_hdl, &sys->ep->connect); if (ret) { IPAERR("sps_set_config() failed %d\n", ret); return; } } else { ret = sps_get_config(sys->ep->ep_hdl, &sys->ep->connect); if (ret) { IPAERR("sps_get_config() failed %d\n", ret); return; } sys->ep->connect.options = SPS_O_AUTO_ENABLE | SPS_O_ACK_TRANSFERS | SPS_O_POLL; ret = sps_set_config(sys->ep->ep_hdl, &sys->ep->connect); if (ret) { IPAERR("sps_set_config() failed %d\n", ret); return; } } } void ipa_sps_irq_control_all(bool enable) { struct ipa_ep_context *ep; int ipa_ep_idx, client_num; IPADBG("\n"); for (client_num = IPA_CLIENT_CONS; client_num < IPA_CLIENT_MAX; client_num++) { if (!IPA_CLIENT_IS_APPS_CONS(client_num)) continue; ipa_ep_idx = ipa_get_ep_mapping(client_num); if (ipa_ep_idx == -1) { IPAERR("Invalid client.\n"); continue; } ep = &ipa_ctx->ep[ipa_ep_idx]; if (!ep->valid) { IPAERR("EP (%d) not allocated.\n", ipa_ep_idx); continue; } ipa_sps_irq_control(ep->sys, enable); } } /** * ipa_rx_notify() - Callback function which is called by the SPS driver when a * a packet is received Loading drivers/platform/msm/ipa/ipa_v2/ipa_i.h +1 −0 Original line number Diff line number Diff line Loading @@ -1987,4 +1987,5 @@ void ipa_update_repl_threshold(enum ipa_client_type ipa_client); void ipa_flow_control(enum ipa_client_type ipa_client, bool enable, uint32_t qmap_id); int ipa2_restore_suspend_handler(void); void ipa_sps_irq_control_all(bool enable); #endif /* _IPA_I_H_ */ drivers/platform/msm/ipa/ipa_v2/ipa_interrupts.c +7 −6 Original line number Diff line number Diff line Loading @@ -85,7 +85,7 @@ static bool is_valid_ep(u32 ep_suspend_data) return false; } static int handle_interrupt(int irq_num) static int handle_interrupt(int irq_num, bool isr_context) { struct ipa_interrupt_info interrupt_info; struct ipa_interrupt_work_wrap *work_data; Loading Loading @@ -121,7 +121,8 @@ static int handle_interrupt(int irq_num) break; } if (interrupt_info.deferred_flag) { /* Force defer processing if in ISR context. */ if (interrupt_info.deferred_flag || isr_context) { work_data = kzalloc(sizeof(struct ipa_interrupt_work_wrap), GFP_ATOMIC); if (!work_data) { Loading Loading @@ -150,7 +151,7 @@ fail_alloc_work: return res; } static void ipa_process_interrupts(void) static void ipa_process_interrupts(bool isr_context) { u32 reg; u32 bmsk; Loading @@ -163,7 +164,7 @@ static void ipa_process_interrupts(void) bmsk = 1; for (i = 0; i < IPA_IRQ_NUM_MAX; i++) { if (en & reg & bmsk) handle_interrupt(i); handle_interrupt(i, isr_context); bmsk = bmsk << 1; } ipa_write_reg(ipa_ctx->mmio, Loading @@ -177,7 +178,7 @@ static void ipa_interrupt_defer(struct work_struct *work) { IPADBG("processing interrupts in wq\n"); ipa_inc_client_enable_clks(); ipa_process_interrupts(); ipa_process_interrupts(false); ipa_dec_client_disable_clks(); IPADBG("Done\n"); } Loading @@ -199,7 +200,7 @@ static irqreturn_t ipa_isr(int irq, void *ctxt) goto bail; } ipa_process_interrupts(); ipa_process_interrupts(true); bail: ipa_active_clients_trylock_unlock(&flags); Loading drivers/platform/msm/ipa/ipa_v2/ipa_utils.c +43 −4 Original line number Diff line number Diff line Loading @@ -5097,15 +5097,54 @@ void ipa_suspend_apps_pipes(bool suspend) { struct ipa_ep_cfg_ctrl cfg; int ipa_ep_idx; u32 lan_empty = 0, wan_empty = 0; int ret; struct sps_event_notify notify; struct ipa_ep_context *ep; memset(&cfg, 0, sizeof(cfg)); cfg.ipa_ep_suspend = suspend; ipa_ep_idx = ipa_get_ep_mapping(IPA_CLIENT_APPS_LAN_CONS); if (ipa_ctx->ep[ipa_ep_idx].valid) ipa_cfg_ep_ctrl(ipa_ep_idx, &cfg); ep = &ipa_ctx->ep[ipa_ep_idx]; if (ep->valid) { ipa2_cfg_ep_ctrl(ipa_ep_idx, &cfg); /* Check if the pipes are empty. */ ret = sps_is_pipe_empty(ep->ep_hdl, &lan_empty); if (ret) { IPAERR("%s: sps_is_pipe_empty failed with %d\n", __func__, ret); } if (!lan_empty) { IPADBG("LAN Cons is not-empty. Enter poll mode.\n"); notify.user = ep->sys; notify.event_id = SPS_EVENT_EOT; if (ep->sys->sps_callback) ep->sys->sps_callback(¬ify); } } ipa_ep_idx = ipa_get_ep_mapping(IPA_CLIENT_APPS_WAN_CONS); if (ipa_ctx->ep[ipa_ep_idx].valid) ipa_cfg_ep_ctrl(ipa_ep_idx, &cfg); /* Considering the case for SSR. */ if (ipa_ep_idx == -1) { IPADBG("Invalid client.\n"); return; } ep = &ipa_ctx->ep[ipa_ep_idx]; if (ep->valid) { ipa2_cfg_ep_ctrl(ipa_ep_idx, &cfg); /* Check if the pipes are empty. */ ret = sps_is_pipe_empty(ep->ep_hdl, &wan_empty); if (ret) { IPAERR("%s: sps_is_pipe_empty failed with %d\n", __func__, ret); } if (!wan_empty) { IPADBG("WAN Cons is not-empty. Enter poll mode.\n"); notify.user = ep->sys; notify.event_id = SPS_EVENT_EOT; if (ep->sys->sps_callback) ep->sys->sps_callback(¬ify); } } } Loading
drivers/platform/msm/ipa/ipa_v2/ipa.c +7 −2 Original line number Diff line number Diff line Loading @@ -2544,6 +2544,8 @@ void _ipa_enable_clks_v2_0(void) if (smmu_clk) clk_prepare_enable(smmu_clk); /* Enable the BAM IRQ. */ ipa_sps_irq_control_all(true); ipa_suspend_apps_pipes(false); } Loading Loading @@ -2667,6 +2669,7 @@ void _ipa_disable_clks_v2_0(void) { IPADBG("disabling gcc_ipa_clk\n"); ipa_suspend_apps_pipes(true); ipa_sps_irq_control_all(false); ipa_uc_notify_clk_state(false); if (ipa_clk) clk_disable_unprepare(ipa_clk); Loading Loading @@ -3023,6 +3026,8 @@ void ipa_suspend_handler(enum ipa_irq_type interrupt, &ipa_ctx->sps_pm.dec_clients) ) { ipa_inc_client_enable_clks(); IPADBG("Pipes un-suspended.\n"); IPADBG("Enter poll mode.\n"); atomic_set( &ipa_ctx->sps_pm.dec_clients, 1); Loading Loading @@ -3575,8 +3580,8 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p, } /*add handler for suspend interrupt*/ result = ipa2_add_interrupt_handler(IPA_TX_SUSPEND_IRQ, ipa_suspend_handler, true, NULL); result = ipa_add_interrupt_handler(IPA_TX_SUSPEND_IRQ, ipa_suspend_handler, false, NULL); if (result) { IPAERR("register handler for suspend interrupt failed\n"); result = -ENODEV; Loading
drivers/platform/msm/ipa/ipa_v2/ipa_dp.c +71 −0 Original line number Diff line number Diff line Loading @@ -792,6 +792,77 @@ fail: msecs_to_jiffies(1)); } /** * ipa_sps_irq_control() - Function to enable or disable BAM IRQ. */ static void ipa_sps_irq_control(struct ipa_sys_context *sys, bool enable) { int ret; if (enable) { ret = sps_get_config(sys->ep->ep_hdl, &sys->ep->connect); if (ret) { IPAERR("sps_get_config() failed %d\n", ret); return; } sys->event.options = SPS_O_EOT; ret = sps_register_event(sys->ep->ep_hdl, &sys->event); if (ret) { IPAERR("sps_register_event() failed %d\n", ret); return; } sys->ep->connect.options = SPS_O_AUTO_ENABLE | SPS_O_ACK_TRANSFERS | SPS_O_EOT; ret = sps_set_config(sys->ep->ep_hdl, &sys->ep->connect); if (ret) { IPAERR("sps_set_config() failed %d\n", ret); return; } } else { ret = sps_get_config(sys->ep->ep_hdl, &sys->ep->connect); if (ret) { IPAERR("sps_get_config() failed %d\n", ret); return; } sys->ep->connect.options = SPS_O_AUTO_ENABLE | SPS_O_ACK_TRANSFERS | SPS_O_POLL; ret = sps_set_config(sys->ep->ep_hdl, &sys->ep->connect); if (ret) { IPAERR("sps_set_config() failed %d\n", ret); return; } } } void ipa_sps_irq_control_all(bool enable) { struct ipa_ep_context *ep; int ipa_ep_idx, client_num; IPADBG("\n"); for (client_num = IPA_CLIENT_CONS; client_num < IPA_CLIENT_MAX; client_num++) { if (!IPA_CLIENT_IS_APPS_CONS(client_num)) continue; ipa_ep_idx = ipa_get_ep_mapping(client_num); if (ipa_ep_idx == -1) { IPAERR("Invalid client.\n"); continue; } ep = &ipa_ctx->ep[ipa_ep_idx]; if (!ep->valid) { IPAERR("EP (%d) not allocated.\n", ipa_ep_idx); continue; } ipa_sps_irq_control(ep->sys, enable); } } /** * ipa_rx_notify() - Callback function which is called by the SPS driver when a * a packet is received Loading
drivers/platform/msm/ipa/ipa_v2/ipa_i.h +1 −0 Original line number Diff line number Diff line Loading @@ -1987,4 +1987,5 @@ void ipa_update_repl_threshold(enum ipa_client_type ipa_client); void ipa_flow_control(enum ipa_client_type ipa_client, bool enable, uint32_t qmap_id); int ipa2_restore_suspend_handler(void); void ipa_sps_irq_control_all(bool enable); #endif /* _IPA_I_H_ */
drivers/platform/msm/ipa/ipa_v2/ipa_interrupts.c +7 −6 Original line number Diff line number Diff line Loading @@ -85,7 +85,7 @@ static bool is_valid_ep(u32 ep_suspend_data) return false; } static int handle_interrupt(int irq_num) static int handle_interrupt(int irq_num, bool isr_context) { struct ipa_interrupt_info interrupt_info; struct ipa_interrupt_work_wrap *work_data; Loading Loading @@ -121,7 +121,8 @@ static int handle_interrupt(int irq_num) break; } if (interrupt_info.deferred_flag) { /* Force defer processing if in ISR context. */ if (interrupt_info.deferred_flag || isr_context) { work_data = kzalloc(sizeof(struct ipa_interrupt_work_wrap), GFP_ATOMIC); if (!work_data) { Loading Loading @@ -150,7 +151,7 @@ fail_alloc_work: return res; } static void ipa_process_interrupts(void) static void ipa_process_interrupts(bool isr_context) { u32 reg; u32 bmsk; Loading @@ -163,7 +164,7 @@ static void ipa_process_interrupts(void) bmsk = 1; for (i = 0; i < IPA_IRQ_NUM_MAX; i++) { if (en & reg & bmsk) handle_interrupt(i); handle_interrupt(i, isr_context); bmsk = bmsk << 1; } ipa_write_reg(ipa_ctx->mmio, Loading @@ -177,7 +178,7 @@ static void ipa_interrupt_defer(struct work_struct *work) { IPADBG("processing interrupts in wq\n"); ipa_inc_client_enable_clks(); ipa_process_interrupts(); ipa_process_interrupts(false); ipa_dec_client_disable_clks(); IPADBG("Done\n"); } Loading @@ -199,7 +200,7 @@ static irqreturn_t ipa_isr(int irq, void *ctxt) goto bail; } ipa_process_interrupts(); ipa_process_interrupts(true); bail: ipa_active_clients_trylock_unlock(&flags); Loading
drivers/platform/msm/ipa/ipa_v2/ipa_utils.c +43 −4 Original line number Diff line number Diff line Loading @@ -5097,15 +5097,54 @@ void ipa_suspend_apps_pipes(bool suspend) { struct ipa_ep_cfg_ctrl cfg; int ipa_ep_idx; u32 lan_empty = 0, wan_empty = 0; int ret; struct sps_event_notify notify; struct ipa_ep_context *ep; memset(&cfg, 0, sizeof(cfg)); cfg.ipa_ep_suspend = suspend; ipa_ep_idx = ipa_get_ep_mapping(IPA_CLIENT_APPS_LAN_CONS); if (ipa_ctx->ep[ipa_ep_idx].valid) ipa_cfg_ep_ctrl(ipa_ep_idx, &cfg); ep = &ipa_ctx->ep[ipa_ep_idx]; if (ep->valid) { ipa2_cfg_ep_ctrl(ipa_ep_idx, &cfg); /* Check if the pipes are empty. */ ret = sps_is_pipe_empty(ep->ep_hdl, &lan_empty); if (ret) { IPAERR("%s: sps_is_pipe_empty failed with %d\n", __func__, ret); } if (!lan_empty) { IPADBG("LAN Cons is not-empty. Enter poll mode.\n"); notify.user = ep->sys; notify.event_id = SPS_EVENT_EOT; if (ep->sys->sps_callback) ep->sys->sps_callback(¬ify); } } ipa_ep_idx = ipa_get_ep_mapping(IPA_CLIENT_APPS_WAN_CONS); if (ipa_ctx->ep[ipa_ep_idx].valid) ipa_cfg_ep_ctrl(ipa_ep_idx, &cfg); /* Considering the case for SSR. */ if (ipa_ep_idx == -1) { IPADBG("Invalid client.\n"); return; } ep = &ipa_ctx->ep[ipa_ep_idx]; if (ep->valid) { ipa2_cfg_ep_ctrl(ipa_ep_idx, &cfg); /* Check if the pipes are empty. */ ret = sps_is_pipe_empty(ep->ep_hdl, &wan_empty); if (ret) { IPAERR("%s: sps_is_pipe_empty failed with %d\n", __func__, ret); } if (!wan_empty) { IPADBG("WAN Cons is not-empty. Enter poll mode.\n"); notify.user = ep->sys; notify.event_id = SPS_EVENT_EOT; if (ep->sys->sps_callback) ep->sys->sps_callback(¬ify); } } }