Skip to content

Commit 2c3960c

Browse files
govindsiKalle Valo
authored andcommitted
ath11k: setup ce tasklet for control path
CE srng is used for control path and CE srng processing is done using tasklet bottom half. Setup ce tasklet initialization and scheduling for control path. Needed for PCI support. Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.1.0.1-01238-QCAHKSWPL_SILICONZ-2 Signed-off-by: Govind Singh <[email protected]> Signed-off-by: Kalle Valo <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent c4eacab commit 2c3960c

File tree

3 files changed

+112
-8
lines changed

3 files changed

+112
-8
lines changed

drivers/net/wireless/ath/ath11k/ce.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ void ath11k_ce_poll_send_completed(struct ath11k_base *ab, u8 pipe_id)
524524
if ((pipe->attr_flags & CE_ATTR_DIS_INTR) && pipe->send_cb)
525525
pipe->send_cb(pipe);
526526
}
527+
EXPORT_SYMBOL(ath11k_ce_per_engine_service);
527528

528529
int ath11k_ce_send(struct ath11k_base *ab, struct sk_buff *skb, u8 pipe_id,
529530
u16 transfer_id)
@@ -673,6 +674,7 @@ void ath11k_ce_rx_post_buf(struct ath11k_base *ab)
673674
}
674675
}
675676
}
677+
EXPORT_SYMBOL(ath11k_ce_rx_post_buf);
676678

677679
void ath11k_ce_rx_replenish_retry(struct timer_list *t)
678680
{

drivers/net/wireless/ath/ath11k/ce.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,4 +181,6 @@ int ath11k_ce_alloc_pipes(struct ath11k_base *ab);
181181
void ath11k_ce_free_pipes(struct ath11k_base *ab);
182182
int ath11k_ce_get_attr_flags(int ce_id);
183183
void ath11k_ce_poll_send_completed(struct ath11k_base *ab, u8 pipe_id);
184+
int ath11k_ce_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
185+
u8 *ul_pipe, u8 *dl_pipe);
184186
#endif

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

Lines changed: 108 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,14 @@ static void ath11k_pci_free_irq(struct ath11k_base *ab)
401401
}
402402
}
403403

404+
static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
405+
{
406+
u32 irq_idx;
407+
408+
irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
409+
enable_irq(ab->irq_num[irq_idx]);
410+
}
411+
404412
static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
405413
{
406414
u32 irq_idx;
@@ -409,11 +417,46 @@ static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
409417
disable_irq_nosync(ab->irq_num[irq_idx]);
410418
}
411419

420+
static void ath11k_pci_ce_irqs_disable(struct ath11k_base *ab)
421+
{
422+
int i;
423+
424+
for (i = 0; i < CE_COUNT; i++) {
425+
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
426+
continue;
427+
ath11k_pci_ce_irq_disable(ab, i);
428+
}
429+
}
430+
431+
static void ath11k_pci_sync_ce_irqs(struct ath11k_base *ab)
432+
{
433+
int i;
434+
int irq_idx;
435+
436+
for (i = 0; i < CE_COUNT; i++) {
437+
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
438+
continue;
439+
440+
irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
441+
synchronize_irq(ab->irq_num[irq_idx]);
442+
}
443+
}
444+
445+
static void ath11k_pci_ce_tasklet(unsigned long data)
446+
{
447+
struct ath11k_ce_pipe *ce_pipe = (struct ath11k_ce_pipe *)data;
448+
449+
ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
450+
451+
ath11k_pci_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num);
452+
}
453+
412454
static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
413455
{
414456
struct ath11k_ce_pipe *ce_pipe = arg;
415457

416458
ath11k_pci_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
459+
tasklet_schedule(&ce_pipe->intr_tq);
417460

418461
return IRQ_HANDLED;
419462
}
@@ -444,6 +487,9 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
444487

445488
irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
446489

490+
tasklet_init(&ce_pipe->intr_tq, ath11k_pci_ce_tasklet,
491+
(unsigned long)ce_pipe);
492+
447493
ret = request_irq(irq, ath11k_pci_ce_interrupt_handler,
448494
IRQF_SHARED, irq_name[irq_idx],
449495
ce_pipe);
@@ -471,14 +517,6 @@ static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab)
471517
ab->qmi.service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390;
472518
}
473519

474-
static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
475-
{
476-
u32 irq_idx;
477-
478-
irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
479-
enable_irq(ab->irq_num[irq_idx]);
480-
}
481-
482520
static void ath11k_pci_ce_irqs_enable(struct ath11k_base *ab)
483521
{
484522
int i;
@@ -638,14 +676,75 @@ static void ath11k_pci_power_down(struct ath11k_base *ab)
638676
ath11k_mhi_stop(ab_pci);
639677
}
640678

679+
static void ath11k_pci_kill_tasklets(struct ath11k_base *ab)
680+
{
681+
int i;
682+
683+
for (i = 0; i < CE_COUNT; i++) {
684+
struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
685+
686+
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
687+
continue;
688+
689+
tasklet_kill(&ce_pipe->intr_tq);
690+
}
691+
}
692+
641693
static void ath11k_pci_stop(struct ath11k_base *ab)
642694
{
695+
ath11k_pci_ce_irqs_disable(ab);
696+
ath11k_pci_sync_ce_irqs(ab);
697+
ath11k_pci_kill_tasklets(ab);
643698
ath11k_ce_cleanup_pipes(ab);
644699
}
645700

646701
static int ath11k_pci_start(struct ath11k_base *ab)
647702
{
648703
ath11k_pci_ce_irqs_enable(ab);
704+
ath11k_ce_rx_post_buf(ab);
705+
706+
return 0;
707+
}
708+
709+
static int ath11k_pci_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
710+
u8 *ul_pipe, u8 *dl_pipe)
711+
{
712+
const struct service_to_pipe *entry;
713+
bool ul_set = false, dl_set = false;
714+
int i;
715+
716+
for (i = 0; i < ARRAY_SIZE(target_service_to_ce_map_wlan); i++) {
717+
entry = &target_service_to_ce_map_wlan[i];
718+
719+
if (__le32_to_cpu(entry->service_id) != service_id)
720+
continue;
721+
722+
switch (__le32_to_cpu(entry->pipedir)) {
723+
case PIPEDIR_NONE:
724+
break;
725+
case PIPEDIR_IN:
726+
WARN_ON(dl_set);
727+
*dl_pipe = __le32_to_cpu(entry->pipenum);
728+
dl_set = true;
729+
break;
730+
case PIPEDIR_OUT:
731+
WARN_ON(ul_set);
732+
*ul_pipe = __le32_to_cpu(entry->pipenum);
733+
ul_set = true;
734+
break;
735+
case PIPEDIR_INOUT:
736+
WARN_ON(dl_set);
737+
WARN_ON(ul_set);
738+
*dl_pipe = __le32_to_cpu(entry->pipenum);
739+
*ul_pipe = __le32_to_cpu(entry->pipenum);
740+
dl_set = true;
741+
ul_set = true;
742+
break;
743+
}
744+
}
745+
746+
if (WARN_ON(!ul_set || !dl_set))
747+
return -ENOENT;
649748

650749
return 0;
651750
}
@@ -659,6 +758,7 @@ static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
659758
.power_up = ath11k_pci_power_up,
660759
.get_msi_address = ath11k_pci_get_msi_address,
661760
.get_user_msi_vector = ath11k_get_user_msi_assignment,
761+
.map_service_to_pipe = ath11k_pci_map_service_to_pipe,
662762
};
663763

664764
static int ath11k_pci_probe(struct pci_dev *pdev,

0 commit comments

Comments
 (0)