@@ -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+
404412static 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+
412454static 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-
482520static 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+
641693static 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
646701static 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
664764static int ath11k_pci_probe (struct pci_dev * pdev ,
0 commit comments