@@ -187,6 +187,26 @@ const struct ce_attr ath11k_host_ce_config_qca6390[] = {
187187
188188};
189189
190+ static bool ath11k_ce_need_shadow_fix (int ce_id )
191+ {
192+ /* only ce4 needs shadow workaroud*/
193+ if (ce_id == 4 )
194+ return true;
195+ return false;
196+ }
197+
198+ static void ath11k_ce_stop_shadow_timers (struct ath11k_base * ab )
199+ {
200+ int i ;
201+
202+ if (!ab -> hw_params .supports_shadow_regs )
203+ return ;
204+
205+ for (i = 0 ; i < ab -> hw_params .ce_count ; i ++ )
206+ if (ath11k_ce_need_shadow_fix (i ))
207+ ath11k_dp_shadow_stop_timer (ab , & ab -> ce .hp_timer [i ]);
208+ }
209+
190210static int ath11k_ce_rx_buf_enqueue_pipe (struct ath11k_ce_pipe * pipe ,
191211 struct sk_buff * skb , dma_addr_t paddr )
192212{
@@ -505,6 +525,12 @@ static int ath11k_ce_init_ring(struct ath11k_base *ab,
505525
506526 ce_ring -> hal_ring_id = ret ;
507527
528+ if (ab -> hw_params .supports_shadow_regs &&
529+ ath11k_ce_need_shadow_fix (ce_id ))
530+ ath11k_dp_shadow_init_timer (ab , & ab -> ce .hp_timer [ce_id ],
531+ ATH11K_SHADOW_CTRL_TIMER_INTERVAL ,
532+ ce_ring -> hal_ring_id );
533+
508534 return 0 ;
509535}
510536
@@ -677,6 +703,9 @@ int ath11k_ce_send(struct ath11k_base *ab, struct sk_buff *skb, u8 pipe_id,
677703
678704 ath11k_hal_srng_access_end (ab , srng );
679705
706+ if (ath11k_ce_need_shadow_fix (pipe_id ))
707+ ath11k_dp_shadow_start_timer (ab , srng , & ab -> ce .hp_timer [pipe_id ]);
708+
680709 spin_unlock_bh (& srng -> lock );
681710
682711 spin_unlock_bh (& ab -> ce .ce_lock );
@@ -713,11 +742,56 @@ static void ath11k_ce_rx_pipe_cleanup(struct ath11k_ce_pipe *pipe)
713742 }
714743}
715744
745+ static void ath11k_ce_shadow_config (struct ath11k_base * ab )
746+ {
747+ int i ;
748+
749+ for (i = 0 ; i < ab -> hw_params .ce_count ; i ++ ) {
750+ if (ab -> hw_params .host_ce_config [i ].src_nentries )
751+ ath11k_hal_srng_update_shadow_config (ab ,
752+ HAL_CE_SRC , i );
753+
754+ if (ab -> hw_params .host_ce_config [i ].dest_nentries ) {
755+ ath11k_hal_srng_update_shadow_config (ab ,
756+ HAL_CE_DST , i );
757+
758+ ath11k_hal_srng_update_shadow_config (ab ,
759+ HAL_CE_DST_STATUS , i );
760+ }
761+ }
762+ }
763+
764+ void ath11k_ce_get_shadow_config (struct ath11k_base * ab ,
765+ u32 * * shadow_cfg , u32 * shadow_cfg_len )
766+ {
767+ if (!ab -> hw_params .supports_shadow_regs )
768+ return ;
769+
770+ ath11k_hal_srng_get_shadow_config (ab , shadow_cfg , shadow_cfg_len );
771+
772+ /* shadow is already configured */
773+ if (* shadow_cfg_len )
774+ return ;
775+
776+ /* shadow isn't configured yet, configure now.
777+ * non-CE srngs are configured firstly, then
778+ * all CE srngs.
779+ */
780+ ath11k_hal_srng_shadow_config (ab );
781+ ath11k_ce_shadow_config (ab );
782+
783+ /* get the shadow configuration */
784+ ath11k_hal_srng_get_shadow_config (ab , shadow_cfg , shadow_cfg_len );
785+ }
786+ EXPORT_SYMBOL (ath11k_ce_get_shadow_config );
787+
716788void ath11k_ce_cleanup_pipes (struct ath11k_base * ab )
717789{
718790 struct ath11k_ce_pipe * pipe ;
719791 int pipe_num ;
720792
793+ ath11k_ce_stop_shadow_timers (ab );
794+
721795 for (pipe_num = 0 ; pipe_num < ab -> hw_params .ce_count ; pipe_num ++ ) {
722796 pipe = & ab -> ce .ce_pipe [pipe_num ];
723797 ath11k_ce_rx_pipe_cleanup (pipe );
@@ -767,6 +841,9 @@ int ath11k_ce_init_pipes(struct ath11k_base *ab)
767841 int i ;
768842 int ret ;
769843
844+ ath11k_ce_get_shadow_config (ab , & ab -> qmi .ce_cfg .shadow_reg_v2 ,
845+ & ab -> qmi .ce_cfg .shadow_reg_v2_len );
846+
770847 for (i = 0 ; i < ab -> hw_params .ce_count ; i ++ ) {
771848 pipe = & ab -> ce .ce_pipe [i ];
772849
@@ -828,6 +905,9 @@ void ath11k_ce_free_pipes(struct ath11k_base *ab)
828905 for (i = 0 ; i < ab -> hw_params .ce_count ; i ++ ) {
829906 pipe = & ab -> ce .ce_pipe [i ];
830907
908+ if (ath11k_ce_need_shadow_fix (i ))
909+ ath11k_dp_shadow_stop_timer (ab , & ab -> ce .hp_timer [i ]);
910+
831911 if (pipe -> src_ring ) {
832912 desc_sz = ath11k_hal_ce_get_desc_size (HAL_CE_DESC_SRC );
833913 dma_free_coherent (ab -> dev ,
0 commit comments