1de8650a8SEran Ben Elisha /* SPDX-License-Identifier: GPL-2.0 */
2de8650a8SEran Ben Elisha /* Copyright (c) 2019 Mellanox Technologies. */
3de8650a8SEran Ben Elisha 
44edc17fdSAya Levin #include "health.h"
5145e5637SEran Ben Elisha #include "en/ptp.h"
6c27971d0SRoi Dayan #include "en/devlink.h"
732def412SAmir Tzin #include "lib/tout.h"
8de8650a8SEran Ben Elisha 
9fc9d982aSAdham Faris /* Keep this string array consistent with the MLX5E_SQ_STATE_* enums in en.h */
10fc9d982aSAdham Faris static const char * const sq_sw_state_type_name[] = {
11fc9d982aSAdham Faris 	[MLX5E_SQ_STATE_ENABLED] = "enabled",
12fc9d982aSAdham Faris 	[MLX5E_SQ_STATE_MPWQE] = "mpwqe",
13fc9d982aSAdham Faris 	[MLX5E_SQ_STATE_RECOVERING] = "recovering",
14fc9d982aSAdham Faris 	[MLX5E_SQ_STATE_IPSEC] = "ipsec",
15fc9d982aSAdham Faris 	[MLX5E_SQ_STATE_DIM] = "dim",
16fc9d982aSAdham Faris 	[MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE] = "vlan_need_l2_inline",
17fc9d982aSAdham Faris 	[MLX5E_SQ_STATE_PENDING_XSK_TX] = "pending_xsk_tx",
18fc9d982aSAdham Faris 	[MLX5E_SQ_STATE_PENDING_TLS_RX_RESYNC] = "pending_tls_rx_resync",
19fc9d982aSAdham Faris 	[MLX5E_SQ_STATE_XDP_MULTIBUF] = "xdp_multibuf",
20fc9d982aSAdham Faris };
21fc9d982aSAdham Faris 
mlx5e_wait_for_sq_flush(struct mlx5e_txqsq * sq)22de8650a8SEran Ben Elisha static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq)
23de8650a8SEran Ben Elisha {
2432def412SAmir Tzin 	struct mlx5_core_dev *dev = sq->mdev;
2532def412SAmir Tzin 	unsigned long exp_time;
2632def412SAmir Tzin 
2732def412SAmir Tzin 	exp_time = jiffies + msecs_to_jiffies(mlx5_tout_ms(dev, FLUSH_ON_ERROR));
28de8650a8SEran Ben Elisha 
29de8650a8SEran Ben Elisha 	while (time_before(jiffies, exp_time)) {
30de8650a8SEran Ben Elisha 		if (sq->cc == sq->pc)
31de8650a8SEran Ben Elisha 			return 0;
32de8650a8SEran Ben Elisha 
33de8650a8SEran Ben Elisha 		msleep(20);
34de8650a8SEran Ben Elisha 	}
35de8650a8SEran Ben Elisha 
364ad40d8eSEran Ben Elisha 	netdev_err(sq->netdev,
37de8650a8SEran Ben Elisha 		   "Wait for SQ 0x%x flush timeout (sq cc = 0x%x, sq pc = 0x%x)\n",
38de8650a8SEran Ben Elisha 		   sq->sqn, sq->cc, sq->pc);
39de8650a8SEran Ben Elisha 
40de8650a8SEran Ben Elisha 	return -ETIMEDOUT;
41de8650a8SEran Ben Elisha }
42de8650a8SEran Ben Elisha 
mlx5e_reset_txqsq_cc_pc(struct mlx5e_txqsq * sq)43de8650a8SEran Ben Elisha static void mlx5e_reset_txqsq_cc_pc(struct mlx5e_txqsq *sq)
44de8650a8SEran Ben Elisha {
45de8650a8SEran Ben Elisha 	WARN_ONCE(sq->cc != sq->pc,
46de8650a8SEran Ben Elisha 		  "SQ 0x%x: cc (0x%x) != pc (0x%x)\n",
47de8650a8SEran Ben Elisha 		  sq->sqn, sq->cc, sq->pc);
48de8650a8SEran Ben Elisha 	sq->cc = 0;
49de8650a8SEran Ben Elisha 	sq->dma_fifo_cc = 0;
50de8650a8SEran Ben Elisha 	sq->pc = 0;
51de8650a8SEran Ben Elisha }
52de8650a8SEran Ben Elisha 
mlx5e_health_sq_put_sw_state(struct devlink_fmsg * fmsg,struct mlx5e_txqsq * sq)53fc9d982aSAdham Faris static int mlx5e_health_sq_put_sw_state(struct devlink_fmsg *fmsg, struct mlx5e_txqsq *sq)
54fc9d982aSAdham Faris {
55fc9d982aSAdham Faris 	int err;
56fc9d982aSAdham Faris 	int i;
57fc9d982aSAdham Faris 
58fc9d982aSAdham Faris 	BUILD_BUG_ON_MSG(ARRAY_SIZE(sq_sw_state_type_name) != MLX5E_NUM_SQ_STATES,
59fc9d982aSAdham Faris 			 "sq_sw_state_type_name string array must be consistent with MLX5E_SQ_STATE_* enum in en.h");
60fc9d982aSAdham Faris 	err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "SW State");
61fc9d982aSAdham Faris 	if (err)
62fc9d982aSAdham Faris 		return err;
63fc9d982aSAdham Faris 
64fc9d982aSAdham Faris 	for (i = 0; i < ARRAY_SIZE(sq_sw_state_type_name); ++i) {
65fc9d982aSAdham Faris 		err = devlink_fmsg_u32_pair_put(fmsg, sq_sw_state_type_name[i],
66fc9d982aSAdham Faris 						test_bit(i, &sq->state));
67fc9d982aSAdham Faris 		if (err)
68fc9d982aSAdham Faris 			return err;
69fc9d982aSAdham Faris 	}
70fc9d982aSAdham Faris 
71b0d87ed2SAdham Faris 	return mlx5e_health_fmsg_named_obj_nest_end(fmsg);
72fc9d982aSAdham Faris }
73fc9d982aSAdham Faris 
mlx5e_tx_reporter_err_cqe_recover(void * ctx)74c50de4afSAya Levin static int mlx5e_tx_reporter_err_cqe_recover(void *ctx)
75de8650a8SEran Ben Elisha {
76c50de4afSAya Levin 	struct mlx5_core_dev *mdev;
77c50de4afSAya Levin 	struct net_device *dev;
78c50de4afSAya Levin 	struct mlx5e_txqsq *sq;
79de8650a8SEran Ben Elisha 	u8 state;
80de8650a8SEran Ben Elisha 	int err;
81de8650a8SEran Ben Elisha 
82c50de4afSAya Levin 	sq = ctx;
834ad40d8eSEran Ben Elisha 	mdev = sq->mdev;
844ad40d8eSEran Ben Elisha 	dev = sq->netdev;
85c50de4afSAya Levin 
86c50de4afSAya Levin 	if (!test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state))
87c50de4afSAya Levin 		return 0;
88c50de4afSAya Levin 
89de8650a8SEran Ben Elisha 	err = mlx5_core_query_sq_state(mdev, sq->sqn, &state);
90de8650a8SEran Ben Elisha 	if (err) {
91de8650a8SEran Ben Elisha 		netdev_err(dev, "Failed to query SQ 0x%x state. err = %d\n",
92de8650a8SEran Ben Elisha 			   sq->sqn, err);
93276d197eSAya Levin 		goto out;
94de8650a8SEran Ben Elisha 	}
95de8650a8SEran Ben Elisha 
96d9a2fcf5SAya Levin 	if (state != MLX5_SQC_STATE_ERR)
97276d197eSAya Levin 		goto out;
98de8650a8SEran Ben Elisha 
99de8650a8SEran Ben Elisha 	mlx5e_tx_disable_queue(sq->txq);
100de8650a8SEran Ben Elisha 
101de8650a8SEran Ben Elisha 	err = mlx5e_wait_for_sq_flush(sq);
102de8650a8SEran Ben Elisha 	if (err)
103276d197eSAya Levin 		goto out;
104de8650a8SEran Ben Elisha 
105de8650a8SEran Ben Elisha 	/* At this point, no new packets will arrive from the stack as TXQ is
106de8650a8SEran Ben Elisha 	 * marked with QUEUE_STATE_DRV_XOFF. In addition, NAPI cleared all
107de8650a8SEran Ben Elisha 	 * pending WQEs. SQ can safely reset the SQ.
108de8650a8SEran Ben Elisha 	 */
109de8650a8SEran Ben Elisha 
1104ad40d8eSEran Ben Elisha 	err = mlx5e_health_sq_to_ready(mdev, dev, sq->sqn);
111de8650a8SEran Ben Elisha 	if (err)
112276d197eSAya Levin 		goto out;
113de8650a8SEran Ben Elisha 
114de8650a8SEran Ben Elisha 	mlx5e_reset_txqsq_cc_pc(sq);
115de8650a8SEran Ben Elisha 	sq->stats->recover++;
116276d197eSAya Levin 	clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
117de8650a8SEran Ben Elisha 	mlx5e_activate_txqsq(sq);
11879efecb4SMaxim Mikityanskiy 	if (sq->channel)
11979efecb4SMaxim Mikityanskiy 		mlx5e_trigger_napi_icosq(sq->channel);
12079efecb4SMaxim Mikityanskiy 	else
12179efecb4SMaxim Mikityanskiy 		mlx5e_trigger_napi_sched(sq->cq.napi);
122de8650a8SEran Ben Elisha 
123de8650a8SEran Ben Elisha 	return 0;
124276d197eSAya Levin out:
125276d197eSAya Levin 	clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
126276d197eSAya Levin 	return err;
127de8650a8SEran Ben Elisha }
128de8650a8SEran Ben Elisha 
129e6205564SAya Levin struct mlx5e_tx_timeout_ctx {
130e6205564SAya Levin 	struct mlx5e_txqsq *sq;
131e6205564SAya Levin 	signed int status;
132e6205564SAya Levin };
133e6205564SAya Levin 
mlx5e_tx_reporter_timeout_recover(void * ctx)134c50de4afSAya Levin static int mlx5e_tx_reporter_timeout_recover(void *ctx)
1357d91126bSEran Ben Elisha {
136e6205564SAya Levin 	struct mlx5e_tx_timeout_ctx *to_ctx;
137e6205564SAya Levin 	struct mlx5e_priv *priv;
138c50de4afSAya Levin 	struct mlx5_eq_comp *eq;
139c50de4afSAya Levin 	struct mlx5e_txqsq *sq;
140c50de4afSAya Levin 	int err;
1417d91126bSEran Ben Elisha 
142e6205564SAya Levin 	to_ctx = ctx;
143e6205564SAya Levin 	sq = to_ctx->sq;
144c50de4afSAya Levin 	eq = sq->cq.mcq.eq;
1454ad40d8eSEran Ben Elisha 	priv = sq->priv;
1464ad40d8eSEran Ben Elisha 	err = mlx5e_health_channel_eq_recover(sq->netdev, eq, sq->cq.ch_stats);
147e6205564SAya Levin 	if (!err) {
148e6205564SAya Levin 		to_ctx->status = 0; /* this sq recovered */
149e6205564SAya Levin 		return err;
150e6205564SAya Levin 	}
151e6205564SAya Levin 
152e6205564SAya Levin 	err = mlx5e_safe_reopen_channels(priv);
153e6205564SAya Levin 	if (!err) {
154e6205564SAya Levin 		to_ctx->status = 1; /* all channels recovered */
155e6205564SAya Levin 		return err;
156e6205564SAya Levin 	}
157e6205564SAya Levin 
158e6205564SAya Levin 	to_ctx->status = err;
1597d91126bSEran Ben Elisha 	clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
160e6205564SAya Levin 	netdev_err(priv->netdev,
161e6205564SAya Levin 		   "mlx5e_safe_reopen_channels failed recovering from a tx_timeout, err(%d).\n",
162e6205564SAya Levin 		   err);
1637d91126bSEran Ben Elisha 
164c50de4afSAya Levin 	return err;
1657d91126bSEran Ben Elisha }
1667d91126bSEran Ben Elisha 
mlx5e_tx_reporter_ptpsq_unhealthy_recover(void * ctx)167*53b836a4SRahul Rameshbabu static int mlx5e_tx_reporter_ptpsq_unhealthy_recover(void *ctx)
168*53b836a4SRahul Rameshbabu {
169*53b836a4SRahul Rameshbabu 	struct mlx5e_ptpsq *ptpsq = ctx;
170*53b836a4SRahul Rameshbabu 	struct mlx5e_channels *chs;
171*53b836a4SRahul Rameshbabu 	struct net_device *netdev;
172*53b836a4SRahul Rameshbabu 	struct mlx5e_priv *priv;
173*53b836a4SRahul Rameshbabu 	int carrier_ok;
174*53b836a4SRahul Rameshbabu 	int err;
175*53b836a4SRahul Rameshbabu 
176*53b836a4SRahul Rameshbabu 	if (!test_bit(MLX5E_SQ_STATE_RECOVERING, &ptpsq->txqsq.state))
177*53b836a4SRahul Rameshbabu 		return 0;
178*53b836a4SRahul Rameshbabu 
179*53b836a4SRahul Rameshbabu 	priv = ptpsq->txqsq.priv;
180*53b836a4SRahul Rameshbabu 
181*53b836a4SRahul Rameshbabu 	mutex_lock(&priv->state_lock);
182*53b836a4SRahul Rameshbabu 	chs = &priv->channels;
183*53b836a4SRahul Rameshbabu 	netdev = priv->netdev;
184*53b836a4SRahul Rameshbabu 
185*53b836a4SRahul Rameshbabu 	carrier_ok = netif_carrier_ok(netdev);
186*53b836a4SRahul Rameshbabu 	netif_carrier_off(netdev);
187*53b836a4SRahul Rameshbabu 
188*53b836a4SRahul Rameshbabu 	mlx5e_deactivate_priv_channels(priv);
189*53b836a4SRahul Rameshbabu 
190*53b836a4SRahul Rameshbabu 	mlx5e_ptp_close(chs->ptp);
191*53b836a4SRahul Rameshbabu 	err = mlx5e_ptp_open(priv, &chs->params, chs->c[0]->lag_port, &chs->ptp);
192*53b836a4SRahul Rameshbabu 
193*53b836a4SRahul Rameshbabu 	mlx5e_activate_priv_channels(priv);
194*53b836a4SRahul Rameshbabu 
195*53b836a4SRahul Rameshbabu 	/* return carrier back if needed */
196*53b836a4SRahul Rameshbabu 	if (carrier_ok)
197*53b836a4SRahul Rameshbabu 		netif_carrier_on(netdev);
198*53b836a4SRahul Rameshbabu 
199*53b836a4SRahul Rameshbabu 	mutex_unlock(&priv->state_lock);
200*53b836a4SRahul Rameshbabu 
201*53b836a4SRahul Rameshbabu 	return err;
202*53b836a4SRahul Rameshbabu }
203*53b836a4SRahul Rameshbabu 
204de8650a8SEran Ben Elisha /* state lock cannot be grabbed within this function.
205de8650a8SEran Ben Elisha  * It can cause a dead lock or a read-after-free.
206de8650a8SEran Ben Elisha  */
mlx5e_tx_reporter_recover_from_ctx(struct mlx5e_err_ctx * err_ctx)207c50de4afSAya Levin static int mlx5e_tx_reporter_recover_from_ctx(struct mlx5e_err_ctx *err_ctx)
208de8650a8SEran Ben Elisha {
209c50de4afSAya Levin 	return err_ctx->recover(err_ctx->ctx);
210de8650a8SEran Ben Elisha }
211de8650a8SEran Ben Elisha 
mlx5e_tx_reporter_recover(struct devlink_health_reporter * reporter,void * context,struct netlink_ext_ack * extack)212de8650a8SEran Ben Elisha static int mlx5e_tx_reporter_recover(struct devlink_health_reporter *reporter,
213e7a98105SJiri Pirko 				     void *context,
214e7a98105SJiri Pirko 				     struct netlink_ext_ack *extack)
215de8650a8SEran Ben Elisha {
216de8650a8SEran Ben Elisha 	struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
217c50de4afSAya Levin 	struct mlx5e_err_ctx *err_ctx = context;
218de8650a8SEran Ben Elisha 
219de8650a8SEran Ben Elisha 	return err_ctx ? mlx5e_tx_reporter_recover_from_ctx(err_ctx) :
220c50de4afSAya Levin 			 mlx5e_health_recover_channels(priv);
221de8650a8SEran Ben Elisha }
222de8650a8SEran Ben Elisha 
223de8650a8SEran Ben Elisha static int
mlx5e_tx_reporter_build_diagnose_output_sq_common(struct devlink_fmsg * fmsg,struct mlx5e_txqsq * sq,int tc)224145e5637SEran Ben Elisha mlx5e_tx_reporter_build_diagnose_output_sq_common(struct devlink_fmsg *fmsg,
2252d708887SAya Levin 						  struct mlx5e_txqsq *sq, int tc)
226de8650a8SEran Ben Elisha {
227dd921fd2SAya Levin 	bool stopped = netif_xmit_stopped(sq->txq);
2284ad40d8eSEran Ben Elisha 	struct mlx5e_priv *priv = sq->priv;
229dd921fd2SAya Levin 	u8 state;
230de8650a8SEran Ben Elisha 	int err;
231de8650a8SEran Ben Elisha 
232dd921fd2SAya Levin 	err = mlx5_core_query_sq_state(priv->mdev, sq->sqn, &state);
233dd921fd2SAya Levin 	if (err)
234dd921fd2SAya Levin 		return err;
235dd921fd2SAya Levin 
2362d708887SAya Levin 	err = devlink_fmsg_u32_pair_put(fmsg, "tc", tc);
2372d708887SAya Levin 	if (err)
2382d708887SAya Levin 		return err;
2392d708887SAya Levin 
2402d708887SAya Levin 	err = devlink_fmsg_u32_pair_put(fmsg, "txq ix", sq->txq_ix);
2412d708887SAya Levin 	if (err)
2422d708887SAya Levin 		return err;
2432d708887SAya Levin 
244dd921fd2SAya Levin 	err = devlink_fmsg_u32_pair_put(fmsg, "sqn", sq->sqn);
245de8650a8SEran Ben Elisha 	if (err)
246de8650a8SEran Ben Elisha 		return err;
247de8650a8SEran Ben Elisha 
248de8650a8SEran Ben Elisha 	err = devlink_fmsg_u8_pair_put(fmsg, "HW state", state);
249de8650a8SEran Ben Elisha 	if (err)
250de8650a8SEran Ben Elisha 		return err;
251de8650a8SEran Ben Elisha 
252de8650a8SEran Ben Elisha 	err = devlink_fmsg_bool_pair_put(fmsg, "stopped", stopped);
253de8650a8SEran Ben Elisha 	if (err)
254de8650a8SEran Ben Elisha 		return err;
255de8650a8SEran Ben Elisha 
2562d708887SAya Levin 	err = devlink_fmsg_u32_pair_put(fmsg, "cc", sq->cc);
2572d708887SAya Levin 	if (err)
2582d708887SAya Levin 		return err;
2592d708887SAya Levin 
2602d708887SAya Levin 	err = devlink_fmsg_u32_pair_put(fmsg, "pc", sq->pc);
2612d708887SAya Levin 	if (err)
2622d708887SAya Levin 		return err;
2632d708887SAya Levin 
264fc9d982aSAdham Faris 	err = mlx5e_health_sq_put_sw_state(fmsg, sq);
265fc9d982aSAdham Faris 	if (err)
266fc9d982aSAdham Faris 		return err;
267fc9d982aSAdham Faris 
268d5cbedd7SAya Levin 	err = mlx5e_health_cq_diag_fmsg(&sq->cq, fmsg);
2692bf09e60SAya Levin 	if (err)
2702bf09e60SAya Levin 		return err;
2712bf09e60SAya Levin 
272145e5637SEran Ben Elisha 	return mlx5e_health_eq_diag_fmsg(sq->cq.mcq.eq, fmsg);
273145e5637SEran Ben Elisha }
274145e5637SEran Ben Elisha 
275145e5637SEran Ben Elisha static int
mlx5e_tx_reporter_build_diagnose_output(struct devlink_fmsg * fmsg,struct mlx5e_txqsq * sq,int tc)276145e5637SEran Ben Elisha mlx5e_tx_reporter_build_diagnose_output(struct devlink_fmsg *fmsg,
277145e5637SEran Ben Elisha 					struct mlx5e_txqsq *sq, int tc)
278145e5637SEran Ben Elisha {
279145e5637SEran Ben Elisha 	int err;
280145e5637SEran Ben Elisha 
281145e5637SEran Ben Elisha 	err = devlink_fmsg_obj_nest_start(fmsg);
282145e5637SEran Ben Elisha 	if (err)
283145e5637SEran Ben Elisha 		return err;
284145e5637SEran Ben Elisha 
285145e5637SEran Ben Elisha 	err = devlink_fmsg_u32_pair_put(fmsg, "channel ix", sq->ch_ix);
286145e5637SEran Ben Elisha 	if (err)
287145e5637SEran Ben Elisha 		return err;
288145e5637SEran Ben Elisha 
289145e5637SEran Ben Elisha 	err = mlx5e_tx_reporter_build_diagnose_output_sq_common(fmsg, sq, tc);
29056837c2aSAya Levin 	if (err)
29156837c2aSAya Levin 		return err;
29256837c2aSAya Levin 
293de8650a8SEran Ben Elisha 	err = devlink_fmsg_obj_nest_end(fmsg);
294de8650a8SEran Ben Elisha 	if (err)
295de8650a8SEran Ben Elisha 		return err;
296de8650a8SEran Ben Elisha 
297de8650a8SEran Ben Elisha 	return 0;
298de8650a8SEran Ben Elisha }
299de8650a8SEran Ben Elisha 
300145e5637SEran Ben Elisha static int
mlx5e_tx_reporter_build_diagnose_output_ptpsq(struct devlink_fmsg * fmsg,struct mlx5e_ptpsq * ptpsq,int tc)301145e5637SEran Ben Elisha mlx5e_tx_reporter_build_diagnose_output_ptpsq(struct devlink_fmsg *fmsg,
302145e5637SEran Ben Elisha 					      struct mlx5e_ptpsq *ptpsq, int tc)
303145e5637SEran Ben Elisha {
304145e5637SEran Ben Elisha 	int err;
305145e5637SEran Ben Elisha 
306145e5637SEran Ben Elisha 	err = devlink_fmsg_obj_nest_start(fmsg);
307145e5637SEran Ben Elisha 	if (err)
308145e5637SEran Ben Elisha 		return err;
309145e5637SEran Ben Elisha 
310145e5637SEran Ben Elisha 	err = devlink_fmsg_string_pair_put(fmsg, "channel", "ptp");
311145e5637SEran Ben Elisha 	if (err)
312145e5637SEran Ben Elisha 		return err;
313145e5637SEran Ben Elisha 
3141880bc4eSEran Ben Elisha 	err = mlx5e_tx_reporter_build_diagnose_output_sq_common(fmsg, &ptpsq->txqsq, tc);
3151880bc4eSEran Ben Elisha 	if (err)
3161880bc4eSEran Ben Elisha 		return err;
3171880bc4eSEran Ben Elisha 
3181880bc4eSEran Ben Elisha 	err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "Port TS");
3191880bc4eSEran Ben Elisha 	if (err)
3201880bc4eSEran Ben Elisha 		return err;
3211880bc4eSEran Ben Elisha 
3221880bc4eSEran Ben Elisha 	err = mlx5e_health_cq_diag_fmsg(&ptpsq->ts_cq, fmsg);
3231880bc4eSEran Ben Elisha 	if (err)
3241880bc4eSEran Ben Elisha 		return err;
3251880bc4eSEran Ben Elisha 
3261880bc4eSEran Ben Elisha 	err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
327145e5637SEran Ben Elisha 	if (err)
328145e5637SEran Ben Elisha 		return err;
329145e5637SEran Ben Elisha 
330145e5637SEran Ben Elisha 	err = devlink_fmsg_obj_nest_end(fmsg);
331145e5637SEran Ben Elisha 	if (err)
332145e5637SEran Ben Elisha 		return err;
333145e5637SEran Ben Elisha 
334145e5637SEran Ben Elisha 	return 0;
335145e5637SEran Ben Elisha }
336145e5637SEran Ben Elisha 
337145e5637SEran Ben Elisha static int
mlx5e_tx_reporter_diagnose_generic_txqsq(struct devlink_fmsg * fmsg,struct mlx5e_txqsq * txqsq)338145e5637SEran Ben Elisha mlx5e_tx_reporter_diagnose_generic_txqsq(struct devlink_fmsg *fmsg,
339145e5637SEran Ben Elisha 					 struct mlx5e_txqsq *txqsq)
340145e5637SEran Ben Elisha {
341145e5637SEran Ben Elisha 	u32 sq_stride, sq_sz;
34295742c1cSAya Levin 	bool real_time;
343145e5637SEran Ben Elisha 	int err;
344145e5637SEran Ben Elisha 
345145e5637SEran Ben Elisha 	err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "SQ");
346145e5637SEran Ben Elisha 	if (err)
347145e5637SEran Ben Elisha 		return err;
348145e5637SEran Ben Elisha 
34995742c1cSAya Levin 	real_time =  mlx5_is_real_time_sq(txqsq->mdev);
350145e5637SEran Ben Elisha 	sq_sz = mlx5_wq_cyc_get_size(&txqsq->wq);
351145e5637SEran Ben Elisha 	sq_stride = MLX5_SEND_WQE_BB;
352145e5637SEran Ben Elisha 
353145e5637SEran Ben Elisha 	err = devlink_fmsg_u64_pair_put(fmsg, "stride size", sq_stride);
354145e5637SEran Ben Elisha 	if (err)
355145e5637SEran Ben Elisha 		return err;
356145e5637SEran Ben Elisha 
357145e5637SEran Ben Elisha 	err = devlink_fmsg_u32_pair_put(fmsg, "size", sq_sz);
358145e5637SEran Ben Elisha 	if (err)
359145e5637SEran Ben Elisha 		return err;
360145e5637SEran Ben Elisha 
36195742c1cSAya Levin 	err = devlink_fmsg_string_pair_put(fmsg, "ts_format", real_time ? "RT" : "FRC");
36295742c1cSAya Levin 	if (err)
36395742c1cSAya Levin 		return err;
36495742c1cSAya Levin 
365145e5637SEran Ben Elisha 	err = mlx5e_health_cq_common_diag_fmsg(&txqsq->cq, fmsg);
366145e5637SEran Ben Elisha 	if (err)
367145e5637SEran Ben Elisha 		return err;
368145e5637SEran Ben Elisha 
369145e5637SEran Ben Elisha 	return mlx5e_health_fmsg_named_obj_nest_end(fmsg);
370145e5637SEran Ben Elisha }
371145e5637SEran Ben Elisha 
372145e5637SEran Ben Elisha static int
mlx5e_tx_reporter_diagnose_generic_tx_port_ts(struct devlink_fmsg * fmsg,struct mlx5e_ptpsq * ptpsq)3731880bc4eSEran Ben Elisha mlx5e_tx_reporter_diagnose_generic_tx_port_ts(struct devlink_fmsg *fmsg,
3741880bc4eSEran Ben Elisha 					      struct mlx5e_ptpsq *ptpsq)
3751880bc4eSEran Ben Elisha {
3761880bc4eSEran Ben Elisha 	int err;
3771880bc4eSEran Ben Elisha 
3781880bc4eSEran Ben Elisha 	err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "Port TS");
3791880bc4eSEran Ben Elisha 	if (err)
3801880bc4eSEran Ben Elisha 		return err;
3811880bc4eSEran Ben Elisha 
3821880bc4eSEran Ben Elisha 	err = mlx5e_health_cq_common_diag_fmsg(&ptpsq->ts_cq, fmsg);
3831880bc4eSEran Ben Elisha 	if (err)
3841880bc4eSEran Ben Elisha 		return err;
3851880bc4eSEran Ben Elisha 
3861880bc4eSEran Ben Elisha 	return mlx5e_health_fmsg_named_obj_nest_end(fmsg);
3871880bc4eSEran Ben Elisha }
3881880bc4eSEran Ben Elisha 
3891880bc4eSEran Ben Elisha static int
mlx5e_tx_reporter_diagnose_common_config(struct devlink_health_reporter * reporter,struct devlink_fmsg * fmsg)390145e5637SEran Ben Elisha mlx5e_tx_reporter_diagnose_common_config(struct devlink_health_reporter *reporter,
391145e5637SEran Ben Elisha 					 struct devlink_fmsg *fmsg)
392145e5637SEran Ben Elisha {
393145e5637SEran Ben Elisha 	struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
394145e5637SEran Ben Elisha 	struct mlx5e_txqsq *generic_sq = priv->txq2sq[0];
39524c22dd0SAya Levin 	struct mlx5e_ptp *ptp_ch = priv->channels.ptp;
396145e5637SEran Ben Elisha 	struct mlx5e_ptpsq *generic_ptpsq;
397145e5637SEran Ben Elisha 	int err;
398145e5637SEran Ben Elisha 
399145e5637SEran Ben Elisha 	err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "Common Config");
400145e5637SEran Ben Elisha 	if (err)
401145e5637SEran Ben Elisha 		return err;
402145e5637SEran Ben Elisha 
403145e5637SEran Ben Elisha 	err = mlx5e_tx_reporter_diagnose_generic_txqsq(fmsg, generic_sq);
404145e5637SEran Ben Elisha 	if (err)
405145e5637SEran Ben Elisha 		return err;
406145e5637SEran Ben Elisha 
40724c22dd0SAya Levin 	if (!ptp_ch || !test_bit(MLX5E_PTP_STATE_TX, ptp_ch->state))
408145e5637SEran Ben Elisha 		goto out;
409145e5637SEran Ben Elisha 
41024c22dd0SAya Levin 	generic_ptpsq = &ptp_ch->ptpsq[0];
41124c22dd0SAya Levin 
412145e5637SEran Ben Elisha 	err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "PTP");
413145e5637SEran Ben Elisha 	if (err)
414145e5637SEran Ben Elisha 		return err;
415145e5637SEran Ben Elisha 
416145e5637SEran Ben Elisha 	err = mlx5e_tx_reporter_diagnose_generic_txqsq(fmsg, &generic_ptpsq->txqsq);
417145e5637SEran Ben Elisha 	if (err)
418145e5637SEran Ben Elisha 		return err;
419145e5637SEran Ben Elisha 
4201880bc4eSEran Ben Elisha 	err = mlx5e_tx_reporter_diagnose_generic_tx_port_ts(fmsg, generic_ptpsq);
4211880bc4eSEran Ben Elisha 	if (err)
4221880bc4eSEran Ben Elisha 		return err;
4231880bc4eSEran Ben Elisha 
424145e5637SEran Ben Elisha 	err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
425145e5637SEran Ben Elisha 	if (err)
426145e5637SEran Ben Elisha 		return err;
427145e5637SEran Ben Elisha 
428145e5637SEran Ben Elisha out:
429145e5637SEran Ben Elisha 	return mlx5e_health_fmsg_named_obj_nest_end(fmsg);
430145e5637SEran Ben Elisha }
431145e5637SEran Ben Elisha 
mlx5e_tx_reporter_diagnose(struct devlink_health_reporter * reporter,struct devlink_fmsg * fmsg,struct netlink_ext_ack * extack)432de8650a8SEran Ben Elisha static int mlx5e_tx_reporter_diagnose(struct devlink_health_reporter *reporter,
433e7a98105SJiri Pirko 				      struct devlink_fmsg *fmsg,
434e7a98105SJiri Pirko 				      struct netlink_ext_ack *extack)
435de8650a8SEran Ben Elisha {
436de8650a8SEran Ben Elisha 	struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
437b0d35de4SAya Levin 	struct mlx5e_ptp *ptp_ch = priv->channels.ptp;
4382d708887SAya Levin 
4392d708887SAya Levin 	int i, tc, err = 0;
440de8650a8SEran Ben Elisha 
441de8650a8SEran Ben Elisha 	mutex_lock(&priv->state_lock);
442de8650a8SEran Ben Elisha 
443de8650a8SEran Ben Elisha 	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
444de8650a8SEran Ben Elisha 		goto unlock;
445de8650a8SEran Ben Elisha 
446145e5637SEran Ben Elisha 	err = mlx5e_tx_reporter_diagnose_common_config(reporter, fmsg);
4472d708887SAya Levin 	if (err)
4482d708887SAya Levin 		goto unlock;
4492d708887SAya Levin 
450de8650a8SEran Ben Elisha 	err = devlink_fmsg_arr_pair_nest_start(fmsg, "SQs");
451de8650a8SEran Ben Elisha 	if (err)
452de8650a8SEran Ben Elisha 		goto unlock;
453de8650a8SEran Ben Elisha 
4542d708887SAya Levin 	for (i = 0; i < priv->channels.num; i++) {
4552d708887SAya Levin 		struct mlx5e_channel *c = priv->channels.c[i];
456de8650a8SEran Ben Elisha 
45786d747a3STariq Toukan 		for (tc = 0; tc < mlx5e_get_dcb_num_tc(&priv->channels.params); tc++) {
4582d708887SAya Levin 			struct mlx5e_txqsq *sq = &c->sq[tc];
4592d708887SAya Levin 
4602d708887SAya Levin 			err = mlx5e_tx_reporter_build_diagnose_output(fmsg, sq, tc);
461de8650a8SEran Ben Elisha 			if (err)
46299d31cbdSAya Levin 				goto unlock;
463de8650a8SEran Ben Elisha 		}
4642d708887SAya Levin 	}
465145e5637SEran Ben Elisha 
46624c22dd0SAya Levin 	if (!ptp_ch || !test_bit(MLX5E_PTP_STATE_TX, ptp_ch->state))
467145e5637SEran Ben Elisha 		goto close_sqs_nest;
468145e5637SEran Ben Elisha 
46986d747a3STariq Toukan 	for (tc = 0; tc < mlx5e_get_dcb_num_tc(&priv->channels.params); tc++) {
470145e5637SEran Ben Elisha 		err = mlx5e_tx_reporter_build_diagnose_output_ptpsq(fmsg,
471145e5637SEran Ben Elisha 								    &ptp_ch->ptpsq[tc],
472145e5637SEran Ben Elisha 								    tc);
473145e5637SEran Ben Elisha 		if (err)
474145e5637SEran Ben Elisha 			goto unlock;
475145e5637SEran Ben Elisha 	}
476145e5637SEran Ben Elisha 
477145e5637SEran Ben Elisha close_sqs_nest:
478de8650a8SEran Ben Elisha 	err = devlink_fmsg_arr_pair_nest_end(fmsg);
479de8650a8SEran Ben Elisha 	if (err)
480de8650a8SEran Ben Elisha 		goto unlock;
481de8650a8SEran Ben Elisha 
482de8650a8SEran Ben Elisha unlock:
483de8650a8SEran Ben Elisha 	mutex_unlock(&priv->state_lock);
484de8650a8SEran Ben Elisha 	return err;
485de8650a8SEran Ben Elisha }
486de8650a8SEran Ben Elisha 
mlx5e_tx_reporter_dump_sq(struct mlx5e_priv * priv,struct devlink_fmsg * fmsg,void * ctx)4875f29458bSAya Levin static int mlx5e_tx_reporter_dump_sq(struct mlx5e_priv *priv, struct devlink_fmsg *fmsg,
4885f29458bSAya Levin 				     void *ctx)
4895f29458bSAya Levin {
4905f29458bSAya Levin 	struct mlx5_rsc_key key = {};
4915f29458bSAya Levin 	struct mlx5e_txqsq *sq = ctx;
4925f29458bSAya Levin 	int err;
4935f29458bSAya Levin 
4945f29458bSAya Levin 	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
4955f29458bSAya Levin 		return 0;
4965f29458bSAya Levin 
497d5cbedd7SAya Levin 	err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "SX Slice");
4985f29458bSAya Levin 	if (err)
4995f29458bSAya Levin 		return err;
5005f29458bSAya Levin 
5015f29458bSAya Levin 	key.size = PAGE_SIZE;
5025f29458bSAya Levin 	key.rsc = MLX5_SGMT_TYPE_SX_SLICE_ALL;
5035f29458bSAya Levin 	err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg);
5045f29458bSAya Levin 	if (err)
5055f29458bSAya Levin 		return err;
5065f29458bSAya Levin 
507d5cbedd7SAya Levin 	err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
5085f29458bSAya Levin 	if (err)
5095f29458bSAya Levin 		return err;
5105f29458bSAya Levin 
511d5cbedd7SAya Levin 	err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "SQ");
5125f29458bSAya Levin 	if (err)
5135f29458bSAya Levin 		return err;
5145f29458bSAya Levin 
515d5cbedd7SAya Levin 	err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "QPC");
5165f29458bSAya Levin 	if (err)
5175f29458bSAya Levin 		return err;
5185f29458bSAya Levin 
5195f29458bSAya Levin 	key.rsc = MLX5_SGMT_TYPE_FULL_QPC;
5205f29458bSAya Levin 	key.index1 = sq->sqn;
5215f29458bSAya Levin 	key.num_of_obj1 = 1;
5225f29458bSAya Levin 
5235f29458bSAya Levin 	err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg);
5245f29458bSAya Levin 	if (err)
5255f29458bSAya Levin 		return err;
5265f29458bSAya Levin 
527d5cbedd7SAya Levin 	err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
5285f29458bSAya Levin 	if (err)
5295f29458bSAya Levin 		return err;
5305f29458bSAya Levin 
531d5cbedd7SAya Levin 	err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "send_buff");
5325f29458bSAya Levin 	if (err)
5335f29458bSAya Levin 		return err;
5345f29458bSAya Levin 
5355f29458bSAya Levin 	key.rsc = MLX5_SGMT_TYPE_SND_BUFF;
5365f29458bSAya Levin 	key.num_of_obj2 = MLX5_RSC_DUMP_ALL;
5375f29458bSAya Levin 	err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg);
5385f29458bSAya Levin 	if (err)
5395f29458bSAya Levin 		return err;
5405f29458bSAya Levin 
541d5cbedd7SAya Levin 	err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
5425f29458bSAya Levin 	if (err)
5435f29458bSAya Levin 		return err;
5445f29458bSAya Levin 
545d5cbedd7SAya Levin 	return mlx5e_health_fmsg_named_obj_nest_end(fmsg);
5465f29458bSAya Levin }
5475f29458bSAya Levin 
mlx5e_tx_reporter_timeout_dump(struct mlx5e_priv * priv,struct devlink_fmsg * fmsg,void * ctx)548918fc385SAmir Tzin static int mlx5e_tx_reporter_timeout_dump(struct mlx5e_priv *priv, struct devlink_fmsg *fmsg,
549918fc385SAmir Tzin 					  void *ctx)
550918fc385SAmir Tzin {
551918fc385SAmir Tzin 	struct mlx5e_tx_timeout_ctx *to_ctx = ctx;
552918fc385SAmir Tzin 
553918fc385SAmir Tzin 	return mlx5e_tx_reporter_dump_sq(priv, fmsg, to_ctx->sq);
554918fc385SAmir Tzin }
555918fc385SAmir Tzin 
mlx5e_tx_reporter_ptpsq_unhealthy_dump(struct mlx5e_priv * priv,struct devlink_fmsg * fmsg,void * ctx)556*53b836a4SRahul Rameshbabu static int mlx5e_tx_reporter_ptpsq_unhealthy_dump(struct mlx5e_priv *priv,
557*53b836a4SRahul Rameshbabu 						  struct devlink_fmsg *fmsg,
558*53b836a4SRahul Rameshbabu 						  void *ctx)
559*53b836a4SRahul Rameshbabu {
560*53b836a4SRahul Rameshbabu 	struct mlx5e_ptpsq *ptpsq = ctx;
561*53b836a4SRahul Rameshbabu 
562*53b836a4SRahul Rameshbabu 	return mlx5e_tx_reporter_dump_sq(priv, fmsg, &ptpsq->txqsq);
563*53b836a4SRahul Rameshbabu }
564*53b836a4SRahul Rameshbabu 
mlx5e_tx_reporter_dump_all_sqs(struct mlx5e_priv * priv,struct devlink_fmsg * fmsg)5655f29458bSAya Levin static int mlx5e_tx_reporter_dump_all_sqs(struct mlx5e_priv *priv,
5665f29458bSAya Levin 					  struct devlink_fmsg *fmsg)
5675f29458bSAya Levin {
568b0d35de4SAya Levin 	struct mlx5e_ptp *ptp_ch = priv->channels.ptp;
5695f29458bSAya Levin 	struct mlx5_rsc_key key = {};
5705f29458bSAya Levin 	int i, tc, err;
5715f29458bSAya Levin 
5725f29458bSAya Levin 	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
5735f29458bSAya Levin 		return 0;
5745f29458bSAya Levin 
575d5cbedd7SAya Levin 	err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "SX Slice");
5765f29458bSAya Levin 	if (err)
5775f29458bSAya Levin 		return err;
5785f29458bSAya Levin 
5795f29458bSAya Levin 	key.size = PAGE_SIZE;
5805f29458bSAya Levin 	key.rsc = MLX5_SGMT_TYPE_SX_SLICE_ALL;
5815f29458bSAya Levin 	err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg);
5825f29458bSAya Levin 	if (err)
5835f29458bSAya Levin 		return err;
5845f29458bSAya Levin 
585d5cbedd7SAya Levin 	err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
5865f29458bSAya Levin 	if (err)
5875f29458bSAya Levin 		return err;
5885f29458bSAya Levin 
5895f29458bSAya Levin 	err = devlink_fmsg_arr_pair_nest_start(fmsg, "SQs");
5905f29458bSAya Levin 	if (err)
5915f29458bSAya Levin 		return err;
5925f29458bSAya Levin 
5935f29458bSAya Levin 	for (i = 0; i < priv->channels.num; i++) {
5945f29458bSAya Levin 		struct mlx5e_channel *c = priv->channels.c[i];
5955f29458bSAya Levin 
59686d747a3STariq Toukan 		for (tc = 0; tc < mlx5e_get_dcb_num_tc(&priv->channels.params); tc++) {
5975f29458bSAya Levin 			struct mlx5e_txqsq *sq = &c->sq[tc];
5985f29458bSAya Levin 
5995f29458bSAya Levin 			err = mlx5e_health_queue_dump(priv, fmsg, sq->sqn, "SQ");
6005f29458bSAya Levin 			if (err)
6015f29458bSAya Levin 				return err;
6025f29458bSAya Levin 		}
6035f29458bSAya Levin 	}
604145e5637SEran Ben Elisha 
60524c22dd0SAya Levin 	if (ptp_ch && test_bit(MLX5E_PTP_STATE_TX, ptp_ch->state)) {
60686d747a3STariq Toukan 		for (tc = 0; tc < mlx5e_get_dcb_num_tc(&priv->channels.params); tc++) {
607145e5637SEran Ben Elisha 			struct mlx5e_txqsq *sq = &ptp_ch->ptpsq[tc].txqsq;
608145e5637SEran Ben Elisha 
609145e5637SEran Ben Elisha 			err = mlx5e_health_queue_dump(priv, fmsg, sq->sqn, "PTP SQ");
610145e5637SEran Ben Elisha 			if (err)
611145e5637SEran Ben Elisha 				return err;
612145e5637SEran Ben Elisha 		}
613145e5637SEran Ben Elisha 	}
614145e5637SEran Ben Elisha 
6155f29458bSAya Levin 	return devlink_fmsg_arr_pair_nest_end(fmsg);
6165f29458bSAya Levin }
6175f29458bSAya Levin 
mlx5e_tx_reporter_dump_from_ctx(struct mlx5e_priv * priv,struct mlx5e_err_ctx * err_ctx,struct devlink_fmsg * fmsg)6185f29458bSAya Levin static int mlx5e_tx_reporter_dump_from_ctx(struct mlx5e_priv *priv,
6195f29458bSAya Levin 					   struct mlx5e_err_ctx *err_ctx,
6205f29458bSAya Levin 					   struct devlink_fmsg *fmsg)
6215f29458bSAya Levin {
6225f29458bSAya Levin 	return err_ctx->dump(priv, fmsg, err_ctx->ctx);
6235f29458bSAya Levin }
6245f29458bSAya Levin 
mlx5e_tx_reporter_dump(struct devlink_health_reporter * reporter,struct devlink_fmsg * fmsg,void * context,struct netlink_ext_ack * extack)6255f29458bSAya Levin static int mlx5e_tx_reporter_dump(struct devlink_health_reporter *reporter,
6265f29458bSAya Levin 				  struct devlink_fmsg *fmsg, void *context,
6275f29458bSAya Levin 				  struct netlink_ext_ack *extack)
6285f29458bSAya Levin {
6295f29458bSAya Levin 	struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
6305f29458bSAya Levin 	struct mlx5e_err_ctx *err_ctx = context;
6315f29458bSAya Levin 
6325f29458bSAya Levin 	return err_ctx ? mlx5e_tx_reporter_dump_from_ctx(priv, err_ctx, fmsg) :
6335f29458bSAya Levin 			 mlx5e_tx_reporter_dump_all_sqs(priv, fmsg);
6345f29458bSAya Levin }
6355f29458bSAya Levin 
mlx5e_reporter_tx_err_cqe(struct mlx5e_txqsq * sq)6360a56be3cSAya Levin void mlx5e_reporter_tx_err_cqe(struct mlx5e_txqsq *sq)
6370a56be3cSAya Levin {
6380a56be3cSAya Levin 	char err_str[MLX5E_REPORTER_PER_Q_MAX_LEN];
6394ad40d8eSEran Ben Elisha 	struct mlx5e_priv *priv = sq->priv;
6400a56be3cSAya Levin 	struct mlx5e_err_ctx err_ctx = {};
6410a56be3cSAya Levin 
6420a56be3cSAya Levin 	err_ctx.ctx = sq;
6430a56be3cSAya Levin 	err_ctx.recover = mlx5e_tx_reporter_err_cqe_recover;
6445f29458bSAya Levin 	err_ctx.dump = mlx5e_tx_reporter_dump_sq;
645b21aef7eSJoe Perches 	snprintf(err_str, sizeof(err_str), "ERR CQE on SQ: 0x%x", sq->sqn);
6460a56be3cSAya Levin 
6470a56be3cSAya Levin 	mlx5e_health_report(priv, priv->tx_reporter, err_str, &err_ctx);
6480a56be3cSAya Levin }
6490a56be3cSAya Levin 
mlx5e_reporter_tx_timeout(struct mlx5e_txqsq * sq)6500a56be3cSAya Levin int mlx5e_reporter_tx_timeout(struct mlx5e_txqsq *sq)
6510a56be3cSAya Levin {
6520a56be3cSAya Levin 	char err_str[MLX5E_REPORTER_PER_Q_MAX_LEN];
653e6205564SAya Levin 	struct mlx5e_tx_timeout_ctx to_ctx = {};
6544ad40d8eSEran Ben Elisha 	struct mlx5e_priv *priv = sq->priv;
6550a56be3cSAya Levin 	struct mlx5e_err_ctx err_ctx = {};
6560a56be3cSAya Levin 
657e6205564SAya Levin 	to_ctx.sq = sq;
658e6205564SAya Levin 	err_ctx.ctx = &to_ctx;
6590a56be3cSAya Levin 	err_ctx.recover = mlx5e_tx_reporter_timeout_recover;
660918fc385SAmir Tzin 	err_ctx.dump = mlx5e_tx_reporter_timeout_dump;
661b21aef7eSJoe Perches 	snprintf(err_str, sizeof(err_str),
662b21aef7eSJoe Perches 		 "TX timeout on queue: %d, SQ: 0x%x, CQ: 0x%x, SQ Cons: 0x%x SQ Prod: 0x%x, usecs since last trans: %u",
6634ad40d8eSEran Ben Elisha 		 sq->ch_ix, sq->sqn, sq->cq.mcq.cqn, sq->cc, sq->pc,
6645337824fSEric Dumazet 		 jiffies_to_usecs(jiffies - READ_ONCE(sq->txq->trans_start)));
6650a56be3cSAya Levin 
666e6205564SAya Levin 	mlx5e_health_report(priv, priv->tx_reporter, err_str, &err_ctx);
667e6205564SAya Levin 	return to_ctx.status;
6680a56be3cSAya Levin }
6690a56be3cSAya Levin 
mlx5e_reporter_tx_ptpsq_unhealthy(struct mlx5e_ptpsq * ptpsq)670*53b836a4SRahul Rameshbabu void mlx5e_reporter_tx_ptpsq_unhealthy(struct mlx5e_ptpsq *ptpsq)
671*53b836a4SRahul Rameshbabu {
672*53b836a4SRahul Rameshbabu 	struct mlx5e_ptp_metadata_map *map = &ptpsq->metadata_map;
673*53b836a4SRahul Rameshbabu 	char err_str[MLX5E_REPORTER_PER_Q_MAX_LEN];
674*53b836a4SRahul Rameshbabu 	struct mlx5e_txqsq *txqsq = &ptpsq->txqsq;
675*53b836a4SRahul Rameshbabu 	struct mlx5e_cq *ts_cq = &ptpsq->ts_cq;
676*53b836a4SRahul Rameshbabu 	struct mlx5e_priv *priv = txqsq->priv;
677*53b836a4SRahul Rameshbabu 	struct mlx5e_err_ctx err_ctx = {};
678*53b836a4SRahul Rameshbabu 
679*53b836a4SRahul Rameshbabu 	err_ctx.ctx = ptpsq;
680*53b836a4SRahul Rameshbabu 	err_ctx.recover = mlx5e_tx_reporter_ptpsq_unhealthy_recover;
681*53b836a4SRahul Rameshbabu 	err_ctx.dump = mlx5e_tx_reporter_ptpsq_unhealthy_dump;
682*53b836a4SRahul Rameshbabu 	snprintf(err_str, sizeof(err_str),
683*53b836a4SRahul Rameshbabu 		 "Unhealthy TX port TS queue: %d, SQ: 0x%x, CQ: 0x%x, Undelivered CQEs: %u Map Capacity: %u",
684*53b836a4SRahul Rameshbabu 		 txqsq->ch_ix, txqsq->sqn, ts_cq->mcq.cqn, map->undelivered_counter, map->capacity);
685*53b836a4SRahul Rameshbabu 
686*53b836a4SRahul Rameshbabu 	mlx5e_health_report(priv, priv->tx_reporter, err_str, &err_ctx);
687*53b836a4SRahul Rameshbabu }
688*53b836a4SRahul Rameshbabu 
689de8650a8SEran Ben Elisha static const struct devlink_health_reporter_ops mlx5_tx_reporter_ops = {
690de8650a8SEran Ben Elisha 		.name = "tx",
691de8650a8SEran Ben Elisha 		.recover = mlx5e_tx_reporter_recover,
692de8650a8SEran Ben Elisha 		.diagnose = mlx5e_tx_reporter_diagnose,
6935f29458bSAya Levin 		.dump = mlx5e_tx_reporter_dump,
694de8650a8SEran Ben Elisha };
695de8650a8SEran Ben Elisha 
696de8650a8SEran Ben Elisha #define MLX5_REPORTER_TX_GRACEFUL_PERIOD 500
697de8650a8SEran Ben Elisha 
mlx5e_reporter_tx_create(struct mlx5e_priv * priv)698b3ea4c4fSEran Ben Elisha void mlx5e_reporter_tx_create(struct mlx5e_priv *priv)
699de8650a8SEran Ben Elisha {
700baf6dfdbSAya Levin 	struct devlink_health_reporter *reporter;
701de8650a8SEran Ben Elisha 
702bc1536f3SJiri Pirko 	reporter = devlink_port_health_reporter_create(priv->netdev->devlink_port,
703bc1536f3SJiri Pirko 						       &mlx5_tx_reporter_ops,
704b7e93bb6SVladyslav Tarasiuk 						       MLX5_REPORTER_TX_GRACEFUL_PERIOD, priv);
705baf6dfdbSAya Levin 	if (IS_ERR(reporter)) {
706de8650a8SEran Ben Elisha 		netdev_warn(priv->netdev,
707de8650a8SEran Ben Elisha 			    "Failed to create tx reporter, err = %ld\n",
708baf6dfdbSAya Levin 			    PTR_ERR(reporter));
709b3ea4c4fSEran Ben Elisha 		return;
7107f7cc235SAya Levin 	}
711baf6dfdbSAya Levin 	priv->tx_reporter = reporter;
712de8650a8SEran Ben Elisha }
713de8650a8SEran Ben Elisha 
mlx5e_reporter_tx_destroy(struct mlx5e_priv * priv)71406293ae4SAya Levin void mlx5e_reporter_tx_destroy(struct mlx5e_priv *priv)
715de8650a8SEran Ben Elisha {
716baf6dfdbSAya Levin 	if (!priv->tx_reporter)
717de8650a8SEran Ben Elisha 		return;
718de8650a8SEran Ben Elisha 
7199f167327SJiri Pirko 	devlink_health_reporter_destroy(priv->tx_reporter);
7207a9fb35eSRoi Dayan 	priv->tx_reporter = NULL;
721de8650a8SEran Ben Elisha }
722