Skip to content

Commit 8398654

Browse files
Kang Yangkvalo
authored andcommitted
wifi: ath12k: add support one MSI vector
On some platforms it's not possible to allocate 32 MSI vectors for various reasons, maybe kernel configuration, VT-d disabled, buggy BIOS etc. So ath12k was not able to use WCN7850 PCI devices on those platforms. Add support for one MSI vector to solve that. In case of one MSI vector, interrupt migration needs to be disabled. This is because when interrupt migration happens, the msi_data may change. However, msi_data is already programmed to rings during initial phase and ath12k has no way to know that msi_data is changed during run time and reprogram again. In case of one MSI vector, MHI subsystem should not use IRQF_NO_SUSPEND as WCN7850 doesn't set this flag too. Ath12k doesn't need to leave IRQ enabled in suspend state. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Signed-off-by: Kang Yang <[email protected]> Acked-by: Jeff Johnson <[email protected]> Signed-off-by: Kalle Valo <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 6711b2a commit 8398654

File tree

2 files changed

+52
-15
lines changed

2 files changed

+52
-15
lines changed

drivers/net/wireless/ath/ath12k/mhi.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ static int ath12k_mhi_get_msi(struct ath12k_pci *ab_pci)
251251
u32 user_base_data, base_vector;
252252
int ret, num_vectors, i;
253253
int *irq;
254+
unsigned int msi_data;
254255

255256
ret = ath12k_pci_get_user_msi_assignment(ab,
256257
"MHI", &num_vectors,
@@ -265,9 +266,15 @@ static int ath12k_mhi_get_msi(struct ath12k_pci *ab_pci)
265266
if (!irq)
266267
return -ENOMEM;
267268

268-
for (i = 0; i < num_vectors; i++)
269-
irq[i] = ath12k_pci_get_msi_irq(ab->dev,
270-
base_vector + i);
269+
msi_data = base_vector;
270+
for (i = 0; i < num_vectors; i++) {
271+
if (test_bit(ATH12K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
272+
irq[i] = ath12k_pci_get_msi_irq(ab->dev,
273+
msi_data++);
274+
else
275+
irq[i] = ath12k_pci_get_msi_irq(ab->dev,
276+
msi_data);
277+
}
271278

272279
ab_pci->mhi_ctrl->irq = irq;
273280
ab_pci->mhi_ctrl->nr_irqs = num_vectors;
@@ -374,6 +381,9 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci)
374381
goto free_controller;
375382
}
376383

384+
if (!test_bit(ATH12K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
385+
mhi_ctrl->irq_flags = IRQF_SHARED | IRQF_NOBALANCING;
386+
377387
mhi_ctrl->iova_start = 0;
378388
mhi_ctrl->iova_stop = 0xffffffff;
379389
mhi_ctrl->sbl_size = SZ_512K;

drivers/net/wireless/ath/ath12k/pci.c

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,17 @@ static const struct ath12k_msi_config ath12k_msi_config[] = {
6161
},
6262
};
6363

64+
static const struct ath12k_msi_config msi_config_one_msi = {
65+
.total_vectors = 1,
66+
.total_users = 4,
67+
.users = (struct ath12k_msi_user[]) {
68+
{ .name = "MHI", .num_vectors = 3, .base_vector = 0 },
69+
{ .name = "CE", .num_vectors = 1, .base_vector = 0 },
70+
{ .name = "WAKE", .num_vectors = 1, .base_vector = 0 },
71+
{ .name = "DP", .num_vectors = 1, .base_vector = 0 },
72+
},
73+
};
74+
6475
static const char *irq_name[ATH12K_IRQ_NUM_MAX] = {
6576
"bhi",
6677
"mhi-er0",
@@ -414,24 +425,27 @@ static void ath12k_pci_sync_ce_irqs(struct ath12k_base *ab)
414425
static void ath12k_pci_ce_tasklet(struct tasklet_struct *t)
415426
{
416427
struct ath12k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
428+
int irq_idx = ATH12K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
417429

418430
ath12k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
419431

420-
ath12k_pci_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num);
432+
enable_irq(ce_pipe->ab->irq_num[irq_idx]);
421433
}
422434

423435
static irqreturn_t ath12k_pci_ce_interrupt_handler(int irq, void *arg)
424436
{
425437
struct ath12k_ce_pipe *ce_pipe = arg;
426438
struct ath12k_base *ab = ce_pipe->ab;
439+
int irq_idx = ATH12K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
427440

428441
if (!test_bit(ATH12K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags))
429442
return IRQ_HANDLED;
430443

431444
/* last interrupt received for this CE */
432445
ce_pipe->timestamp = jiffies;
433446

434-
ath12k_pci_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
447+
disable_irq_nosync(ab->irq_num[irq_idx]);
448+
435449
tasklet_schedule(&ce_pipe->intr_tq);
436450

437451
return IRQ_HANDLED;
@@ -504,11 +518,13 @@ static int ath12k_pci_ext_grp_napi_poll(struct napi_struct *napi, int budget)
504518
napi);
505519
struct ath12k_base *ab = irq_grp->ab;
506520
int work_done;
521+
int i;
507522

508523
work_done = ath12k_dp_service_srng(ab, irq_grp, budget);
509524
if (work_done < budget) {
510525
napi_complete_done(napi, work_done);
511-
ath12k_pci_ext_grp_enable(irq_grp);
526+
for (i = 0; i < irq_grp->num_irq; i++)
527+
enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
512528
}
513529

514530
if (work_done > budget)
@@ -521,6 +537,7 @@ static irqreturn_t ath12k_pci_ext_interrupt_handler(int irq, void *arg)
521537
{
522538
struct ath12k_ext_irq_grp *irq_grp = arg;
523539
struct ath12k_base *ab = irq_grp->ab;
540+
int i;
524541

525542
if (!test_bit(ATH12K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags))
526543
return IRQ_HANDLED;
@@ -530,7 +547,8 @@ static irqreturn_t ath12k_pci_ext_interrupt_handler(int irq, void *arg)
530547
/* last interrupt received for this group */
531548
irq_grp->timestamp = jiffies;
532549

533-
ath12k_pci_ext_grp_disable(irq_grp);
550+
for (i = 0; i < irq_grp->num_irq; i++)
551+
disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
534552

535553
napi_schedule(&irq_grp->napi);
536554

@@ -713,19 +731,27 @@ static int ath12k_pci_msi_alloc(struct ath12k_pci *ab_pci)
713731
msi_config->total_vectors,
714732
msi_config->total_vectors,
715733
PCI_IRQ_MSI);
716-
if (num_vectors != msi_config->total_vectors) {
717-
ath12k_err(ab, "failed to get %d MSI vectors, only %d available",
718-
msi_config->total_vectors, num_vectors);
719734

720-
if (num_vectors >= 0)
721-
return -EINVAL;
722-
else
723-
return num_vectors;
724-
} else {
735+
if (num_vectors == msi_config->total_vectors) {
725736
set_bit(ATH12K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags);
726737
ab_pci->irq_flags = IRQF_SHARED;
738+
} else {
739+
num_vectors = pci_alloc_irq_vectors(ab_pci->pdev,
740+
1,
741+
1,
742+
PCI_IRQ_MSI);
743+
if (num_vectors < 0) {
744+
ret = -EINVAL;
745+
goto reset_msi_config;
746+
}
747+
clear_bit(ATH12K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags);
748+
ab_pci->msi_config = &msi_config_one_msi;
749+
ab_pci->irq_flags = IRQF_SHARED | IRQF_NOBALANCING;
750+
ath12k_dbg(ab, ATH12K_DBG_PCI, "request MSI one vector\n");
727751
}
728752

753+
ath12k_info(ab, "MSI vectors: %d\n", num_vectors);
754+
729755
ath12k_pci_msi_disable(ab_pci);
730756

731757
msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
@@ -746,6 +772,7 @@ static int ath12k_pci_msi_alloc(struct ath12k_pci *ab_pci)
746772
free_msi_vector:
747773
pci_free_irq_vectors(ab_pci->pdev);
748774

775+
reset_msi_config:
749776
return ret;
750777
}
751778

0 commit comments

Comments
 (0)