diff options
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ath11k/mhi.c | 14 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath11k/pci.c | 52 |
2 files changed, 51 insertions, 15 deletions
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c index 26c7ae242db6..d0f94a785a59 100644 --- a/drivers/net/wireless/ath/ath11k/mhi.c +++ b/drivers/net/wireless/ath/ath11k/mhi.c @@ -248,6 +248,7 @@ static int ath11k_mhi_get_msi(struct ath11k_pci *ab_pci) u32 user_base_data, base_vector; int ret, num_vectors, i; int *irq; + unsigned int msi_data; ret = ath11k_pci_get_user_msi_assignment(ab_pci, "MHI", &num_vectors, @@ -262,9 +263,15 @@ static int ath11k_mhi_get_msi(struct ath11k_pci *ab_pci) if (!irq) return -ENOMEM; - for (i = 0; i < num_vectors; i++) + for (i = 0; i < num_vectors; i++) { + msi_data = base_vector; + + if (test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags)) + msi_data += i; + irq[i] = ath11k_pci_get_msi_irq(ab->dev, - base_vector + i); + msi_data); + } ab_pci->mhi_ctrl->irq = irq; ab_pci->mhi_ctrl->nr_irqs = num_vectors; @@ -339,6 +346,9 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci) return ret; } + if (!test_bit(ATH11K_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; diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c index 825d2846d10b..671a80b03973 100644 --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c @@ -77,6 +77,17 @@ static const struct ath11k_msi_config ath11k_msi_config[] = { }, }; +static const struct ath11k_msi_config msi_config_one_msi = { + .total_vectors = 1, + .total_users = 4, + .users = (struct ath11k_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[ATH11K_IRQ_NUM_MAX] = { "bhi", "mhi-er0", @@ -619,16 +630,18 @@ static void ath11k_pci_sync_ce_irqs(struct ath11k_base *ab) static void ath11k_pci_ce_tasklet(struct tasklet_struct *t) { struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq); + int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num; ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num); - ath11k_pci_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num); + enable_irq(ce_pipe->ab->irq_num[irq_idx]); } static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg) { struct ath11k_ce_pipe *ce_pipe = arg; struct ath11k_base *ab = ce_pipe->ab; + int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num; if (!test_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags)) return IRQ_HANDLED; @@ -636,7 +649,8 @@ static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg) /* last interrupt received for this CE */ ce_pipe->timestamp = jiffies; - ath11k_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; @@ -729,11 +743,13 @@ static int ath11k_pci_ext_grp_napi_poll(struct napi_struct *napi, int budget) napi); struct ath11k_base *ab = irq_grp->ab; int work_done; + int i; work_done = ath11k_dp_service_srng(ab, irq_grp, budget); if (work_done < budget) { napi_complete_done(napi, work_done); - ath11k_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) @@ -746,6 +762,7 @@ static irqreturn_t ath11k_pci_ext_interrupt_handler(int irq, void *arg) { struct ath11k_ext_irq_grp *irq_grp = arg; struct ath11k_base *ab = irq_grp->ab; + int i; if (!test_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags)) return IRQ_HANDLED; @@ -755,7 +772,8 @@ static irqreturn_t ath11k_pci_ext_interrupt_handler(int irq, void *arg) /* last interrupt received for this group */ irq_grp->timestamp = jiffies; - ath11k_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); @@ -941,18 +959,25 @@ static int ath11k_pci_alloc_msi(struct ath11k_pci *ab_pci) msi_config->total_vectors, msi_config->total_vectors, PCI_IRQ_MSI); - if (num_vectors != msi_config->total_vectors) { - ath11k_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(ATH11K_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(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags); + ab_pci->msi_config = &msi_config_one_msi; + ab_pci->irq_flags = IRQF_SHARED | IRQF_NOBALANCING; + ath11k_dbg(ab, ATH11K_DBG_PCI, "request MSI one vector\n"); } + ath11k_info(ab, "MSI vectors: %d\n", num_vectors); + ath11k_pci_msi_disable(ab_pci); msi_desc = irq_get_msi_desc(ab_pci->pdev->irq); @@ -973,6 +998,7 @@ static int ath11k_pci_alloc_msi(struct ath11k_pci *ab_pci) free_msi_vector: pci_free_irq_vectors(ab_pci->pdev); +reset_msi_config: return ret; } |