ath10k_ce_write32(ar, ce_ctrl_addr + wm_regs->addr, mask);
 }
 
-static bool ath10k_ce_engine_int_status_check(struct ath10k *ar, u32 ce_ctrl_addr,
-                                             unsigned int mask)
-{
-       struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
-
-       return ath10k_ce_read32(ar, ce_ctrl_addr + wm_regs->addr) & mask;
-}
-
-u32 ath10k_ce_gen_interrupt_summary(struct ath10k *ar)
-{
-       struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
-       struct ath10k_ce_pipe *ce_state;
-       struct ath10k_ce *ce;
-       u32 irq_summary = 0;
-       u32 ctrl_addr;
-       u32 ce_id;
-
-       ce = ath10k_ce_priv(ar);
-
-       for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
-               ce_state = &ce->ce_states[ce_id];
-               ctrl_addr = ce_state->ctrl_addr;
-               if (ath10k_ce_engine_int_status_check(ar, ctrl_addr,
-                                                     wm_regs->cc_mask)) {
-                       irq_summary |= BIT(ce_id);
-               }
-       }
-
-       return irq_summary;
-}
-EXPORT_SYMBOL(ath10k_ce_gen_interrupt_summary);
-
 /*
  * Guts of ath10k_ce_send.
  * The caller takes responsibility for any needed locking.
        ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
 }
 
-int ath10k_ce_disable_interrupts(struct ath10k *ar)
+void ath10k_ce_disable_interrupt(struct ath10k *ar, int ce_id)
 {
        struct ath10k_ce *ce = ath10k_ce_priv(ar);
        struct ath10k_ce_pipe *ce_state;
        u32 ctrl_addr;
-       int ce_id;
 
-       for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
-               ce_state  = &ce->ce_states[ce_id];
-               if (ce_state->attr_flags & CE_ATTR_POLL)
-                       continue;
+       ce_state  = &ce->ce_states[ce_id];
+       if (ce_state->attr_flags & CE_ATTR_POLL)
+               return;
 
-               ctrl_addr = ath10k_ce_base_address(ar, ce_id);
+       ctrl_addr = ath10k_ce_base_address(ar, ce_id);
 
-               ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr);
-               ath10k_ce_error_intr_disable(ar, ctrl_addr);
-               ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
-       }
+       ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr);
+       ath10k_ce_error_intr_disable(ar, ctrl_addr);
+       ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
+}
+EXPORT_SYMBOL(ath10k_ce_disable_interrupt);
 
-       return 0;
+void ath10k_ce_disable_interrupts(struct ath10k *ar)
+{
+       int ce_id;
+
+       for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
+               ath10k_ce_disable_interrupt(ar, ce_id);
 }
 EXPORT_SYMBOL(ath10k_ce_disable_interrupts);
 
-void ath10k_ce_enable_interrupts(struct ath10k *ar)
+void ath10k_ce_enable_interrupt(struct ath10k *ar, int ce_id)
 {
        struct ath10k_ce *ce = ath10k_ce_priv(ar);
-       int ce_id;
        struct ath10k_ce_pipe *ce_state;
 
+       ce_state  = &ce->ce_states[ce_id];
+       if (ce_state->attr_flags & CE_ATTR_POLL)
+               return;
+
+       ath10k_ce_per_engine_handler_adjust(ce_state);
+}
+EXPORT_SYMBOL(ath10k_ce_enable_interrupt);
+
+void ath10k_ce_enable_interrupts(struct ath10k *ar)
+{
+       int ce_id;
+
        /* Enable interrupts for copy engine that
         * are not using polling mode.
         */
-       for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
-               ce_state  = &ce->ce_states[ce_id];
-               if (ce_state->attr_flags & CE_ATTR_POLL)
-                       continue;
-
-               ath10k_ce_per_engine_handler_adjust(ce_state);
-       }
+       for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
+               ath10k_ce_enable_interrupt(ar, ce_id);
 }
 EXPORT_SYMBOL(ath10k_ce_enable_interrupts);
 
 
 /*==================CE Interrupt Handlers====================*/
 void ath10k_ce_per_engine_service_any(struct ath10k *ar);
 void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id);
-int ath10k_ce_disable_interrupts(struct ath10k *ar);
+void ath10k_ce_disable_interrupt(struct ath10k *ar, int ce_id);
+void ath10k_ce_disable_interrupts(struct ath10k *ar);
+void ath10k_ce_enable_interrupt(struct ath10k *ar, int ce_id);
 void ath10k_ce_enable_interrupts(struct ath10k *ar);
 void ath10k_ce_dump_registers(struct ath10k *ar,
                              struct ath10k_fw_crash_data *crash_data);
 
-u32 ath10k_ce_gen_interrupt_summary(struct ath10k *ar);
 void ath10k_ce_alloc_rri(struct ath10k *ar);
 void ath10k_ce_free_rri(struct ath10k *ar);
 
 {
        struct ath10k_ce *ce = ath10k_ce_priv(ar);
 
-       if (!ar->hw_params.per_ce_irq)
-               return CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET(
-                       ce->bus_ops->read32((ar), CE_WRAPPER_BASE_ADDRESS +
-                       CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS));
-       else
-               return ath10k_ce_gen_interrupt_summary(ar);
+       return CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET(
+               ce->bus_ops->read32((ar), CE_WRAPPER_BASE_ADDRESS +
+               CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS));
 }
 
 /* Host software's Copy Engine configuration. */
 
  * Copyright (c) 2018 The Linux Foundation. All rights reserved.
  */
 
+#include <linux/bits.h>
 #include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 {
        struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
 
+       bitmap_clear(ar_snoc->pending_ce_irqs, 0, CE_COUNT_MAX);
        napi_enable(&ar->napi);
        ath10k_snoc_irq_enable(ar);
        ath10k_snoc_rx_post(ar);
                return IRQ_HANDLED;
        }
 
-       ath10k_snoc_irq_disable(ar);
+       ath10k_ce_disable_interrupt(ar, ce_id);
+       set_bit(ce_id, ar_snoc->pending_ce_irqs);
+
        napi_schedule(&ar->napi);
 
        return IRQ_HANDLED;
 static int ath10k_snoc_napi_poll(struct napi_struct *ctx, int budget)
 {
        struct ath10k *ar = container_of(ctx, struct ath10k, napi);
+       struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
        int done = 0;
+       int ce_id;
 
        if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) {
                napi_complete(ctx);
                return done;
        }
 
-       ath10k_ce_per_engine_service_any(ar);
+       for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
+               if (test_and_clear_bit(ce_id, ar_snoc->pending_ce_irqs)) {
+                       ath10k_ce_per_engine_service(ar, ce_id);
+                       ath10k_ce_enable_interrupt(ar, ce_id);
+               }
+
        done = ath10k_htt_txrx_compl_task(ar, budget);
 
-       if (done < budget) {
+       if (done < budget)
                napi_complete(ctx);
-               ath10k_snoc_irq_enable(ar);
-       }
 
        return done;
 }