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 mlx5e_trigger_napi_icosq(icosq->channel); 127 128 mutex_unlock(&icosq->channel->icosq_recovery_lock); 129 130 return 0; 131 out: 132 clear_bit(MLX5E_SQ_STATE_RECOVERING, &icosq->state); 133 mutex_unlock(&icosq->channel->icosq_recovery_lock); 134 return err; 135 } 136 137 static int mlx5e_rx_reporter_err_rq_cqe_recover(void *ctx) 138 { 139 struct mlx5e_rq *rq = ctx; 140 int err; 141 142 mlx5e_deactivate_rq(rq); 143 err = mlx5e_flush_rq(rq, MLX5_RQC_STATE_ERR); 144 clear_bit(MLX5E_RQ_STATE_RECOVERING, &rq->state); 145 if (err) 146 return err; 147 148 mlx5e_activate_rq(rq); 149 rq->stats->recover++; 150 if (rq->channel) 151 mlx5e_trigger_napi_icosq(rq->channel); 152 else 153 mlx5e_trigger_napi_sched(rq->cq.napi); 154 return 0; 155 } 156 157 static int mlx5e_rx_reporter_timeout_recover(void *ctx) 158 { 159 struct mlx5_eq_comp *eq; 160 struct mlx5e_rq *rq; 161 int err; 162 163 rq = ctx; 164 eq = rq->cq.mcq.eq; 165 166 err = mlx5e_health_channel_eq_recover(rq->netdev, eq, rq->cq.ch_stats); 167 if (err && rq->icosq) 168 clear_bit(MLX5E_SQ_STATE_ENABLED, &rq->icosq->state); 169 170 return err; 171 } 172 173 static int mlx5e_rx_reporter_recover_from_ctx(struct mlx5e_err_ctx *err_ctx) 174 { 175 return err_ctx->recover(err_ctx->ctx); 176 } 177 178 static int mlx5e_rx_reporter_recover(struct devlink_health_reporter *reporter, 179 void *context, 180 struct netlink_ext_ack *extack) 181 { 182 struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter); 183 struct mlx5e_err_ctx *err_ctx = context; 184 185 return err_ctx ? mlx5e_rx_reporter_recover_from_ctx(err_ctx) : 186 mlx5e_health_recover_channels(priv); 187 } 188 189 static int mlx5e_reporter_icosq_diagnose(struct mlx5e_icosq *icosq, u8 hw_state, 190 struct devlink_fmsg *fmsg) 191 { 192 int err; 193 194 err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "ICOSQ"); 195 if (err) 196 return err; 197 198 err = devlink_fmsg_u32_pair_put(fmsg, "sqn", icosq->sqn); 199 if (err) 200 return err; 201 202 err = devlink_fmsg_u8_pair_put(fmsg, "HW state", hw_state); 203 if (err) 204 return err; 205 206 err = devlink_fmsg_u32_pair_put(fmsg, "cc", icosq->cc); 207 if (err) 208 return err; 209 210 err = devlink_fmsg_u32_pair_put(fmsg, "pc", icosq->pc); 211 if (err) 212 return err; 213 214 err = devlink_fmsg_u32_pair_put(fmsg, "WQE size", 215 mlx5_wq_cyc_get_size(&icosq->wq)); 216 if (err) 217 return err; 218 219 err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "CQ"); 220 if (err) 221 return err; 222 223 err = devlink_fmsg_u32_pair_put(fmsg, "cqn", icosq->cq.mcq.cqn); 224 if (err) 225 return err; 226 227 err = devlink_fmsg_u32_pair_put(fmsg, "cc", icosq->cq.wq.cc); 228 if (err) 229 return err; 230 231 err = devlink_fmsg_u32_pair_put(fmsg, "size", mlx5_cqwq_get_size(&icosq->cq.wq)); 232 if (err) 233 return err; 234 235 err = mlx5e_health_fmsg_named_obj_nest_end(fmsg); 236 if (err) 237 return err; 238 239 return mlx5e_health_fmsg_named_obj_nest_end(fmsg); 240 } 241 242 static int 243 mlx5e_rx_reporter_build_diagnose_output_rq_common(struct mlx5e_rq *rq, 244 struct devlink_fmsg *fmsg) 245 { 246 u16 wqe_counter; 247 int wqes_sz; 248 u8 hw_state; 249 u16 wq_head; 250 int err; 251 252 err = mlx5e_query_rq_state(rq->mdev, rq->rqn, &hw_state); 253 if (err) 254 return err; 255 256 wqes_sz = mlx5e_rqwq_get_cur_sz(rq); 257 wq_head = mlx5e_rqwq_get_head(rq); 258 wqe_counter = mlx5e_rqwq_get_wqe_counter(rq); 259 260 err = devlink_fmsg_u32_pair_put(fmsg, "rqn", rq->rqn); 261 if (err) 262 return err; 263 264 err = devlink_fmsg_u8_pair_put(fmsg, "HW state", hw_state); 265 if (err) 266 return err; 267 268 err = devlink_fmsg_u8_pair_put(fmsg, "SW state", rq->state); 269 if (err) 270 return err; 271 272 err = devlink_fmsg_u32_pair_put(fmsg, "WQE counter", wqe_counter); 273 if (err) 274 return err; 275 276 err = devlink_fmsg_u32_pair_put(fmsg, "posted WQEs", wqes_sz); 277 if (err) 278 return err; 279 280 err = devlink_fmsg_u32_pair_put(fmsg, "cc", wq_head); 281 if (err) 282 return err; 283 284 err = mlx5e_health_cq_diag_fmsg(&rq->cq, fmsg); 285 if (err) 286 return err; 287 288 err = mlx5e_health_eq_diag_fmsg(rq->cq.mcq.eq, fmsg); 289 if (err) 290 return err; 291 292 if (rq->icosq) { 293 struct mlx5e_icosq *icosq = rq->icosq; 294 u8 icosq_hw_state; 295 296 err = mlx5_core_query_sq_state(rq->mdev, icosq->sqn, &icosq_hw_state); 297 if (err) 298 return err; 299 300 err = mlx5e_reporter_icosq_diagnose(icosq, icosq_hw_state, fmsg); 301 if (err) 302 return err; 303 } 304 305 return 0; 306 } 307 308 static int mlx5e_rx_reporter_build_diagnose_output(struct mlx5e_rq *rq, 309 struct devlink_fmsg *fmsg) 310 { 311 int err; 312 313 err = devlink_fmsg_obj_nest_start(fmsg); 314 if (err) 315 return err; 316 317 err = devlink_fmsg_u32_pair_put(fmsg, "channel ix", rq->ix); 318 if (err) 319 return err; 320 321 err = mlx5e_rx_reporter_build_diagnose_output_rq_common(rq, fmsg); 322 if (err) 323 return err; 324 325 return devlink_fmsg_obj_nest_end(fmsg); 326 } 327 328 static int mlx5e_rx_reporter_diagnose_generic_rq(struct mlx5e_rq *rq, 329 struct devlink_fmsg *fmsg) 330 { 331 struct mlx5e_priv *priv = rq->priv; 332 struct mlx5e_params *params; 333 u32 rq_stride, rq_sz; 334 bool real_time; 335 int err; 336 337 params = &priv->channels.params; 338 rq_sz = mlx5e_rqwq_get_size(rq); 339 real_time = mlx5_is_real_time_rq(priv->mdev); 340 rq_stride = BIT(mlx5e_mpwqe_get_log_stride_size(priv->mdev, params, NULL)); 341 342 err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "RQ"); 343 if (err) 344 return err; 345 346 err = devlink_fmsg_u8_pair_put(fmsg, "type", params->rq_wq_type); 347 if (err) 348 return err; 349 350 err = devlink_fmsg_u64_pair_put(fmsg, "stride size", rq_stride); 351 if (err) 352 return err; 353 354 err = devlink_fmsg_u32_pair_put(fmsg, "size", rq_sz); 355 if (err) 356 return err; 357 358 err = devlink_fmsg_string_pair_put(fmsg, "ts_format", real_time ? "RT" : "FRC"); 359 if (err) 360 return err; 361 362 err = mlx5e_health_cq_common_diag_fmsg(&rq->cq, fmsg); 363 if (err) 364 return err; 365 366 return mlx5e_health_fmsg_named_obj_nest_end(fmsg); 367 } 368 369 static int 370 mlx5e_rx_reporter_diagnose_common_ptp_config(struct mlx5e_priv *priv, struct mlx5e_ptp *ptp_ch, 371 struct devlink_fmsg *fmsg) 372 { 373 int err; 374 375 err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "PTP"); 376 if (err) 377 return err; 378 379 err = devlink_fmsg_u32_pair_put(fmsg, "filter_type", priv->tstamp.rx_filter); 380 if (err) 381 return err; 382 383 err = mlx5e_rx_reporter_diagnose_generic_rq(&ptp_ch->rq, fmsg); 384 if (err) 385 return err; 386 387 return mlx5e_health_fmsg_named_obj_nest_end(fmsg); 388 } 389 390 static int 391 mlx5e_rx_reporter_diagnose_common_config(struct devlink_health_reporter *reporter, 392 struct devlink_fmsg *fmsg) 393 { 394 struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter); 395 struct mlx5e_rq *generic_rq = &priv->channels.c[0]->rq; 396 struct mlx5e_ptp *ptp_ch = priv->channels.ptp; 397 int err; 398 399 err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "Common config"); 400 if (err) 401 return err; 402 403 err = mlx5e_rx_reporter_diagnose_generic_rq(generic_rq, fmsg); 404 if (err) 405 return err; 406 407 if (ptp_ch && test_bit(MLX5E_PTP_STATE_RX, ptp_ch->state)) { 408 err = mlx5e_rx_reporter_diagnose_common_ptp_config(priv, ptp_ch, fmsg); 409 if (err) 410 return err; 411 } 412 413 return mlx5e_health_fmsg_named_obj_nest_end(fmsg); 414 } 415 416 static int mlx5e_rx_reporter_build_diagnose_output_ptp_rq(struct mlx5e_rq *rq, 417 struct devlink_fmsg *fmsg) 418 { 419 int err; 420 421 err = devlink_fmsg_obj_nest_start(fmsg); 422 if (err) 423 return err; 424 425 err = devlink_fmsg_string_pair_put(fmsg, "channel", "ptp"); 426 if (err) 427 return err; 428 429 err = mlx5e_rx_reporter_build_diagnose_output_rq_common(rq, fmsg); 430 if (err) 431 return err; 432 433 err = devlink_fmsg_obj_nest_end(fmsg); 434 if (err) 435 return err; 436 437 return 0; 438 } 439 440 static int mlx5e_rx_reporter_diagnose(struct devlink_health_reporter *reporter, 441 struct devlink_fmsg *fmsg, 442 struct netlink_ext_ack *extack) 443 { 444 struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter); 445 struct mlx5e_ptp *ptp_ch = priv->channels.ptp; 446 int i, err = 0; 447 448 mutex_lock(&priv->state_lock); 449 450 if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) 451 goto unlock; 452 453 err = mlx5e_rx_reporter_diagnose_common_config(reporter, fmsg); 454 if (err) 455 goto unlock; 456 457 err = devlink_fmsg_arr_pair_nest_start(fmsg, "RQs"); 458 if (err) 459 goto unlock; 460 461 for (i = 0; i < priv->channels.num; i++) { 462 struct mlx5e_channel *c = priv->channels.c[i]; 463 struct mlx5e_rq *rq; 464 465 rq = test_bit(MLX5E_CHANNEL_STATE_XSK, c->state) ? 466 &c->xskrq : &c->rq; 467 468 err = mlx5e_rx_reporter_build_diagnose_output(rq, fmsg); 469 if (err) 470 goto unlock; 471 } 472 if (ptp_ch && test_bit(MLX5E_PTP_STATE_RX, ptp_ch->state)) { 473 err = mlx5e_rx_reporter_build_diagnose_output_ptp_rq(&ptp_ch->rq, fmsg); 474 if (err) 475 goto unlock; 476 } 477 err = devlink_fmsg_arr_pair_nest_end(fmsg); 478 unlock: 479 mutex_unlock(&priv->state_lock); 480 return err; 481 } 482 483 static int mlx5e_rx_reporter_dump_icosq(struct mlx5e_priv *priv, struct devlink_fmsg *fmsg, 484 void *ctx) 485 { 486 struct mlx5e_txqsq *icosq = ctx; 487 struct mlx5_rsc_key key = {}; 488 int err; 489 490 if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) 491 return 0; 492 493 err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "SX Slice"); 494 if (err) 495 return err; 496 497 key.size = PAGE_SIZE; 498 key.rsc = MLX5_SGMT_TYPE_SX_SLICE_ALL; 499 err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg); 500 if (err) 501 return err; 502 503 err = mlx5e_health_fmsg_named_obj_nest_end(fmsg); 504 if (err) 505 return err; 506 507 err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "ICOSQ"); 508 if (err) 509 return err; 510 511 err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "QPC"); 512 if (err) 513 return err; 514 515 key.rsc = MLX5_SGMT_TYPE_FULL_QPC; 516 key.index1 = icosq->sqn; 517 key.num_of_obj1 = 1; 518 519 err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg); 520 if (err) 521 return err; 522 523 err = mlx5e_health_fmsg_named_obj_nest_end(fmsg); 524 if (err) 525 return err; 526 527 err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "send_buff"); 528 if (err) 529 return err; 530 531 key.rsc = MLX5_SGMT_TYPE_SND_BUFF; 532 key.num_of_obj2 = MLX5_RSC_DUMP_ALL; 533 534 err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg); 535 if (err) 536 return err; 537 538 err = mlx5e_health_fmsg_named_obj_nest_end(fmsg); 539 if (err) 540 return err; 541 542 return mlx5e_health_fmsg_named_obj_nest_end(fmsg); 543 } 544 545 static int mlx5e_rx_reporter_dump_rq(struct mlx5e_priv *priv, struct devlink_fmsg *fmsg, 546 void *ctx) 547 { 548 struct mlx5_rsc_key key = {}; 549 struct mlx5e_rq *rq = ctx; 550 int err; 551 552 if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) 553 return 0; 554 555 err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "RX Slice"); 556 if (err) 557 return err; 558 559 key.size = PAGE_SIZE; 560 key.rsc = MLX5_SGMT_TYPE_RX_SLICE_ALL; 561 err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg); 562 if (err) 563 return err; 564 565 err = mlx5e_health_fmsg_named_obj_nest_end(fmsg); 566 if (err) 567 return err; 568 569 err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "RQ"); 570 if (err) 571 return err; 572 573 err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "QPC"); 574 if (err) 575 return err; 576 577 key.rsc = MLX5_SGMT_TYPE_FULL_QPC; 578 key.index1 = rq->rqn; 579 key.num_of_obj1 = 1; 580 581 err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg); 582 if (err) 583 return err; 584 585 err = mlx5e_health_fmsg_named_obj_nest_end(fmsg); 586 if (err) 587 return err; 588 589 err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "receive_buff"); 590 if (err) 591 return err; 592 593 key.rsc = MLX5_SGMT_TYPE_RCV_BUFF; 594 key.num_of_obj2 = MLX5_RSC_DUMP_ALL; 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 return mlx5e_health_fmsg_named_obj_nest_end(fmsg); 604 } 605 606 static int mlx5e_rx_reporter_dump_all_rqs(struct mlx5e_priv *priv, 607 struct devlink_fmsg *fmsg) 608 { 609 struct mlx5e_ptp *ptp_ch = priv->channels.ptp; 610 struct mlx5_rsc_key key = {}; 611 int i, err; 612 613 if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) 614 return 0; 615 616 err = mlx5e_health_fmsg_named_obj_nest_start(fmsg, "RX Slice"); 617 if (err) 618 return err; 619 620 key.size = PAGE_SIZE; 621 key.rsc = MLX5_SGMT_TYPE_RX_SLICE_ALL; 622 err = mlx5e_health_rsc_fmsg_dump(priv, &key, fmsg); 623 if (err) 624 return err; 625 626 err = mlx5e_health_fmsg_named_obj_nest_end(fmsg); 627 if (err) 628 return err; 629 630 err = devlink_fmsg_arr_pair_nest_start(fmsg, "RQs"); 631 if (err) 632 return err; 633 634 for (i = 0; i < priv->channels.num; i++) { 635 struct mlx5e_rq *rq = &priv->channels.c[i]->rq; 636 637 err = mlx5e_health_queue_dump(priv, fmsg, rq->rqn, "RQ"); 638 if (err) 639 return err; 640 } 641 642 if (ptp_ch && test_bit(MLX5E_PTP_STATE_RX, ptp_ch->state)) { 643 err = mlx5e_health_queue_dump(priv, fmsg, ptp_ch->rq.rqn, "PTP RQ"); 644 if (err) 645 return err; 646 } 647 648 return devlink_fmsg_arr_pair_nest_end(fmsg); 649 } 650 651 static int mlx5e_rx_reporter_dump_from_ctx(struct mlx5e_priv *priv, 652 struct mlx5e_err_ctx *err_ctx, 653 struct devlink_fmsg *fmsg) 654 { 655 return err_ctx->dump(priv, fmsg, err_ctx->ctx); 656 } 657 658 static int mlx5e_rx_reporter_dump(struct devlink_health_reporter *reporter, 659 struct devlink_fmsg *fmsg, void *context, 660 struct netlink_ext_ack *extack) 661 { 662 struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter); 663 struct mlx5e_err_ctx *err_ctx = context; 664 665 return err_ctx ? mlx5e_rx_reporter_dump_from_ctx(priv, err_ctx, fmsg) : 666 mlx5e_rx_reporter_dump_all_rqs(priv, fmsg); 667 } 668 669 void mlx5e_reporter_rx_timeout(struct mlx5e_rq *rq) 670 { 671 char icosq_str[MLX5E_REPORTER_PER_Q_MAX_LEN] = {}; 672 char err_str[MLX5E_REPORTER_PER_Q_MAX_LEN]; 673 struct mlx5e_icosq *icosq = rq->icosq; 674 struct mlx5e_priv *priv = rq->priv; 675 struct mlx5e_err_ctx err_ctx = {}; 676 677 err_ctx.ctx = rq; 678 err_ctx.recover = mlx5e_rx_reporter_timeout_recover; 679 err_ctx.dump = mlx5e_rx_reporter_dump_rq; 680 681 if (icosq) 682 snprintf(icosq_str, sizeof(icosq_str), "ICOSQ: 0x%x, ", icosq->sqn); 683 snprintf(err_str, sizeof(err_str), 684 "RX timeout on channel: %d, %sRQ: 0x%x, CQ: 0x%x", 685 rq->ix, icosq_str, rq->rqn, rq->cq.mcq.cqn); 686 687 mlx5e_health_report(priv, priv->rx_reporter, err_str, &err_ctx); 688 } 689 690 void mlx5e_reporter_rq_cqe_err(struct mlx5e_rq *rq) 691 { 692 char err_str[MLX5E_REPORTER_PER_Q_MAX_LEN]; 693 struct mlx5e_priv *priv = rq->priv; 694 struct mlx5e_err_ctx err_ctx = {}; 695 696 err_ctx.ctx = rq; 697 err_ctx.recover = mlx5e_rx_reporter_err_rq_cqe_recover; 698 err_ctx.dump = mlx5e_rx_reporter_dump_rq; 699 snprintf(err_str, sizeof(err_str), "ERR CQE on RQ: 0x%x", rq->rqn); 700 701 mlx5e_health_report(priv, priv->rx_reporter, err_str, &err_ctx); 702 } 703 704 void mlx5e_reporter_icosq_cqe_err(struct mlx5e_icosq *icosq) 705 { 706 struct mlx5e_priv *priv = icosq->channel->priv; 707 char err_str[MLX5E_REPORTER_PER_Q_MAX_LEN]; 708 struct mlx5e_err_ctx err_ctx = {}; 709 710 err_ctx.ctx = icosq; 711 err_ctx.recover = mlx5e_rx_reporter_err_icosq_cqe_recover; 712 err_ctx.dump = mlx5e_rx_reporter_dump_icosq; 713 snprintf(err_str, sizeof(err_str), "ERR CQE on ICOSQ: 0x%x", icosq->sqn); 714 715 mlx5e_health_report(priv, priv->rx_reporter, err_str, &err_ctx); 716 } 717 718 void mlx5e_reporter_icosq_suspend_recovery(struct mlx5e_channel *c) 719 { 720 mutex_lock(&c->icosq_recovery_lock); 721 } 722 723 void mlx5e_reporter_icosq_resume_recovery(struct mlx5e_channel *c) 724 { 725 mutex_unlock(&c->icosq_recovery_lock); 726 } 727 728 static const struct devlink_health_reporter_ops mlx5_rx_reporter_ops = { 729 .name = "rx", 730 .recover = mlx5e_rx_reporter_recover, 731 .diagnose = mlx5e_rx_reporter_diagnose, 732 .dump = mlx5e_rx_reporter_dump, 733 }; 734 735 #define MLX5E_REPORTER_RX_GRACEFUL_PERIOD 500 736 737 void mlx5e_reporter_rx_create(struct mlx5e_priv *priv) 738 { 739 struct devlink_health_reporter *reporter; 740 741 reporter = devlink_port_health_reporter_create(priv->netdev->devlink_port, 742 &mlx5_rx_reporter_ops, 743 MLX5E_REPORTER_RX_GRACEFUL_PERIOD, priv); 744 if (IS_ERR(reporter)) { 745 netdev_warn(priv->netdev, "Failed to create rx reporter, err = %ld\n", 746 PTR_ERR(reporter)); 747 return; 748 } 749 priv->rx_reporter = reporter; 750 } 751 752 void mlx5e_reporter_rx_destroy(struct mlx5e_priv *priv) 753 { 754 if (!priv->rx_reporter) 755 return; 756 757 devlink_health_reporter_destroy(priv->rx_reporter); 758 priv->rx_reporter = NULL; 759 } 760