u32 user_base_data, base_vector;
        int ret, num_vectors, i;
        int *irq;
+       unsigned int msi_data;
 
        ret = ath12k_pci_get_user_msi_assignment(ab,
                                                 "MHI", &num_vectors,
        if (!irq)
                return -ENOMEM;
 
-       for (i = 0; i < num_vectors; i++)
-               irq[i] = ath12k_pci_get_msi_irq(ab->dev,
-                                               base_vector + i);
+       msi_data = base_vector;
+       for (i = 0; i < num_vectors; i++) {
+               if (test_bit(ATH12K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
+                       irq[i] = ath12k_pci_get_msi_irq(ab->dev,
+                                                       msi_data++);
+               else
+                       irq[i] = ath12k_pci_get_msi_irq(ab->dev,
+                                                       msi_data);
+       }
 
        ab_pci->mhi_ctrl->irq = irq;
        ab_pci->mhi_ctrl->nr_irqs = num_vectors;
                goto free_controller;
        }
 
+       if (!test_bit(ATH12K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
+               mhi_ctrl->irq_flags = IRQF_SHARED | IRQF_NOBALANCING;
+
        mhi_ctrl->iova_start = 0;
        mhi_ctrl->iova_stop = 0xffffffff;
        mhi_ctrl->sbl_size = SZ_512K;
 
        },
 };
 
+static const struct ath12k_msi_config msi_config_one_msi = {
+       .total_vectors = 1,
+       .total_users = 4,
+       .users = (struct ath12k_msi_user[]) {
+               { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
+               { .name = "CE", .num_vectors = 1, .base_vector = 0 },
+               { .name = "WAKE", .num_vectors = 1, .base_vector = 0 },
+               { .name = "DP", .num_vectors = 1, .base_vector = 0 },
+       },
+};
+
 static const char *irq_name[ATH12K_IRQ_NUM_MAX] = {
        "bhi",
        "mhi-er0",
 static void ath12k_pci_ce_tasklet(struct tasklet_struct *t)
 {
        struct ath12k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
+       int irq_idx = ATH12K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
 
        ath12k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
 
-       ath12k_pci_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num);
+       enable_irq(ce_pipe->ab->irq_num[irq_idx]);
 }
 
 static irqreturn_t ath12k_pci_ce_interrupt_handler(int irq, void *arg)
 {
        struct ath12k_ce_pipe *ce_pipe = arg;
        struct ath12k_base *ab = ce_pipe->ab;
+       int irq_idx = ATH12K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
 
        if (!test_bit(ATH12K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags))
                return IRQ_HANDLED;
        /* last interrupt received for this CE */
        ce_pipe->timestamp = jiffies;
 
-       ath12k_pci_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
+       disable_irq_nosync(ab->irq_num[irq_idx]);
+
        tasklet_schedule(&ce_pipe->intr_tq);
 
        return IRQ_HANDLED;
                                                napi);
        struct ath12k_base *ab = irq_grp->ab;
        int work_done;
+       int i;
 
        work_done = ath12k_dp_service_srng(ab, irq_grp, budget);
        if (work_done < budget) {
                napi_complete_done(napi, work_done);
-               ath12k_pci_ext_grp_enable(irq_grp);
+               for (i = 0; i < irq_grp->num_irq; i++)
+                       enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
        }
 
        if (work_done > budget)
 {
        struct ath12k_ext_irq_grp *irq_grp = arg;
        struct ath12k_base *ab = irq_grp->ab;
+       int i;
 
        if (!test_bit(ATH12K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags))
                return IRQ_HANDLED;
        /* last interrupt received for this group */
        irq_grp->timestamp = jiffies;
 
-       ath12k_pci_ext_grp_disable(irq_grp);
+       for (i = 0; i < irq_grp->num_irq; i++)
+               disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
 
        napi_schedule(&irq_grp->napi);
 
                                            msi_config->total_vectors,
                                            msi_config->total_vectors,
                                            PCI_IRQ_MSI);
-       if (num_vectors != msi_config->total_vectors) {
-               ath12k_err(ab, "failed to get %d MSI vectors, only %d available",
-                          msi_config->total_vectors, num_vectors);
 
-               if (num_vectors >= 0)
-                       return -EINVAL;
-               else
-                       return num_vectors;
-       } else {
+       if (num_vectors == msi_config->total_vectors) {
                set_bit(ATH12K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags);
                ab_pci->irq_flags = IRQF_SHARED;
+       } else {
+               num_vectors = pci_alloc_irq_vectors(ab_pci->pdev,
+                                                   1,
+                                                   1,
+                                                   PCI_IRQ_MSI);
+               if (num_vectors < 0) {
+                       ret = -EINVAL;
+                       goto reset_msi_config;
+               }
+               clear_bit(ATH12K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags);
+               ab_pci->msi_config = &msi_config_one_msi;
+               ab_pci->irq_flags = IRQF_SHARED | IRQF_NOBALANCING;
+               ath12k_dbg(ab, ATH12K_DBG_PCI, "request MSI one vector\n");
        }
 
+       ath12k_info(ab, "MSI vectors: %d\n", num_vectors);
+
        ath12k_pci_msi_disable(ab_pci);
 
        msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
 free_msi_vector:
        pci_free_irq_vectors(ab_pci->pdev);
 
+reset_msi_config:
        return ret;
 }