ath11k: refactor multiple MSI vector implementation
authorCarl Huang <cjhuang@codeaurora.org>
Fri, 19 Nov 2021 13:36:26 +0000 (15:36 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 22 Nov 2021 11:11:02 +0000 (13:11 +0200)
This is to prepare for one MSI vector support. IRQ enable and disable
of CE and DP are done only in case of multiple MSI vectors.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1

Signed-off-by: Carl Huang <cjhuang@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Baochen Qiang <bqiang@codeaurora.org>
Link: https://lore.kernel.org/r/20211026041705.5167-1-bqiang@codeaurora.org
drivers/net/wireless/ath/ath11k/pci.c
drivers/net/wireless/ath/ath11k/pci.h

index c74e24ce0bd3a096fc0de103c93f112f6c4f969f..825d2846d10bcdc3ce545eebd36fdd12d0c9d961 100644 (file)
@@ -486,11 +486,11 @@ int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_nam
        for (idx = 0; idx < msi_config->total_users; idx++) {
                if (strcmp(user_name, msi_config->users[idx].name) == 0) {
                        *num_vectors = msi_config->users[idx].num_vectors;
-                       *user_base_data = msi_config->users[idx].base_vector
-                               + ab_pci->msi_ep_base_data;
-                       *base_vector = msi_config->users[idx].base_vector;
+                       *base_vector =  msi_config->users[idx].base_vector;
+                       *user_base_data = *base_vector + ab_pci->msi_ep_base_data;
 
-                       ath11k_dbg(ab, ATH11K_DBG_PCI, "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
+                       ath11k_dbg(ab, ATH11K_DBG_PCI,
+                                  "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
                                   user_name, *num_vectors, *user_base_data,
                                   *base_vector);
 
@@ -561,16 +561,30 @@ static void ath11k_pci_free_irq(struct ath11k_base *ab)
 
 static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
 {
+       struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
        u32 irq_idx;
 
+       /* In case of one MSI vector, we handle irq enable/disable in a
+        * uniform way since we only have one irq
+        */
+       if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
+               return;
+
        irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
        enable_irq(ab->irq_num[irq_idx]);
 }
 
 static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
 {
+       struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
        u32 irq_idx;
 
+       /* In case of one MSI vector, we handle irq enable/disable in a
+        * uniform way since we only have one irq
+        */
+       if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
+               return;
+
        irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
        disable_irq_nosync(ab->irq_num[irq_idx]);
 }
@@ -630,8 +644,15 @@ static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
 
 static void ath11k_pci_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
 {
+       struct ath11k_pci *ab_pci = ath11k_pci_priv(irq_grp->ab);
        int i;
 
+       /* In case of one MSI vector, we handle irq enable/disable
+        * in a uniform way since we only have one irq
+        */
+       if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
+               return;
+
        for (i = 0; i < irq_grp->num_irq; i++)
                disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
 }
@@ -654,8 +675,15 @@ static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc)
 
 static void ath11k_pci_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp)
 {
+       struct ath11k_pci *ab_pci = ath11k_pci_priv(irq_grp->ab);
        int i;
 
+       /* In case of one MSI vector, we handle irq enable/disable in a
+        * uniform way since we only have one irq
+        */
+       if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
+               return;
+
        for (i = 0; i < irq_grp->num_irq; i++)
                enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
 }
@@ -736,6 +764,7 @@ static irqreturn_t ath11k_pci_ext_interrupt_handler(int irq, void *arg)
 
 static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
 {
+       struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
        int i, j, ret, num_vectors = 0;
        u32 user_base_data = 0, base_vector = 0;
 
@@ -782,16 +811,15 @@ static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
 
                        irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY);
                        ret = request_irq(irq, ath11k_pci_ext_interrupt_handler,
-                                         IRQF_SHARED,
+                                         ab_pci->irq_flags,
                                          "DP_EXT_IRQ", irq_grp);
                        if (ret) {
                                ath11k_err(ab, "failed request irq %d: %d\n",
                                           vector, ret);
                                return ret;
                        }
-
-                       disable_irq_nosync(ab->irq_num[irq_idx]);
                }
+               ath11k_pci_ext_grp_disable(irq_grp);
        }
 
        return 0;
@@ -799,6 +827,7 @@ static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
 
 static int ath11k_pci_config_irq(struct ath11k_base *ab)
 {
+       struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
        struct ath11k_ce_pipe *ce_pipe;
        u32 msi_data_start;
        u32 msi_data_count, msi_data_idx;
@@ -826,7 +855,7 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
                tasklet_setup(&ce_pipe->intr_tq, ath11k_pci_ce_tasklet);
 
                ret = request_irq(irq, ath11k_pci_ce_interrupt_handler,
-                                 IRQF_SHARED, irq_name[irq_idx],
+                                 ab_pci->irq_flags, irq_name[irq_idx],
                                  ce_pipe);
                if (ret) {
                        ath11k_err(ab, "failed to request irq %d: %d\n",
@@ -920,6 +949,9 @@ static int ath11k_pci_alloc_msi(struct ath11k_pci *ab_pci)
                        return -EINVAL;
                else
                        return num_vectors;
+       } else {
+               set_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags);
+               ab_pci->irq_flags = IRQF_SHARED;
        }
        ath11k_pci_msi_disable(ab_pci);
 
index f3e645891d193ac0de955e26c60fa3205014273b..61d67b20a0eb4464b498ab00acbb94354fe3fcfe 100644 (file)
@@ -68,6 +68,7 @@ enum ath11k_pci_flags {
        ATH11K_PCI_FLAG_INIT_DONE,
        ATH11K_PCI_FLAG_IS_MSI_64,
        ATH11K_PCI_ASPM_RESTORE,
+       ATH11K_PCI_FLAG_MULTI_MSI_VECTORS,
 };
 
 struct ath11k_pci {
@@ -87,6 +88,8 @@ struct ath11k_pci {
        /* enum ath11k_pci_flags */
        unsigned long flags;
        u16 link_ctl;
+
+       unsigned long irq_flags;
 };
 
 static inline struct ath11k_pci *ath11k_pci_priv(struct ath11k_base *ab)