2
0

729-21-v6.3-net-ethernet-mtk_eth_soc-add-dma-checks-to-mtk_hw_re.patch 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. From: Lorenzo Bianconi <[email protected]>
  2. Date: Sat, 14 Jan 2023 18:01:31 +0100
  3. Subject: [PATCH] net: ethernet: mtk_eth_soc: add dma checks to
  4. mtk_hw_reset_check
  5. Introduce mtk_hw_check_dma_hang routine to monitor possible dma hangs.
  6. Reviewed-by: Leon Romanovsky <[email protected]>
  7. Tested-by: Daniel Golle <[email protected]>
  8. Co-developed-by: Sujuan Chen <[email protected]>
  9. Signed-off-by: Sujuan Chen <[email protected]>
  10. Signed-off-by: Lorenzo Bianconi <[email protected]>
  11. Signed-off-by: Paolo Abeni <[email protected]>
  12. ---
  13. --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
  14. +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
  15. @@ -50,6 +50,7 @@ static const struct mtk_reg_map mtk_reg_
  16. .delay_irq = 0x0a0c,
  17. .irq_status = 0x0a20,
  18. .irq_mask = 0x0a28,
  19. + .adma_rx_dbg0 = 0x0a38,
  20. .int_grp = 0x0a50,
  21. },
  22. .qdma = {
  23. @@ -79,6 +80,8 @@ static const struct mtk_reg_map mtk_reg_
  24. [0] = 0x2800,
  25. [1] = 0x2c00,
  26. },
  27. + .pse_iq_sta = 0x0110,
  28. + .pse_oq_sta = 0x0118,
  29. };
  30. static const struct mtk_reg_map mt7628_reg_map = {
  31. @@ -109,6 +112,7 @@ static const struct mtk_reg_map mt7986_r
  32. .delay_irq = 0x620c,
  33. .irq_status = 0x6220,
  34. .irq_mask = 0x6228,
  35. + .adma_rx_dbg0 = 0x6238,
  36. .int_grp = 0x6250,
  37. },
  38. .qdma = {
  39. @@ -138,6 +142,8 @@ static const struct mtk_reg_map mt7986_r
  40. [0] = 0x4800,
  41. [1] = 0x4c00,
  42. },
  43. + .pse_iq_sta = 0x0180,
  44. + .pse_oq_sta = 0x01a0,
  45. };
  46. /* strings used by ethtool */
  47. @@ -3285,6 +3291,102 @@ static void mtk_hw_warm_reset(struct mtk
  48. val, rst_mask);
  49. }
  50. +static bool mtk_hw_check_dma_hang(struct mtk_eth *eth)
  51. +{
  52. + const struct mtk_reg_map *reg_map = eth->soc->reg_map;
  53. + bool gmac1_tx, gmac2_tx, gdm1_tx, gdm2_tx;
  54. + bool oq_hang, cdm1_busy, adma_busy;
  55. + bool wtx_busy, cdm_full, oq_free;
  56. + u32 wdidx, val, gdm1_fc, gdm2_fc;
  57. + bool qfsm_hang, qfwd_hang;
  58. + bool ret = false;
  59. +
  60. + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
  61. + return false;
  62. +
  63. + /* WDMA sanity checks */
  64. + wdidx = mtk_r32(eth, reg_map->wdma_base[0] + 0xc);
  65. +
  66. + val = mtk_r32(eth, reg_map->wdma_base[0] + 0x204);
  67. + wtx_busy = FIELD_GET(MTK_TX_DMA_BUSY, val);
  68. +
  69. + val = mtk_r32(eth, reg_map->wdma_base[0] + 0x230);
  70. + cdm_full = !FIELD_GET(MTK_CDM_TXFIFO_RDY, val);
  71. +
  72. + oq_free = (!(mtk_r32(eth, reg_map->pse_oq_sta) & GENMASK(24, 16)) &&
  73. + !(mtk_r32(eth, reg_map->pse_oq_sta + 0x4) & GENMASK(8, 0)) &&
  74. + !(mtk_r32(eth, reg_map->pse_oq_sta + 0x10) & GENMASK(24, 16)));
  75. +
  76. + if (wdidx == eth->reset.wdidx && wtx_busy && cdm_full && oq_free) {
  77. + if (++eth->reset.wdma_hang_count > 2) {
  78. + eth->reset.wdma_hang_count = 0;
  79. + ret = true;
  80. + }
  81. + goto out;
  82. + }
  83. +
  84. + /* QDMA sanity checks */
  85. + qfsm_hang = !!mtk_r32(eth, reg_map->qdma.qtx_cfg + 0x234);
  86. + qfwd_hang = !mtk_r32(eth, reg_map->qdma.qtx_cfg + 0x308);
  87. +
  88. + gdm1_tx = FIELD_GET(GENMASK(31, 16), mtk_r32(eth, MTK_FE_GDM1_FSM)) > 0;
  89. + gdm2_tx = FIELD_GET(GENMASK(31, 16), mtk_r32(eth, MTK_FE_GDM2_FSM)) > 0;
  90. + gmac1_tx = FIELD_GET(GENMASK(31, 24), mtk_r32(eth, MTK_MAC_FSM(0))) != 1;
  91. + gmac2_tx = FIELD_GET(GENMASK(31, 24), mtk_r32(eth, MTK_MAC_FSM(1))) != 1;
  92. + gdm1_fc = mtk_r32(eth, reg_map->gdm1_cnt + 0x24);
  93. + gdm2_fc = mtk_r32(eth, reg_map->gdm1_cnt + 0x64);
  94. +
  95. + if (qfsm_hang && qfwd_hang &&
  96. + ((gdm1_tx && gmac1_tx && gdm1_fc < 1) ||
  97. + (gdm2_tx && gmac2_tx && gdm2_fc < 1))) {
  98. + if (++eth->reset.qdma_hang_count > 2) {
  99. + eth->reset.qdma_hang_count = 0;
  100. + ret = true;
  101. + }
  102. + goto out;
  103. + }
  104. +
  105. + /* ADMA sanity checks */
  106. + oq_hang = !!(mtk_r32(eth, reg_map->pse_oq_sta) & GENMASK(8, 0));
  107. + cdm1_busy = !!(mtk_r32(eth, MTK_FE_CDM1_FSM) & GENMASK(31, 16));
  108. + adma_busy = !(mtk_r32(eth, reg_map->pdma.adma_rx_dbg0) & GENMASK(4, 0)) &&
  109. + !(mtk_r32(eth, reg_map->pdma.adma_rx_dbg0) & BIT(6));
  110. +
  111. + if (oq_hang && cdm1_busy && adma_busy) {
  112. + if (++eth->reset.adma_hang_count > 2) {
  113. + eth->reset.adma_hang_count = 0;
  114. + ret = true;
  115. + }
  116. + goto out;
  117. + }
  118. +
  119. + eth->reset.wdma_hang_count = 0;
  120. + eth->reset.qdma_hang_count = 0;
  121. + eth->reset.adma_hang_count = 0;
  122. +out:
  123. + eth->reset.wdidx = wdidx;
  124. +
  125. + return ret;
  126. +}
  127. +
  128. +static void mtk_hw_reset_monitor_work(struct work_struct *work)
  129. +{
  130. + struct delayed_work *del_work = to_delayed_work(work);
  131. + struct mtk_eth *eth = container_of(del_work, struct mtk_eth,
  132. + reset.monitor_work);
  133. +
  134. + if (test_bit(MTK_RESETTING, &eth->state))
  135. + goto out;
  136. +
  137. + /* DMA stuck checks */
  138. + if (mtk_hw_check_dma_hang(eth))
  139. + schedule_work(&eth->pending_work);
  140. +
  141. +out:
  142. + schedule_delayed_work(&eth->reset.monitor_work,
  143. + MTK_DMA_MONITOR_TIMEOUT);
  144. +}
  145. +
  146. static int mtk_hw_init(struct mtk_eth *eth, bool reset)
  147. {
  148. u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA |
  149. @@ -3600,6 +3702,7 @@ static int mtk_cleanup(struct mtk_eth *e
  150. mtk_unreg_dev(eth);
  151. mtk_free_dev(eth);
  152. cancel_work_sync(&eth->pending_work);
  153. + cancel_delayed_work_sync(&eth->reset.monitor_work);
  154. return 0;
  155. }
  156. @@ -4037,6 +4140,7 @@ static int mtk_probe(struct platform_dev
  157. eth->rx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
  158. INIT_WORK(&eth->rx_dim.work, mtk_dim_rx);
  159. + INIT_DELAYED_WORK(&eth->reset.monitor_work, mtk_hw_reset_monitor_work);
  160. eth->tx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
  161. INIT_WORK(&eth->tx_dim.work, mtk_dim_tx);
  162. @@ -4241,6 +4345,8 @@ static int mtk_probe(struct platform_dev
  163. NAPI_POLL_WEIGHT);
  164. platform_set_drvdata(pdev, eth);
  165. + schedule_delayed_work(&eth->reset.monitor_work,
  166. + MTK_DMA_MONITOR_TIMEOUT);
  167. return 0;
  168. --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
  169. +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
  170. @@ -256,6 +256,8 @@
  171. #define MTK_RX_DONE_INT_V2 BIT(14)
  172. +#define MTK_CDM_TXFIFO_RDY BIT(7)
  173. +
  174. /* QDMA Interrupt grouping registers */
  175. #define MTK_RLS_DONE_INT BIT(0)
  176. @@ -538,6 +540,17 @@
  177. #define MT7628_SDM_RBCNT (MT7628_SDM_OFFSET + 0x10c)
  178. #define MT7628_SDM_CS_ERR (MT7628_SDM_OFFSET + 0x110)
  179. +#define MTK_FE_CDM1_FSM 0x220
  180. +#define MTK_FE_CDM2_FSM 0x224
  181. +#define MTK_FE_CDM3_FSM 0x238
  182. +#define MTK_FE_CDM4_FSM 0x298
  183. +#define MTK_FE_CDM5_FSM 0x318
  184. +#define MTK_FE_CDM6_FSM 0x328
  185. +#define MTK_FE_GDM1_FSM 0x228
  186. +#define MTK_FE_GDM2_FSM 0x22C
  187. +
  188. +#define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100))
  189. +
  190. struct mtk_rx_dma {
  191. unsigned int rxd1;
  192. unsigned int rxd2;
  193. @@ -934,6 +947,7 @@ struct mtk_reg_map {
  194. u32 delay_irq; /* delay interrupt */
  195. u32 irq_status; /* interrupt status */
  196. u32 irq_mask; /* interrupt mask */
  197. + u32 adma_rx_dbg0;
  198. u32 int_grp;
  199. } pdma;
  200. struct {
  201. @@ -960,6 +974,8 @@ struct mtk_reg_map {
  202. u32 gdma_to_ppe0;
  203. u32 ppe_base;
  204. u32 wdma_base[2];
  205. + u32 pse_iq_sta;
  206. + u32 pse_oq_sta;
  207. };
  208. /* struct mtk_eth_data - This is the structure holding all differences
  209. @@ -1002,6 +1018,8 @@ struct mtk_soc_data {
  210. } txrx;
  211. };
  212. +#define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000)
  213. +
  214. /* currently no SoC has more than 2 macs */
  215. #define MTK_MAX_DEVS 2
  216. @@ -1124,6 +1142,14 @@ struct mtk_eth {
  217. struct rhashtable flow_table;
  218. struct bpf_prog __rcu *prog;
  219. +
  220. + struct {
  221. + struct delayed_work monitor_work;
  222. + u32 wdidx;
  223. + u8 wdma_hang_count;
  224. + u8 qdma_hang_count;
  225. + u8 adma_hang_count;
  226. + } reset;
  227. };
  228. /* struct mtk_mac - the structure that holds the info about the MACs of the