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