Linux 6.9-rc5
[sfrench/cifs-2.6.git] / drivers / net / ethernet / mellanox / mlx5 / core / en / reporter_rx.c
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2019 Mellanox Technologies.
3
4 #include "health.h"
5 #include "params.h"
6 #include "txrx.h"
7 #include "devlink.h"
8 #include "ptp.h"
9 #include "lib/tout.h"
10
11 static int mlx5e_query_rq_state(struct mlx5_core_dev *dev, u32 rqn, u8 *state)
12 {
13         int outlen = MLX5_ST_SZ_BYTES(query_rq_out);
14         void *out;
15         void *rqc;
16         int err;
17
18         out = kvzalloc(outlen, GFP_KERNEL);
19         if (!out)
20                 return -ENOMEM;
21
22         err = mlx5_core_query_rq(dev, rqn, out);
23         if (err)
24                 goto out;
25
26         rqc = MLX5_ADDR_OF(query_rq_out, out, rq_context);
27         *state = MLX5_GET(rqc, rqc, state);
28
29 out:
30         kvfree(out);
31         return err;
32 }
33
34 static int mlx5e_wait_for_icosq_flush(struct mlx5e_icosq *icosq)
35 {
36         struct mlx5_core_dev *dev = icosq->channel->mdev;
37         unsigned long exp_time;
38
39         exp_time = jiffies + msecs_to_jiffies(mlx5_tout_ms(dev, FLUSH_ON_ERROR));
40
41         while (time_before(jiffies, exp_time)) {
42                 if (icosq->cc == icosq->pc)
43                         return 0;
44
45                 msleep(20);
46         }
47
48         netdev_err(icosq->channel->netdev,
49                    "Wait for ICOSQ 0x%x flush timeout (cc = 0x%x, pc = 0x%x)\n",
50                    icosq->sqn, icosq->cc, icosq->pc);
51
52         return -ETIMEDOUT;
53 }
54
55 static void mlx5e_reset_icosq_cc_pc(struct mlx5e_icosq *icosq)
56 {
57         WARN_ONCE(icosq->cc != icosq->pc, "ICOSQ 0x%x: cc (0x%x) != pc (0x%x)\n",
58                   icosq->sqn, icosq->cc, icosq->pc);
59         icosq->cc = 0;
60         icosq->pc = 0;
61 }
62
63 static int mlx5e_rx_reporter_err_icosq_cqe_recover(void *ctx)
64 {
65         struct mlx5e_rq *xskrq = NULL;
66         struct mlx5_core_dev *mdev;
67         struct mlx5e_icosq *icosq;
68         struct net_device *dev;
69         struct mlx5e_rq *rq;
70         u8 state;
71         int err;
72
73         icosq = ctx;
74
75         mutex_lock(&icosq->channel->icosq_recovery_lock);
76
77         /* mlx5e_close_rq cancels this work before RQ and ICOSQ are killed. */
78         rq = &icosq->channel->rq;
79         if (test_bit(MLX5E_RQ_STATE_ENABLED, &icosq->channel->xskrq.state))
80                 xskrq = &icosq->channel->xskrq;
81         mdev = icosq->channel->mdev;
82         dev = icosq->channel->netdev;
83         err = mlx5_core_query_sq_state(mdev, icosq->sqn, &state);
84         if (err) {
85                 netdev_err(dev, "Failed to query ICOSQ 0x%x state. err = %d\n",
86                            icosq->sqn, err);
87                 goto out;
88         }
89
90         if (state != MLX5_SQC_STATE_ERR)
91                 goto out;
92
93         mlx5e_deactivate_rq(rq);
94         if (xskrq)
95                 mlx5e_deactivate_rq(xskrq);
96
97         err = mlx5e_wait_for_icosq_flush(icosq);
98         if (err)
99                 goto out;
100
101         mlx5e_deactivate_icosq(icosq);
102
103         /* At this point, both the rq and the icosq are disabled */
104
105         err = mlx5e_health_sq_to_ready(mdev, dev, icosq->sqn);
106         if (err)
107                 goto out;
108
109         mlx5e_reset_icosq_cc_pc(icosq);
110
111         mlx5e_free_rx_in_progress_descs(rq);
112         if (xskrq)
113                 mlx5e_free_rx_in_progress_descs(xskrq);
114
115         clear_bit(MLX5E_SQ_STATE_RECOVERING, &icosq->state);
116         mlx5e_activate_icosq(icosq);
117
118         mlx5e_activate_rq(rq);
119         rq->stats->recover++;
120
121         if (xskrq) {
122                 mlx5e_activate_rq(xskrq);
123                 xskrq->stats->recover++;
124         }
125
126         mutex_unlock(&icosq->channel->icosq_recovery_lock);
127
128         return 0;
129 out:
130         clear_bit(MLX5E_SQ_STATE_RECOVERING, &icosq->state);
131         mutex_unlock(&icosq->channel->icosq_recovery_lock);
132         return err;
133 }
134
135 static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state)
136 {
137         struct net_device *dev = rq->netdev;
138         int err;
139
140         err = mlx5e_modify_rq_state(rq, curr_state, MLX5_RQC_STATE_RST);
141         if (err) {
142                 netdev_err(dev, "Failed to move rq 0x%x to reset\n", rq->rqn);
143                 return err;
144         }
145         err = mlx5e_modify_rq_state(rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY);
146         if (err) {
147                 netdev_err(dev, "Failed to move rq 0x%x to ready\n", rq->rqn);
148                 return err;
149         }
150
151         return 0;
152 }
153
154 static int mlx5e_rx_reporter_err_rq_cqe_recover(void *ctx)
155 {
156         struct mlx5e_rq *rq = ctx;
157         int err;
158
159         mlx5e_deactivate_rq(rq);
160         mlx5e_free_rx_descs(rq);
161
162         err = mlx5e_rq_to_ready(rq, MLX5_RQC_STATE_ERR);
163         if (err)
164                 goto out;
165
166         clear_bit(MLX5E_RQ_STATE_RECOVERING, &rq->state);
167         mlx5e_activate_rq(rq);
168         rq->stats->recover++;
169         return 0;
170 out:
171         clear_bit(MLX5E_RQ_STATE_RECOVERING, &rq->state);
172         return err;
173 }
174
175 static int mlx5e_rx_reporter_timeout_recover(void *ctx)
176 {
177         struct mlx5_eq_comp *eq;
178         struct mlx5e_rq *rq;
179         int err;
180
181         rq = ctx;
182         eq = rq->cq.mcq.eq;
183
184         err = mlx5e_health_channel_eq_recover(rq->netdev, eq, rq->cq.ch_stats);
185         if (err && rq->icosq)
186                 clear_bit(MLX5E_SQ_STATE_ENABLED, &rq->icosq->state);
187
188         return err;
189 }
190
191 static int mlx5e_rx_reporter_recover_from_ctx(struct mlx5e_err_ctx *err_ctx)
192 {
193         return err_ctx->recover(err_ctx->ctx);
194 }
195
196 static int mlx5e_rx_reporter_recover(struct devlink_health_reporter *reporter,
197                                      void *context,
198                                      struct netlink_ext_ack *extack)
199 {
200         struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
201         struct mlx5e_err_ctx *err_ctx = context;
202
203         return err_ctx ? mlx5e_rx_reporter_recover_from_ctx(err_ctx) :
204                          mlx5e_health_recover_channels(priv);
205 }
206
207 static int mlx5e_reporter_icosq_diagnose(struct mlx5e_icosq *icosq, u8 hw_state,
208                                          struct devlink_fmsg *fmsg)
209 {
210         int err;
211
212         err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "ICOSQ");
213         if (err)
214                 return err;
215
216         err = devlink_fmsg_u32_pair_put(fmsg, "sqn", icosq->sqn);
217         if (err)
218                 return err;
219
220         err = devlink_fmsg_u8_pair_put(fmsg, "HW state", hw_state);
221         if (err)
222                 return err;
223
224         err = devlink_fmsg_u32_pair_put(fmsg, "cc", icosq->cc);
225         if (err)
226                 return err;
227
228         err = devlink_fmsg_u32_pair_put(fmsg, "pc", icosq->pc);
229         if (err)
230                 return err;
231
232         err = devlink_fmsg_u32_pair_put(fmsg, "WQE size",
233                                         mlx5_wq_cyc_get_size(&icosq->wq));
234         if (err)
235                 return err;
236
237         err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "CQ");
238         if (err)
239                 return err;
240
241         err = devlink_fmsg_u32_pair_put(fmsg, "cqn", icosq->cq.mcq.cqn);
242         if (err)
243                 return err;
244
245         err = devlink_fmsg_u32_pair_put(fmsg, "cc", icosq->cq.wq.cc);
246         if (err)
247                 return err;
248
249         err = devlink_fmsg_u32_pair_put(fmsg, "size", mlx5_cqwq_get_size(&icosq->cq.wq));
250         if (err)
251                 return err;
252
253         err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
254         if (err)
255                 return err;
256
257         return mlx5e_health_fmsg_named_obj_nest_end(fmsg);
258 }
259
260 static int
261 mlx5e_rx_reporter_build_diagnose_output_rq_common(struct mlx5e_rq *rq,
262                                                   struct devlink_fmsg *fmsg)
263 {
264         u16 wqe_counter;
265         int wqes_sz;
266         u8 hw_state;
267         u16 wq_head;
268         int err;
269
270         err = mlx5e_query_rq_state(rq->mdev, rq->rqn, &hw_state);
271         if (err)
272                 return err;
273
274         wqes_sz = mlx5e_rqwq_get_cur_sz(rq);
275         wq_head = mlx5e_rqwq_get_head(rq);
276         wqe_counter = mlx5e_rqwq_get_wqe_counter(rq);
277
278         err = devlink_fmsg_u32_pair_put(fmsg, "rqn", rq->rqn);
279         if (err)
280                 return err;
281
282         err = devlink_fmsg_u8_pair_put(fmsg, "HW state", hw_state);
283         if (err)
284                 return err;
285
286         err = devlink_fmsg_u8_pair_put(fmsg, "SW state", rq->state);
287         if (err)
288                 return err;
289
290         err = devlink_fmsg_u32_pair_put(fmsg, "WQE counter", wqe_counter);
291         if (err)
292                 return err;
293
294         err = devlink_fmsg_u32_pair_put(fmsg, "posted WQEs", wqes_sz);
295         if (err)
296                 return err;
297
298         err = devlink_fmsg_u32_pair_put(fmsg, "cc", wq_head);
299         if (err)
300                 return err;
301
302         err = mlx5e_health_cq_diag_fmsg(&rq->cq, fmsg);
303         if (err)
304                 return err;
305
306         err = mlx5e_health_eq_diag_fmsg(rq->cq.mcq.eq, fmsg);
307         if (err)
308                 return err;
309
310         if (rq->icosq) {
311                 struct mlx5e_icosq *icosq = rq->icosq;
312                 u8 icosq_hw_state;
313
314                 err = mlx5_core_query_sq_state(rq->mdev, icosq->sqn, &icosq_hw_state);
315                 if (err)
316                         return err;
317
318                 err = mlx5e_reporter_icosq_diagnose(icosq, icosq_hw_state, fmsg);
319                 if (err)
320                         return err;
321         }
322
323         return 0;
324 }
325
326 static int mlx5e_rx_reporter_build_diagnose_output(struct mlx5e_rq *rq,
327                                                    struct devlink_fmsg *fmsg)
328 {
329         int err;
330
331         err = devlink_fmsg_obj_nest_start(fmsg);
332         if (err)
333                 return err;
334
335         err = devlink_fmsg_u32_pair_put(fmsg, "channel ix", rq->ix);
336         if (err)
337                 return err;
338
339         err = mlx5e_rx_reporter_build_diagnose_output_rq_common(rq, fmsg);
340         if (err)
341                 return err;
342
343         return devlink_fmsg_obj_nest_end(fmsg);
344 }
345
346 static int mlx5e_rx_reporter_diagnose_generic_rq(struct mlx5e_rq *rq,
347                                                  struct devlink_fmsg *fmsg)
348 {
349         struct mlx5e_priv *priv = rq->priv;
350         struct mlx5e_params *params;
351         u32 rq_stride, rq_sz;
352         bool real_time;
353         int err;
354
355         params = &priv->channels.params;
356         rq_sz = mlx5e_rqwq_get_size(rq);
357         real_time =  mlx5_is_real_time_rq(priv->mdev);
358         rq_stride = BIT(mlx5e_mpwqe_get_log_stride_size(priv->mdev, params, NULL));
359
360         err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "RQ");
361         if (err)
362                 return err;
363
364         err = devlink_fmsg_u8_pair_put(fmsg, "type", params->rq_wq_type);
365         if (err)
366                 return err;
367
368         err = devlink_fmsg_u64_pair_put(fmsg, "stride size", rq_stride);
369         if (err)
370                 return err;
371
372         err = devlink_fmsg_u32_pair_put(fmsg, "size", rq_sz);
373         if (err)
374                 return err;
375
376         err = devlink_fmsg_string_pair_put(fmsg, "ts_format", real_time ? "RT" : "FRC");
377         if (err)
378                 return err;
379
380         err = mlx5e_health_cq_common_diag_fmsg(&rq->cq, fmsg);
381         if (err)
382                 return err;
383
384         return mlx5e_health_fmsg_named_obj_nest_end(fmsg);
385 }
386
387 static int
388 mlx5e_rx_reporter_diagnose_common_ptp_config(struct mlx5e_priv *priv, struct mlx5e_ptp *ptp_ch,
389                                              struct devlink_fmsg *fmsg)
390 {
391         int err;
392
393         err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "PTP");
394         if (err)
395                 return err;
396
397         err = devlink_fmsg_u32_pair_put(fmsg, "filter_type", priv->tstamp.rx_filter);
398         if (err)
399                 return err;
400
401         err = mlx5e_rx_reporter_diagnose_generic_rq(&ptp_ch->rq, fmsg);
402         if (err)
403                 return err;
404
405         return mlx5e_health_fmsg_named_obj_nest_end(fmsg);
406 }
407
408 static int
409 mlx5e_rx_reporter_diagnose_common_config(struct devlink_health_reporter *reporter,
410                                          struct devlink_fmsg *fmsg)
411 {
412         struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
413         struct mlx5e_rq *generic_rq = &priv->channels.c[0]->rq;
414         struct mlx5e_ptp *ptp_ch = priv->channels.ptp;
415         int err;
416
417         err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "Common config");
418         if (err)
419                 return err;
420
421         err = mlx5e_rx_reporter_diagnose_generic_rq(generic_rq, fmsg);
422         if (err)
423                 return err;
424
425         if (ptp_ch && test_bit(MLX5E_PTP_STATE_RX, ptp_ch->state)) {
426                 err = mlx5e_rx_reporter_diagnose_common_ptp_config(priv, ptp_ch, fmsg);
427                 if (err)
428                         return err;
429         }
430
431         return mlx5e_health_fmsg_named_obj_nest_end(fmsg);
432 }
433
434 static int mlx5e_rx_reporter_build_diagnose_output_ptp_rq(struct mlx5e_rq *rq,
435                                                           struct devlink_fmsg *fmsg)
436 {
437         int err;
438
439         err = devlink_fmsg_obj_nest_start(fmsg);
440         if (err)
441                 return err;
442
443         err = devlink_fmsg_string_pair_put(fmsg, "channel", "ptp");
444         if (err)
445                 return err;
446
447         err = mlx5e_rx_reporter_build_diagnose_output_rq_common(rq, fmsg);
448         if (err)
449                 return err;
450
451         err = devlink_fmsg_obj_nest_end(fmsg);
452         if (err)
453                 return err;
454
455         return 0;
456 }
457
458 static int mlx5e_rx_reporter_diagnose(struct devlink_health_reporter *reporter,
459                                       struct devlink_fmsg *fmsg,
460                                       struct netlink_ext_ack *extack)
461 {
462         struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
463         struct mlx5e_ptp *ptp_ch = priv->channels.ptp;
464         int i, err = 0;
465
466         mutex_lock(&priv->state_lock);
467
468         if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
469                 goto unlock;
470
471         err = mlx5e_rx_reporter_diagnose_common_config(reporter, fmsg);
472         if (err)
473                 goto unlock;
474
475         err = devlink_fmsg_arr_pair_nest_start(fmsg, "RQs");
476         if (err)
477                 goto unlock;
478
479         for (i = 0; i < priv->channels.num; i++) {
480                 struct mlx5e_rq *rq = &priv->channels.c[i]->rq;
481
482                 err = mlx5e_rx_reporter_build_diagnose_output(rq, fmsg);
483                 if (err)
484                         goto unlock;
485         }
486         if (ptp_ch && test_bit(MLX5E_PTP_STATE_RX, ptp_ch->state)) {
487                 err = mlx5e_rx_reporter_build_diagnose_output_ptp_rq(&ptp_ch->rq, fmsg);
488                 if (err)
489                         goto unlock;
490         }
491         err = devlink_fmsg_arr_pair_nest_end(fmsg);
492 unlock:
493         mutex_unlock(&priv->state_lock);
494         return err;
495 }
496
497 static int mlx5e_rx_reporter_dump_icosq(struct mlx5e_priv *priv, struct devlink_fmsg *fmsg,
498                                         void *ctx)
499 {
500         struct mlx5e_txqsq *icosq = ctx;
501         struct mlx5_rsc_key key = {};
502         int err;
503
504         if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
505                 return 0;
506
507         err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "SX Slice");
508         if (err)
509                 return err;
510
511         key.size = PAGE_SIZE;
512         key.rsc = MLX5_SGMT_TYPE_SX_SLICE_ALL;
513         err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg);
514         if (err)
515                 return err;
516
517         err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
518         if (err)
519                 return err;
520
521         err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "ICOSQ");
522         if (err)
523                 return err;
524
525         err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "QPC");
526         if (err)
527                 return err;
528
529         key.rsc = MLX5_SGMT_TYPE_FULL_QPC;
530         key.index1 = icosq->sqn;
531         key.num_of_obj1 = 1;
532
533         err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg);
534         if (err)
535                 return err;
536
537         err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
538         if (err)
539                 return err;
540
541         err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "send_buff");
542         if (err)
543                 return err;
544
545         key.rsc = MLX5_SGMT_TYPE_SND_BUFF;
546         key.num_of_obj2 = MLX5_RSC_DUMP_ALL;
547
548         err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg);
549         if (err)
550                 return err;
551
552         err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
553         if (err)
554                 return err;
555
556         return mlx5e_health_fmsg_named_obj_nest_end(fmsg);
557 }
558
559 static int mlx5e_rx_reporter_dump_rq(struct mlx5e_priv *priv, struct devlink_fmsg *fmsg,
560                                      void *ctx)
561 {
562         struct mlx5_rsc_key key = {};
563         struct mlx5e_rq *rq = ctx;
564         int err;
565
566         if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
567                 return 0;
568
569         err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "RX Slice");
570         if (err)
571                 return err;
572
573         key.size = PAGE_SIZE;
574         key.rsc = MLX5_SGMT_TYPE_RX_SLICE_ALL;
575         err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg);
576         if (err)
577                 return err;
578
579         err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
580         if (err)
581                 return err;
582
583         err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "RQ");
584         if (err)
585                 return err;
586
587         err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "QPC");
588         if (err)
589                 return err;
590
591         key.rsc = MLX5_SGMT_TYPE_FULL_QPC;
592         key.index1 = rq->rqn;
593         key.num_of_obj1 = 1;
594
595         err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg);
596         if (err)
597                 return err;
598
599         err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
600         if (err)
601                 return err;
602
603         err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "receive_buff");
604         if (err)
605                 return err;
606
607         key.rsc = MLX5_SGMT_TYPE_RCV_BUFF;
608         key.num_of_obj2 = MLX5_RSC_DUMP_ALL;
609         err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg);
610         if (err)
611                 return err;
612
613         err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
614         if (err)
615                 return err;
616
617         return mlx5e_health_fmsg_named_obj_nest_end(fmsg);
618 }
619
620 static int mlx5e_rx_reporter_dump_all_rqs(struct mlx5e_priv *priv,
621                                           struct devlink_fmsg *fmsg)
622 {
623         struct mlx5e_ptp *ptp_ch = priv->channels.ptp;
624         struct mlx5_rsc_key key = {};
625         int i, err;
626
627         if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
628                 return 0;
629
630         err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "RX Slice");
631         if (err)
632                 return err;
633
634         key.size = PAGE_SIZE;
635         key.rsc = MLX5_SGMT_TYPE_RX_SLICE_ALL;
636         err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg);
637         if (err)
638                 return err;
639
640         err = mlx5e_health_fmsg_named_obj_nest_end(fmsg);
641         if (err)
642                 return err;
643
644         err = devlink_fmsg_arr_pair_nest_start(fmsg, "RQs");
645         if (err)
646                 return err;
647
648         for (i = 0; i < priv->channels.num; i++) {
649                 struct mlx5e_rq *rq = &priv->channels.c[i]->rq;
650
651                 err = mlx5e_health_queue_dump(priv, fmsg, rq->rqn, "RQ");
652                 if (err)
653                         return err;
654         }
655
656         if (ptp_ch && test_bit(MLX5E_PTP_STATE_RX, ptp_ch->state)) {
657                 err = mlx5e_health_queue_dump(priv, fmsg, ptp_ch->rq.rqn, "PTP RQ");
658                 if (err)
659                         return err;
660         }
661
662         return devlink_fmsg_arr_pair_nest_end(fmsg);
663 }
664
665 static int mlx5e_rx_reporter_dump_from_ctx(struct mlx5e_priv *priv,
666                                            struct mlx5e_err_ctx *err_ctx,
667                                            struct devlink_fmsg *fmsg)
668 {
669         return err_ctx->dump(priv, fmsg, err_ctx->ctx);
670 }
671
672 static int mlx5e_rx_reporter_dump(struct devlink_health_reporter *reporter,
673                                   struct devlink_fmsg *fmsg, void *context,
674                                   struct netlink_ext_ack *extack)
675 {
676         struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
677         struct mlx5e_err_ctx *err_ctx = context;
678
679         return err_ctx ? mlx5e_rx_reporter_dump_from_ctx(priv, err_ctx, fmsg) :
680                          mlx5e_rx_reporter_dump_all_rqs(priv, fmsg);
681 }
682
683 void mlx5e_reporter_rx_timeout(struct mlx5e_rq *rq)
684 {
685         char icosq_str[MLX5E_REPORTER_PER_Q_MAX_LEN] = {};
686         char err_str[MLX5E_REPORTER_PER_Q_MAX_LEN];
687         struct mlx5e_icosq *icosq = rq->icosq;
688         struct mlx5e_priv *priv = rq->priv;
689         struct mlx5e_err_ctx err_ctx = {};
690
691         err_ctx.ctx = rq;
692         err_ctx.recover = mlx5e_rx_reporter_timeout_recover;
693         err_ctx.dump = mlx5e_rx_reporter_dump_rq;
694
695         if (icosq)
696                 snprintf(icosq_str, sizeof(icosq_str), "ICOSQ: 0x%x, ", icosq->sqn);
697         snprintf(err_str, sizeof(err_str),
698                  "RX timeout on channel: %d, %sRQ: 0x%x, CQ: 0x%x",
699                  rq->ix, icosq_str, rq->rqn, rq->cq.mcq.cqn);
700
701         mlx5e_health_report(priv, priv->rx_reporter, err_str, &err_ctx);
702 }
703
704 void mlx5e_reporter_rq_cqe_err(struct mlx5e_rq *rq)
705 {
706         char err_str[MLX5E_REPORTER_PER_Q_MAX_LEN];
707         struct mlx5e_priv *priv = rq->priv;
708         struct mlx5e_err_ctx err_ctx = {};
709
710         err_ctx.ctx = rq;
711         err_ctx.recover = mlx5e_rx_reporter_err_rq_cqe_recover;
712         err_ctx.dump = mlx5e_rx_reporter_dump_rq;
713         snprintf(err_str, sizeof(err_str), "ERR CQE on RQ: 0x%x", rq->rqn);
714
715         mlx5e_health_report(priv, priv->rx_reporter, err_str, &err_ctx);
716 }
717
718 void mlx5e_reporter_icosq_cqe_err(struct mlx5e_icosq *icosq)
719 {
720         struct mlx5e_priv *priv = icosq->channel->priv;
721         char err_str[MLX5E_REPORTER_PER_Q_MAX_LEN];
722         struct mlx5e_err_ctx err_ctx = {};
723
724         err_ctx.ctx = icosq;
725         err_ctx.recover = mlx5e_rx_reporter_err_icosq_cqe_recover;
726         err_ctx.dump = mlx5e_rx_reporter_dump_icosq;
727         snprintf(err_str, sizeof(err_str), "ERR CQE on ICOSQ: 0x%x", icosq->sqn);
728
729         mlx5e_health_report(priv, priv->rx_reporter, err_str, &err_ctx);
730 }
731
732 void mlx5e_reporter_icosq_suspend_recovery(struct mlx5e_channel *c)
733 {
734         mutex_lock(&c->icosq_recovery_lock);
735 }
736
737 void mlx5e_reporter_icosq_resume_recovery(struct mlx5e_channel *c)
738 {
739         mutex_unlock(&c->icosq_recovery_lock);
740 }
741
742 static const struct devlink_health_reporter_ops mlx5_rx_reporter_ops = {
743         .name = "rx",
744         .recover = mlx5e_rx_reporter_recover,
745         .diagnose = mlx5e_rx_reporter_diagnose,
746         .dump = mlx5e_rx_reporter_dump,
747 };
748
749 #define MLX5E_REPORTER_RX_GRACEFUL_PERIOD 500
750
751 void mlx5e_reporter_rx_create(struct mlx5e_priv *priv)
752 {
753         struct devlink_port *dl_port = mlx5e_devlink_get_dl_port(priv);
754         struct devlink_health_reporter *reporter;
755
756         reporter = devlink_port_health_reporter_create(dl_port, &mlx5_rx_reporter_ops,
757                                                        MLX5E_REPORTER_RX_GRACEFUL_PERIOD, priv);
758         if (IS_ERR(reporter)) {
759                 netdev_warn(priv->netdev, "Failed to create rx reporter, err = %ld\n",
760                             PTR_ERR(reporter));
761                 return;
762         }
763         priv->rx_reporter = reporter;
764 }
765
766 void mlx5e_reporter_rx_destroy(struct mlx5e_priv *priv)
767 {
768         if (!priv->rx_reporter)
769                 return;
770
771         devlink_port_health_reporter_destroy(priv->rx_reporter);
772         priv->rx_reporter = NULL;
773 }