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