@@ -4014,10 +4014,13 @@ static void mtk_hw_warm_reset(struct mtk_eth *eth)
40144014static bool mtk_hw_check_dma_hang (struct mtk_eth * eth )
40154015{
40164016 const struct mtk_reg_map * reg_map = eth -> soc -> reg_map ;
4017- bool gmac1_tx , gmac2_tx , gdm1_tx , gdm2_tx ;
4017+ bool gmac1_tx , gmac2_tx , gmac3_tx = false, gdm1_tx , gdm2_tx , gdm3_tx = false ;
40184018 bool oq_hang , cdm1_busy , adma_busy ;
40194019 bool wtx_busy , cdm_full , oq_free ;
4020- u32 wdidx , val , gdm1_fc , gdm2_fc ;
4020+ u32 wdidx , val , gdm1_fc , gdm2_fc , gdm3_fc ;
4021+ u32 tdma_glo_cfg , cur_fsm , ipq10 ;
4022+ bool rx_busy , tx_busy , cur_fsm_tx , cur_fsm_rx ;
4023+
40214024 bool qfsm_hang , qfwd_hang ;
40224025 bool ret = false;
40234026
@@ -4053,12 +4056,19 @@ static bool mtk_hw_check_dma_hang(struct mtk_eth *eth)
40534056 gdm2_tx = FIELD_GET (GENMASK (31 , 16 ), mtk_r32 (eth , MTK_FE_GDM2_FSM )) > 0 ;
40544057 gmac1_tx = FIELD_GET (GENMASK (31 , 24 ), mtk_r32 (eth , MTK_MAC_FSM (0 ))) != 1 ;
40554058 gmac2_tx = FIELD_GET (GENMASK (31 , 24 ), mtk_r32 (eth , MTK_MAC_FSM (1 ))) != 1 ;
4056- gdm1_fc = mtk_r32 (eth , reg_map -> gdm1_cnt + 0x24 );
4057- gdm2_fc = mtk_r32 (eth , reg_map -> gdm1_cnt + 0x64 );
4059+ gdm1_fc = mtk_r32 (eth , reg_map -> gdm1_cnt + MTK_GDM_RX_FC_OFFSET (eth , 0 ));
4060+ gdm2_fc = mtk_r32 (eth , reg_map -> gdm1_cnt + MTK_GDM_RX_FC_OFFSET (eth , 1 ));
4061+
4062+ if (mtk_is_netsys_v3_or_greater (eth )) {
4063+ gdm3_tx = FIELD_GET (GENMASK (31 , 16 ), mtk_r32 (eth , MTK_FE_GDM3_FSM )) > 0 ;
4064+ gmac3_tx = FIELD_GET (GENMASK (31 , 24 ), mtk_r32 (eth , MTK_MAC_FSM (2 ))) != 1 ;
4065+ gdm3_fc = mtk_r32 (eth , reg_map -> gdm1_cnt + MTK_GDM_RX_FC_OFFSET (eth , 2 ));
4066+ }
40584067
40594068 if (qfsm_hang && qfwd_hang &&
40604069 ((gdm1_tx && gmac1_tx && gdm1_fc < 1 ) ||
4061- (gdm2_tx && gmac2_tx && gdm2_fc < 1 ))) {
4070+ (gdm2_tx && gmac2_tx && gdm2_fc < 1 ) ||
4071+ (mtk_is_netsys_v3_or_greater (eth ) && gdm3_tx && gmac3_tx && gdm3_fc < 1 ))) {
40624072 if (++ eth -> reset .qdma_hang_count > 2 ) {
40634073 eth -> reset .qdma_hang_count = 0 ;
40644074 ret = true;
@@ -4080,12 +4090,47 @@ static bool mtk_hw_check_dma_hang(struct mtk_eth *eth)
40804090 goto out ;
40814091 }
40824092
4093+ if (mtk_is_netsys_v3_or_greater (eth )) {
4094+ ipq10 = mtk_r32 (eth , reg_map -> pse_iq_sta + 24 ) & GENMASK (23 , 0 );
4095+ cur_fsm = mtk_r32 (eth , MTK_FE_CDM6_FSM );
4096+ tdma_glo_cfg = mtk_r32 (eth , MTK_TDMA_GLO_CFG );
4097+ cur_fsm_rx = !(cur_fsm & GENMASK (27 , 16 ));
4098+ cur_fsm_tx = !(cur_fsm & GENMASK (24 , 0 ));
4099+ tx_busy = !(tdma_glo_cfg & BIT (1 ));
4100+ rx_busy = !(tdma_glo_cfg & BIT (3 ));
4101+
4102+ if (ipq10 && cur_fsm_tx && tx_busy &&
4103+ cur_fsm_tx == !!(eth -> reset .pre_fsm & GENMASK (24 , 0 )) &&
4104+ ipq10 == eth -> reset .pre_ipq10 ) {
4105+ if (++ eth -> reset .tdma_tx_hang_count > 2 ) {
4106+ eth -> reset .tdma_tx_hang_count = 0 ;
4107+ ret = true;
4108+ }
4109+ goto out ;
4110+ }
4111+
4112+ if (cur_fsm_rx && rx_busy &&
4113+ cur_fsm_rx == (eth -> reset .pre_fsm & GENMASK (27 , 16 ))) {
4114+ if (++ eth -> reset .tdma_rx_hang_count > 2 ) {
4115+ eth -> reset .tdma_rx_hang_count = 0 ;
4116+ ret = true;
4117+ }
4118+ goto out ;
4119+ }
4120+ }
4121+
40834122 eth -> reset .wdma_hang_count = 0 ;
40844123 eth -> reset .qdma_hang_count = 0 ;
40854124 eth -> reset .adma_hang_count = 0 ;
4125+ eth -> reset .tdma_tx_hang_count = 0 ;
4126+ eth -> reset .tdma_rx_hang_count = 0 ;
40864127out :
40874128 eth -> reset .wdidx = wdidx ;
40884129
4130+ if (mtk_is_netsys_v3_or_greater (eth )) {
4131+ eth -> reset .pre_fsm = cur_fsm ;
4132+ eth -> reset .pre_ipq10 = ipq10 ;
4133+ }
40894134 return ret ;
40904135}
40914136
0 commit comments