1 /* 2 * Copyright (c) 2015-2024, Broadcom. All rights reserved. The term 3 * Broadcom refers to Broadcom Limited and/or its subsidiaries. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Description: statistics related functions 29 */ 30 31 #include "bnxt_re.h" 32 #include "bnxt.h" 33 34 int bnxt_re_get_flow_stats_from_service_pf(struct bnxt_re_dev *rdev, 35 struct bnxt_re_flow_counters *stats, 36 struct bnxt_qplib_query_stats_info *sinfo) 37 { 38 struct hwrm_cfa_flow_stats_output resp = {}; 39 struct hwrm_cfa_flow_stats_input req = {}; 40 struct bnxt_en_dev *en_dev = rdev->en_dev; 41 struct bnxt_fw_msg fw_msg = {}; 42 u16 target_id; 43 int rc = 0; 44 45 if (sinfo->function_id == 0xFFFFFFFF) 46 target_id = -1; 47 else 48 target_id = sinfo->function_id + 1; 49 50 /* Issue HWRM cmd to read flow counters for CNP tx and rx */ 51 bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_CFA_FLOW_STATS, -1, target_id); 52 req.num_flows = cpu_to_le16(6); 53 req.flow_handle_0 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_CNP_CNT); 54 req.flow_handle_1 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_CNP_CNT | 55 HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_DIR_RX); 56 req.flow_handle_2 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_ROCEV1_CNT); 57 req.flow_handle_3 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_ROCEV1_CNT | 58 HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_DIR_RX); 59 req.flow_handle_4 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_ROCEV2_CNT); 60 req.flow_handle_5 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_ROCEV2_CNT | 61 HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_DIR_RX); 62 bnxt_re_fill_fw_msg(&fw_msg, &req, sizeof(req), &resp, 63 sizeof(resp), BNXT_RE_HWRM_CMD_TIMEOUT(rdev)); 64 rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); 65 if (rc) { 66 dev_err(rdev_to_dev(rdev), 67 "Failed to get CFA Flow stats : rc = 0x%x\n", rc); 68 return rc; 69 } 70 71 stats->cnp_stats.cnp_tx_pkts = le64_to_cpu(resp.packet_0); 72 stats->cnp_stats.cnp_tx_bytes = le64_to_cpu(resp.byte_0); 73 stats->cnp_stats.cnp_rx_pkts = le64_to_cpu(resp.packet_1); 74 stats->cnp_stats.cnp_rx_bytes = le64_to_cpu(resp.byte_1); 75 76 stats->ro_stats.tx_pkts = le64_to_cpu(resp.packet_2) + 77 le64_to_cpu(resp.packet_4); 78 stats->ro_stats.tx_bytes = le64_to_cpu(resp.byte_2) + 79 le64_to_cpu(resp.byte_4); 80 stats->ro_stats.rx_pkts = le64_to_cpu(resp.packet_3) + 81 le64_to_cpu(resp.packet_5); 82 stats->ro_stats.rx_bytes = le64_to_cpu(resp.byte_3) + 83 le64_to_cpu(resp.byte_5); 84 85 return 0; 86 } 87 88 int bnxt_re_get_qos_stats(struct bnxt_re_dev *rdev) 89 { 90 struct bnxt_re_ro_counters roce_only_tmp[2] = {{}, {}}; 91 struct bnxt_re_cnp_counters tmp_counters[2] = {{}, {}}; 92 struct hwrm_cfa_flow_stats_output resp = {}; 93 struct hwrm_cfa_flow_stats_input req = {}; 94 struct bnxt_en_dev *en_dev = rdev->en_dev; 95 struct bnxt_fw_msg fw_msg = {}; 96 struct bnxt_re_cc_stat *cnps; 97 struct bnxt_re_rstat *dstat; 98 int rc = 0; 99 u64 bytes; 100 u64 pkts; 101 102 /* Issue HWRM cmd to read flow counters for CNP tx and rx */ 103 bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_CFA_FLOW_STATS, -1, -1); 104 req.num_flows = cpu_to_le16(6); 105 req.flow_handle_0 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_CNP_CNT); 106 req.flow_handle_1 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_CNP_CNT | 107 HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_DIR_RX); 108 req.flow_handle_2 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_ROCEV1_CNT); 109 req.flow_handle_3 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_ROCEV1_CNT | 110 HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_DIR_RX); 111 req.flow_handle_4 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_ROCEV2_CNT); 112 req.flow_handle_5 = cpu_to_le16(HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_ROCEV2_CNT | 113 HWRM_CFA_FLOW_INFO_INPUT_FLOW_HANDLE_DIR_RX); 114 bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, 115 sizeof(resp), BNXT_RE_HWRM_CMD_TIMEOUT(rdev)); 116 rc = en_dev->en_ops->bnxt_send_fw_msg(en_dev, BNXT_ROCE_ULP, &fw_msg); 117 if (rc) { 118 dev_err(rdev_to_dev(rdev), 119 "Failed to get CFA Flow stats : rc = 0x%x\n", rc); 120 goto done; 121 } 122 123 tmp_counters[0].cnp_tx_pkts = le64_to_cpu(resp.packet_0); 124 tmp_counters[0].cnp_tx_bytes = le64_to_cpu(resp.byte_0); 125 tmp_counters[0].cnp_rx_pkts = le64_to_cpu(resp.packet_1); 126 tmp_counters[0].cnp_rx_bytes = le64_to_cpu(resp.byte_1); 127 128 roce_only_tmp[0].tx_pkts = le64_to_cpu(resp.packet_2) + 129 le64_to_cpu(resp.packet_4); 130 roce_only_tmp[0].tx_bytes = le64_to_cpu(resp.byte_2) + 131 le64_to_cpu(resp.byte_4); 132 roce_only_tmp[0].rx_pkts = le64_to_cpu(resp.packet_3) + 133 le64_to_cpu(resp.packet_5); 134 roce_only_tmp[0].rx_bytes = le64_to_cpu(resp.byte_3) + 135 le64_to_cpu(resp.byte_5); 136 137 cnps = &rdev->stats.cnps; 138 dstat = &rdev->stats.dstat; 139 if (!cnps->is_first) { 140 /* First query done.. */ 141 cnps->is_first = true; 142 cnps->prev[0].cnp_tx_pkts = tmp_counters[0].cnp_tx_pkts; 143 cnps->prev[0].cnp_tx_bytes = tmp_counters[0].cnp_tx_bytes; 144 cnps->prev[0].cnp_rx_pkts = tmp_counters[0].cnp_rx_pkts; 145 cnps->prev[0].cnp_rx_bytes = tmp_counters[0].cnp_rx_bytes; 146 147 cnps->prev[1].cnp_tx_pkts = tmp_counters[1].cnp_tx_pkts; 148 cnps->prev[1].cnp_tx_bytes = tmp_counters[1].cnp_tx_bytes; 149 cnps->prev[1].cnp_rx_pkts = tmp_counters[1].cnp_rx_pkts; 150 cnps->prev[1].cnp_rx_bytes = tmp_counters[1].cnp_rx_bytes; 151 152 dstat->prev[0].tx_pkts = roce_only_tmp[0].tx_pkts; 153 dstat->prev[0].tx_bytes = roce_only_tmp[0].tx_bytes; 154 dstat->prev[0].rx_pkts = roce_only_tmp[0].rx_pkts; 155 dstat->prev[0].rx_bytes = roce_only_tmp[0].rx_bytes; 156 157 dstat->prev[1].tx_pkts = roce_only_tmp[1].tx_pkts; 158 dstat->prev[1].tx_bytes = roce_only_tmp[1].tx_bytes; 159 dstat->prev[1].rx_pkts = roce_only_tmp[1].rx_pkts; 160 dstat->prev[1].rx_bytes = roce_only_tmp[1].rx_bytes; 161 } else { 162 u64 byte_mask, pkts_mask; 163 u64 diff; 164 165 byte_mask = bnxt_re_get_cfa_stat_mask(rdev->chip_ctx, 166 BYTE_MASK); 167 pkts_mask = bnxt_re_get_cfa_stat_mask(rdev->chip_ctx, 168 PKTS_MASK); 169 /* 170 * Calculate the number of cnp packets and use 171 * the value to calculate the CRC bytes. 172 * Multply pkts with 4 and add it to total bytes 173 */ 174 pkts = bnxt_re_stat_diff(tmp_counters[0].cnp_tx_pkts, 175 &cnps->prev[0].cnp_tx_pkts, 176 pkts_mask); 177 cnps->cur[0].cnp_tx_pkts += pkts; 178 diff = bnxt_re_stat_diff(tmp_counters[0].cnp_tx_bytes, 179 &cnps->prev[0].cnp_tx_bytes, 180 byte_mask); 181 bytes = diff + pkts * 4; 182 cnps->cur[0].cnp_tx_bytes += bytes; 183 pkts = bnxt_re_stat_diff(tmp_counters[0].cnp_rx_pkts, 184 &cnps->prev[0].cnp_rx_pkts, 185 pkts_mask); 186 cnps->cur[0].cnp_rx_pkts += pkts; 187 bytes = bnxt_re_stat_diff(tmp_counters[0].cnp_rx_bytes, 188 &cnps->prev[0].cnp_rx_bytes, 189 byte_mask); 190 cnps->cur[0].cnp_rx_bytes += bytes; 191 192 /* 193 * Calculate the number of cnp packets and use 194 * the value to calculate the CRC bytes. 195 * Multply pkts with 4 and add it to total bytes 196 */ 197 pkts = bnxt_re_stat_diff(tmp_counters[1].cnp_tx_pkts, 198 &cnps->prev[1].cnp_tx_pkts, 199 pkts_mask); 200 cnps->cur[1].cnp_tx_pkts += pkts; 201 diff = bnxt_re_stat_diff(tmp_counters[1].cnp_tx_bytes, 202 &cnps->prev[1].cnp_tx_bytes, 203 byte_mask); 204 cnps->cur[1].cnp_tx_bytes += diff + pkts * 4; 205 pkts = bnxt_re_stat_diff(tmp_counters[1].cnp_rx_pkts, 206 &cnps->prev[1].cnp_rx_pkts, 207 pkts_mask); 208 cnps->cur[1].cnp_rx_pkts += pkts; 209 bytes = bnxt_re_stat_diff(tmp_counters[1].cnp_rx_bytes, 210 &cnps->prev[1].cnp_rx_bytes, 211 byte_mask); 212 cnps->cur[1].cnp_rx_bytes += bytes; 213 214 pkts = bnxt_re_stat_diff(roce_only_tmp[0].tx_pkts, 215 &dstat->prev[0].tx_pkts, 216 pkts_mask); 217 dstat->cur[0].tx_pkts += pkts; 218 diff = bnxt_re_stat_diff(roce_only_tmp[0].tx_bytes, 219 &dstat->prev[0].tx_bytes, 220 byte_mask); 221 dstat->cur[0].tx_bytes += diff + pkts * 4; 222 pkts = bnxt_re_stat_diff(roce_only_tmp[0].rx_pkts, 223 &dstat->prev[0].rx_pkts, 224 pkts_mask); 225 dstat->cur[0].rx_pkts += pkts; 226 227 bytes = bnxt_re_stat_diff(roce_only_tmp[0].rx_bytes, 228 &dstat->prev[0].rx_bytes, 229 byte_mask); 230 dstat->cur[0].rx_bytes += bytes; 231 pkts = bnxt_re_stat_diff(roce_only_tmp[1].tx_pkts, 232 &dstat->prev[1].tx_pkts, 233 pkts_mask); 234 dstat->cur[1].tx_pkts += pkts; 235 diff = bnxt_re_stat_diff(roce_only_tmp[1].tx_bytes, 236 &dstat->prev[1].tx_bytes, 237 byte_mask); 238 dstat->cur[1].tx_bytes += diff + pkts * 4; 239 pkts = bnxt_re_stat_diff(roce_only_tmp[1].rx_pkts, 240 &dstat->prev[1].rx_pkts, 241 pkts_mask); 242 dstat->cur[1].rx_pkts += pkts; 243 bytes = bnxt_re_stat_diff(roce_only_tmp[1].rx_bytes, 244 &dstat->prev[1].rx_bytes, 245 byte_mask); 246 dstat->cur[1].rx_bytes += bytes; 247 } 248 done: 249 return rc; 250 } 251 252 static void bnxt_re_copy_ext_stats(struct bnxt_re_dev *rdev, 253 u8 indx, struct bnxt_qplib_ext_stat *s) 254 { 255 struct bnxt_re_ext_roce_stats *e_errs; 256 struct bnxt_re_cnp_counters *cnp; 257 struct bnxt_re_ext_rstat *ext_d; 258 struct bnxt_re_ro_counters *ro; 259 260 cnp = &rdev->stats.cnps.cur[indx]; 261 ro = &rdev->stats.dstat.cur[indx]; 262 ext_d = &rdev->stats.dstat.ext_rstat[indx]; 263 e_errs = &rdev->stats.dstat.e_errs; 264 265 cnp->cnp_tx_pkts = s->tx_cnp; 266 cnp->cnp_rx_pkts = s->rx_cnp; 267 /* In bonding mode do not duplicate other stats */ 268 if (indx) 269 return; 270 cnp->ecn_marked = s->rx_ecn_marked; 271 272 ro->tx_pkts = s->tx_roce_pkts; 273 ro->tx_bytes = s->tx_roce_bytes; 274 ro->rx_pkts = s->rx_roce_pkts; 275 ro->rx_bytes = s->rx_roce_bytes; 276 277 ext_d->tx.atomic_req = s->tx_atomic_req; 278 ext_d->tx.read_req = s->tx_read_req; 279 ext_d->tx.read_resp = s->tx_read_res; 280 ext_d->tx.write_req = s->tx_write_req; 281 ext_d->tx.send_req = s->tx_send_req; 282 ext_d->rx.atomic_req = s->rx_atomic_req; 283 ext_d->rx.read_req = s->rx_read_req; 284 ext_d->rx.read_resp = s->rx_read_res; 285 ext_d->rx.write_req = s->rx_write_req; 286 ext_d->rx.send_req = s->rx_send_req; 287 ext_d->grx.rx_pkts = s->rx_roce_good_pkts; 288 ext_d->grx.rx_bytes = s->rx_roce_good_bytes; 289 ext_d->rx_dcn_payload_cut = s->rx_dcn_payload_cut; 290 ext_d->te_bypassed = s->te_bypassed; 291 e_errs->oob = s->rx_out_of_buffer; 292 e_errs->oos = s->rx_out_of_sequence; 293 e_errs->seq_err_naks_rcvd = s->seq_err_naks_rcvd; 294 e_errs->rnr_naks_rcvd = s->rnr_naks_rcvd; 295 e_errs->missing_resp = s->missing_resp; 296 e_errs->to_retransmits = s->to_retransmits; 297 e_errs->dup_req = s->dup_req; 298 } 299 300 static int bnxt_re_get_ext_stat(struct bnxt_re_dev *rdev) 301 { 302 struct bnxt_qplib_ext_stat estat[2] = {{}, {}}; 303 struct bnxt_qplib_query_stats_info sinfo; 304 u32 fid; 305 int rc; 306 307 fid = PCI_FUNC(rdev->en_dev->pdev->devfn); 308 /* Set default values for sinfo */ 309 sinfo.function_id = 0xFFFFFFFF; 310 sinfo.collection_id = 0xFF; 311 sinfo.vf_valid = false; 312 rc = bnxt_qplib_qext_stat(&rdev->rcfw, fid, &estat[0], &sinfo); 313 if (rc) 314 goto done; 315 bnxt_re_copy_ext_stats(rdev, 0, &estat[0]); 316 317 done: 318 return rc; 319 } 320 321 static void bnxt_re_copy_rstat(struct bnxt_re_rdata_counters *d, 322 struct ctx_hw_stats_ext *s, 323 bool is_thor) 324 { 325 d->tx_ucast_pkts = le64_to_cpu(s->tx_ucast_pkts); 326 d->tx_mcast_pkts = le64_to_cpu(s->tx_mcast_pkts); 327 d->tx_bcast_pkts = le64_to_cpu(s->tx_bcast_pkts); 328 d->tx_discard_pkts = le64_to_cpu(s->tx_discard_pkts); 329 d->tx_error_pkts = le64_to_cpu(s->tx_error_pkts); 330 d->tx_ucast_bytes = le64_to_cpu(s->tx_ucast_bytes); 331 /* Add four bytes of CRC bytes per packet */ 332 d->tx_ucast_bytes += d->tx_ucast_pkts * 4; 333 d->tx_mcast_bytes = le64_to_cpu(s->tx_mcast_bytes); 334 d->tx_bcast_bytes = le64_to_cpu(s->tx_bcast_bytes); 335 d->rx_ucast_pkts = le64_to_cpu(s->rx_ucast_pkts); 336 d->rx_mcast_pkts = le64_to_cpu(s->rx_mcast_pkts); 337 d->rx_bcast_pkts = le64_to_cpu(s->rx_bcast_pkts); 338 d->rx_discard_pkts = le64_to_cpu(s->rx_discard_pkts); 339 d->rx_error_pkts = le64_to_cpu(s->rx_error_pkts); 340 d->rx_ucast_bytes = le64_to_cpu(s->rx_ucast_bytes); 341 d->rx_mcast_bytes = le64_to_cpu(s->rx_mcast_bytes); 342 d->rx_bcast_bytes = le64_to_cpu(s->rx_bcast_bytes); 343 if (is_thor) { 344 d->rx_agg_pkts = le64_to_cpu(s->rx_tpa_pkt); 345 d->rx_agg_bytes = le64_to_cpu(s->rx_tpa_bytes); 346 d->rx_agg_events = le64_to_cpu(s->rx_tpa_events); 347 d->rx_agg_aborts = le64_to_cpu(s->rx_tpa_errors); 348 } 349 } 350 351 static void bnxt_re_get_roce_data_stats(struct bnxt_re_dev *rdev) 352 { 353 bool is_thor = _is_chip_gen_p5_p7(rdev->chip_ctx); 354 struct bnxt_re_rdata_counters *rstat; 355 356 rstat = &rdev->stats.dstat.rstat[0]; 357 bnxt_re_copy_rstat(rstat, rdev->qplib_res.hctx->stats.dma, is_thor); 358 359 } 360 361 int bnxt_re_get_device_stats(struct bnxt_re_dev *rdev) 362 { 363 struct bnxt_qplib_query_stats_info sinfo; 364 int rc = 0; 365 366 /* Stats are in 1s cadence */ 367 if (test_bit(BNXT_RE_FLAG_ISSUE_CFA_FLOW_STATS, &rdev->flags)) { 368 if (bnxt_ext_stats_supported(rdev->chip_ctx, rdev->dev_attr->dev_cap_flags, 369 rdev->is_virtfn)) 370 rc = bnxt_re_get_ext_stat(rdev); 371 else 372 rc = bnxt_re_get_qos_stats(rdev); 373 374 if (rc && rc != -ENOMEM) 375 clear_bit(BNXT_RE_FLAG_ISSUE_CFA_FLOW_STATS, 376 &rdev->flags); 377 } 378 379 if (test_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS, &rdev->flags)) { 380 bnxt_re_get_roce_data_stats(rdev); 381 382 /* Set default values for sinfo */ 383 sinfo.function_id = 0xFFFFFFFF; 384 sinfo.collection_id = 0xFF; 385 sinfo.vf_valid = false; 386 rc = bnxt_qplib_get_roce_error_stats(&rdev->rcfw, 387 &rdev->stats.dstat.errs, 388 &sinfo); 389 if (rc && rc != -ENOMEM) 390 clear_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS, 391 &rdev->flags); 392 } 393 394 return rc; 395 } 396 397 static const char * const bnxt_re_stat_descs[] = { 398 "link_state", 399 "max_qp", 400 "max_srq", 401 "max_cq", 402 "max_mr", 403 "max_mw", 404 "max_ah", 405 "max_pd", 406 "active_qp", 407 "active_rc_qp", 408 "active_ud_qp", 409 "active_srq", 410 "active_cq", 411 "active_mr", 412 "active_mw", 413 "active_ah", 414 "active_pd", 415 "qp_watermark", 416 "rc_qp_watermark", 417 "ud_qp_watermark", 418 "srq_watermark", 419 "cq_watermark", 420 "mr_watermark", 421 "mw_watermark", 422 "ah_watermark", 423 "pd_watermark", 424 "resize_cq_count", 425 "hw_retransmission", 426 "recoverable_errors", 427 "rx_pkts", 428 "rx_bytes", 429 "tx_pkts", 430 "tx_bytes", 431 "cnp_tx_pkts", 432 "cnp_tx_bytes", 433 "cnp_rx_pkts", 434 "cnp_rx_bytes", 435 "roce_only_rx_pkts", 436 "roce_only_rx_bytes", 437 "roce_only_tx_pkts", 438 "roce_only_tx_bytes", 439 "rx_roce_error_pkts", 440 "rx_roce_discard_pkts", 441 "tx_roce_error_pkts", 442 "tx_roce_discards_pkts", 443 "res_oob_drop_count", 444 "tx_atomic_req", 445 "rx_atomic_req", 446 "tx_read_req", 447 "tx_read_resp", 448 "rx_read_req", 449 "rx_read_resp", 450 "tx_write_req", 451 "rx_write_req", 452 "tx_send_req", 453 "rx_send_req", 454 "rx_good_pkts", 455 "rx_good_bytes", 456 "rx_dcn_payload_cut", 457 "te_bypassed", 458 "rx_ecn_marked_pkts", 459 "max_retry_exceeded", 460 "to_retransmits", 461 "seq_err_naks_rcvd", 462 "rnr_naks_rcvd", 463 "missing_resp", 464 "dup_reqs", 465 "unrecoverable_err", 466 "bad_resp_err", 467 "local_qp_op_err", 468 "local_protection_err", 469 "mem_mgmt_op_err", 470 "remote_invalid_req_err", 471 "remote_access_err", 472 "remote_op_err", 473 "res_exceed_max", 474 "res_length_mismatch", 475 "res_exceeds_wqe", 476 "res_opcode_err", 477 "res_rx_invalid_rkey", 478 "res_rx_domain_err", 479 "res_rx_no_perm", 480 "res_rx_range_err", 481 "res_tx_invalid_rkey", 482 "res_tx_domain_err", 483 "res_tx_no_perm", 484 "res_tx_range_err", 485 "res_irrq_oflow", 486 "res_unsup_opcode", 487 "res_unaligned_atomic", 488 "res_rem_inv_err", 489 "res_mem_error64", 490 "res_srq_err", 491 "res_cmp_err", 492 "res_invalid_dup_rkey", 493 "res_wqe_format_err", 494 "res_cq_load_err", 495 "res_srq_load_err", 496 "res_tx_pci_err", 497 "res_rx_pci_err", 498 "res_oos_drop_count", 499 "num_irq_started", 500 "num_irq_stopped", 501 "poll_in_intr_en", 502 "poll_in_intr_dis", 503 "cmdq_full_dbg_cnt", 504 "fw_service_prof_type_sup", 505 "dbq_int_recv", 506 "dbq_int_en", 507 "dbq_pacing_resched", 508 "dbq_pacing_complete", 509 "dbq_pacing_alerts", 510 "dbq_dbr_fifo_reg" 511 512 }; 513 514 static void bnxt_re_print_ext_stat(struct bnxt_re_dev *rdev, 515 struct rdma_hw_stats *stats) 516 { 517 struct bnxt_re_cnp_counters *cnp; 518 struct bnxt_re_ext_rstat *ext_s; 519 520 ext_s = &rdev->stats.dstat.ext_rstat[0]; 521 cnp = &rdev->stats.cnps.cur[0]; 522 523 stats->value[BNXT_RE_TX_ATOMIC_REQ] = ext_s->tx.atomic_req; 524 stats->value[BNXT_RE_RX_ATOMIC_REQ] = ext_s->rx.atomic_req; 525 stats->value[BNXT_RE_TX_READ_REQ] = ext_s->tx.read_req; 526 stats->value[BNXT_RE_TX_READ_RESP] = ext_s->tx.read_resp; 527 stats->value[BNXT_RE_RX_READ_REQ] = ext_s->rx.read_req; 528 stats->value[BNXT_RE_RX_READ_RESP] = ext_s->rx.read_resp; 529 stats->value[BNXT_RE_TX_WRITE_REQ] = ext_s->tx.write_req; 530 stats->value[BNXT_RE_RX_WRITE_REQ] = ext_s->rx.write_req; 531 stats->value[BNXT_RE_TX_SEND_REQ] = ext_s->tx.send_req; 532 stats->value[BNXT_RE_RX_SEND_REQ] = ext_s->rx.send_req; 533 stats->value[BNXT_RE_RX_GOOD_PKTS] = ext_s->grx.rx_pkts; 534 stats->value[BNXT_RE_RX_GOOD_BYTES] = ext_s->grx.rx_bytes; 535 if (_is_chip_p7(rdev->chip_ctx)) { 536 stats->value[BNXT_RE_RX_DCN_PAYLOAD_CUT] = ext_s->rx_dcn_payload_cut; 537 stats->value[BNXT_RE_TE_BYPASSED] = ext_s->te_bypassed; 538 } 539 stats->value[BNXT_RE_RX_ECN_MARKED_PKTS] = cnp->ecn_marked; 540 } 541 542 static void bnxt_re_print_roce_only_counters(struct bnxt_re_dev *rdev, 543 struct rdma_hw_stats *stats) 544 { 545 struct bnxt_re_ro_counters *roce_only = &rdev->stats.dstat.cur[0]; 546 547 stats->value[BNXT_RE_ROCE_ONLY_RX_PKTS] = roce_only->rx_pkts; 548 stats->value[BNXT_RE_ROCE_ONLY_RX_BYTES] = roce_only->rx_bytes; 549 stats->value[BNXT_RE_ROCE_ONLY_TX_PKTS] = roce_only->tx_pkts; 550 stats->value[BNXT_RE_ROCE_ONLY_TX_BYTES] = roce_only->tx_bytes; 551 } 552 553 static void bnxt_re_print_normal_total_counters(struct bnxt_re_dev *rdev, 554 struct rdma_hw_stats *stats) 555 { 556 struct bnxt_re_ro_counters *roce_only; 557 struct bnxt_re_cc_stat *cnps; 558 559 cnps = &rdev->stats.cnps; 560 roce_only = &rdev->stats.dstat.cur[0]; 561 562 stats->value[BNXT_RE_RX_PKTS] = cnps->cur[0].cnp_rx_pkts + roce_only->rx_pkts; 563 stats->value[BNXT_RE_RX_BYTES] = cnps->cur[0].cnp_rx_bytes + roce_only->rx_bytes; 564 stats->value[BNXT_RE_TX_PKTS] = cnps->cur[0].cnp_tx_pkts + roce_only->tx_pkts; 565 stats->value[BNXT_RE_TX_BYTES] = cnps->cur[0].cnp_tx_bytes + roce_only->tx_bytes; 566 } 567 568 static void bnxt_re_print_normal_counters(struct bnxt_re_dev *rdev, 569 struct rdma_hw_stats *rstats) 570 { 571 struct bnxt_re_rdata_counters *stats; 572 struct bnxt_re_cc_stat *cnps; 573 bool en_disp; 574 575 stats = &rdev->stats.dstat.rstat[0]; 576 cnps = &rdev->stats.cnps; 577 en_disp = !_is_chip_gen_p5_p7(rdev->chip_ctx); 578 579 bnxt_re_print_normal_total_counters(rdev, rstats); 580 if (!rdev->is_virtfn) { 581 rstats->value[BNXT_RE_CNP_TX_PKTS] = cnps->cur[0].cnp_tx_pkts; 582 if (en_disp) 583 rstats->value[BNXT_RE_CNP_TX_BYTES] = cnps->cur[0].cnp_tx_bytes; 584 rstats->value[BNXT_RE_CNP_RX_PKTS] = cnps->cur[0].cnp_rx_pkts; 585 if (en_disp) 586 rstats->value[BNXT_RE_CNP_RX_BYTES] = cnps->cur[0].cnp_rx_bytes; 587 } 588 /* Print RoCE only bytes.. CNP counters include RoCE packets also */ 589 bnxt_re_print_roce_only_counters(rdev, rstats); 590 591 rstats->value[BNXT_RE_RX_ROCE_ERROR_PKTS] = stats ? stats->rx_error_pkts : 0; 592 rstats->value[BNXT_RE_RX_ROCE_DISCARD_PKTS] = stats ? stats->rx_discard_pkts : 0; 593 if (!en_disp) { 594 rstats->value[BNXT_RE_TX_ROCE_ERROR_PKTS] = stats ? stats->tx_error_pkts : 0; 595 rstats->value[BNXT_RE_TX_ROCE_DISCARDS_PKTS] = stats ? stats->tx_discard_pkts : 0; 596 } 597 598 if (bnxt_ext_stats_supported(rdev->chip_ctx, rdev->dev_attr->dev_cap_flags, 599 rdev->is_virtfn)) { 600 rstats->value[BNXT_RE_RES_OOB_DROP_COUNT] = rdev->stats.dstat.e_errs.oob; 601 bnxt_re_print_ext_stat(rdev, rstats); 602 } 603 } 604 605 static void bnxt_re_copy_db_pacing_stats(struct bnxt_re_dev *rdev, 606 struct rdma_hw_stats *stats) 607 { 608 struct bnxt_re_dbr_sw_stats *dbr_sw_stats = rdev->dbr_sw_stats; 609 610 stats->value[BNXT_RE_DBQ_PACING_RESCHED] = dbr_sw_stats->dbq_pacing_resched; 611 stats->value[BNXT_RE_DBQ_PACING_CMPL] = dbr_sw_stats->dbq_pacing_complete; 612 stats->value[BNXT_RE_DBQ_PACING_ALERT] = dbr_sw_stats->dbq_pacing_alerts; 613 stats->value[BNXT_RE_DBQ_DBR_FIFO_REG] = readl_fbsd(rdev->en_dev->softc, 614 rdev->dbr_db_fifo_reg_off, 0); 615 } 616 617 int bnxt_re_get_hw_stats(struct ib_device *ibdev, 618 struct rdma_hw_stats *stats, 619 u8 port, int index) 620 { 621 struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev); 622 struct bnxt_re_ext_roce_stats *e_errs; 623 struct bnxt_re_rdata_counters *rstat; 624 struct bnxt_qplib_roce_stats *errs; 625 unsigned long tstamp_diff; 626 struct pci_dev *pdev; 627 int sched_msec; 628 int rc = 0; 629 630 if (!port || !stats) 631 return -EINVAL; 632 633 if (!rdev) 634 return -ENODEV; 635 636 if (!__bnxt_re_is_rdev_valid(rdev)) { 637 return -ENODEV; 638 } 639 640 pdev = rdev->en_dev->pdev; 641 errs = &rdev->stats.dstat.errs; 642 rstat = &rdev->stats.dstat.rstat[0]; 643 e_errs = &rdev->stats.dstat.e_errs; 644 #define BNXT_RE_STATS_CTX_UPDATE_TIMER 250 645 sched_msec = BNXT_RE_STATS_CTX_UPDATE_TIMER; 646 tstamp_diff = jiffies - rdev->stats.read_tstamp; 647 if (test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags)) { 648 if (/* restrict_stats && */ tstamp_diff < msecs_to_jiffies(sched_msec)) 649 goto skip_query; 650 rc = bnxt_re_get_device_stats(rdev); 651 if (rc) 652 dev_err(rdev_to_dev(rdev), 653 "Failed to query device stats\n"); 654 rdev->stats.read_tstamp = jiffies; 655 } 656 657 if (rdev->dbr_pacing) 658 bnxt_re_copy_db_pacing_stats(rdev, stats); 659 660 skip_query: 661 662 if (rdev->netdev) 663 stats->value[BNXT_RE_LINK_STATE] = bnxt_re_link_state(rdev); 664 stats->value[BNXT_RE_MAX_QP] = rdev->dev_attr->max_qp; 665 stats->value[BNXT_RE_MAX_SRQ] = rdev->dev_attr->max_srq; 666 stats->value[BNXT_RE_MAX_CQ] = rdev->dev_attr->max_cq; 667 stats->value[BNXT_RE_MAX_MR] = rdev->dev_attr->max_mr; 668 stats->value[BNXT_RE_MAX_MW] = rdev->dev_attr->max_mw; 669 stats->value[BNXT_RE_MAX_AH] = rdev->dev_attr->max_ah; 670 stats->value[BNXT_RE_MAX_PD] = rdev->dev_attr->max_pd; 671 stats->value[BNXT_RE_ACTIVE_QP] = atomic_read(&rdev->stats.rsors.qp_count); 672 stats->value[BNXT_RE_ACTIVE_RC_QP] = atomic_read(&rdev->stats.rsors.rc_qp_count); 673 stats->value[BNXT_RE_ACTIVE_UD_QP] = atomic_read(&rdev->stats.rsors.ud_qp_count); 674 stats->value[BNXT_RE_ACTIVE_SRQ] = atomic_read(&rdev->stats.rsors.srq_count); 675 stats->value[BNXT_RE_ACTIVE_CQ] = atomic_read(&rdev->stats.rsors.cq_count); 676 stats->value[BNXT_RE_ACTIVE_MR] = atomic_read(&rdev->stats.rsors.mr_count); 677 stats->value[BNXT_RE_ACTIVE_MW] = atomic_read(&rdev->stats.rsors.mw_count); 678 stats->value[BNXT_RE_ACTIVE_AH] = atomic_read(&rdev->stats.rsors.ah_count); 679 stats->value[BNXT_RE_ACTIVE_PD] = atomic_read(&rdev->stats.rsors.pd_count); 680 stats->value[BNXT_RE_QP_WATERMARK] = atomic_read(&rdev->stats.rsors.max_qp_count); 681 stats->value[BNXT_RE_RC_QP_WATERMARK] = atomic_read(&rdev->stats.rsors.max_rc_qp_count); 682 stats->value[BNXT_RE_UD_QP_WATERMARK] = atomic_read(&rdev->stats.rsors.max_ud_qp_count); 683 stats->value[BNXT_RE_SRQ_WATERMARK] = atomic_read(&rdev->stats.rsors.max_srq_count); 684 stats->value[BNXT_RE_CQ_WATERMARK] = atomic_read(&rdev->stats.rsors.max_cq_count); 685 stats->value[BNXT_RE_MR_WATERMARK] = atomic_read(&rdev->stats.rsors.max_mr_count); 686 stats->value[BNXT_RE_MW_WATERMARK] = atomic_read(&rdev->stats.rsors.max_mw_count); 687 stats->value[BNXT_RE_AH_WATERMARK] = atomic_read(&rdev->stats.rsors.max_ah_count); 688 stats->value[BNXT_RE_PD_WATERMARK] = atomic_read(&rdev->stats.rsors.max_pd_count); 689 stats->value[BNXT_RE_RESIZE_CQ_COUNT] = atomic_read(&rdev->stats.rsors.resize_count); 690 stats->value[BNXT_RE_HW_RETRANSMISSION] = BNXT_RE_HW_RETX(rdev->dev_attr->dev_cap_flags) ? 1 : 0; 691 stats->value[BNXT_RE_RECOVERABLE_ERRORS] = rstat ? rstat->tx_bcast_pkts : 0; 692 693 bnxt_re_print_normal_counters(rdev, stats); 694 695 696 stats->value[BNXT_RE_MAX_RETRY_EXCEEDED] = errs->max_retry_exceeded; 697 if (bnxt_ext_stats_supported(rdev->chip_ctx, rdev->dev_attr->dev_cap_flags, 698 rdev->is_virtfn) && 699 _is_hw_retx_supported(rdev->dev_attr->dev_cap_flags)) { 700 stats->value[BNXT_RE_TO_RETRANSMITS] = e_errs->to_retransmits; 701 stats->value[BNXT_RE_SEQ_ERR_NAKS_RCVD] = e_errs->seq_err_naks_rcvd; 702 stats->value[BNXT_RE_RNR_NAKS_RCVD] = e_errs->rnr_naks_rcvd; 703 stats->value[BNXT_RE_MISSING_RESP] = e_errs->missing_resp; 704 stats->value[BNXT_RE_DUP_REQS] = e_errs->dup_req; 705 } else { 706 stats->value[BNXT_RE_TO_RETRANSMITS] = errs->to_retransmits; 707 stats->value[BNXT_RE_SEQ_ERR_NAKS_RCVD] = errs->seq_err_naks_rcvd; 708 stats->value[BNXT_RE_RNR_NAKS_RCVD] = errs->rnr_naks_rcvd; 709 stats->value[BNXT_RE_MISSING_RESP] = errs->missing_resp; 710 stats->value[BNXT_RE_DUP_REQS] = errs->dup_req; 711 } 712 713 stats->value[BNXT_RE_UNRECOVERABLE_ERR] = errs->unrecoverable_err; 714 stats->value[BNXT_RE_BAD_RESP_ERR] = errs->bad_resp_err; 715 stats->value[BNXT_RE_LOCAL_QP_OP_ERR] = errs->local_qp_op_err; 716 stats->value[BNXT_RE_LOCAL_PROTECTION_ERR] = errs->local_protection_err; 717 stats->value[BNXT_RE_MEM_MGMT_OP_ERR] = errs->mem_mgmt_op_err; 718 stats->value[BNXT_RE_REMOTE_INVALID_REQ_ERR] = errs->remote_invalid_req_err; 719 stats->value[BNXT_RE_REMOTE_ACCESS_ERR] = errs->remote_access_err; 720 stats->value[BNXT_RE_REMOTE_OP_ERR] = errs->remote_op_err; 721 stats->value[BNXT_RE_RES_EXCEED_MAX] = errs->res_exceed_max; 722 stats->value[BNXT_RE_RES_LENGTH_MISMATCH] = errs->res_length_mismatch; 723 stats->value[BNXT_RE_RES_EXCEEDS_WQE] = errs->res_exceeds_wqe; 724 stats->value[BNXT_RE_RES_OPCODE_ERR] = errs->res_opcode_err; 725 stats->value[BNXT_RE_RES_RX_INVALID_RKEY] = errs->res_rx_invalid_rkey; 726 stats->value[BNXT_RE_RES_RX_DOMAIN_ERR] = errs->res_rx_domain_err; 727 stats->value[BNXT_RE_RES_RX_NO_PERM] = errs->res_rx_no_perm; 728 stats->value[BNXT_RE_RES_RX_RANGE_ERR] = errs->res_rx_range_err; 729 stats->value[BNXT_RE_RES_TX_INVALID_RKEY] = errs->res_tx_invalid_rkey; 730 stats->value[BNXT_RE_RES_TX_DOMAIN_ERR] = errs->res_tx_domain_err; 731 stats->value[BNXT_RE_RES_TX_NO_PERM] = errs->res_tx_no_perm; 732 stats->value[BNXT_RE_RES_TX_RANGE_ERR] = errs->res_tx_range_err; 733 stats->value[BNXT_RE_RES_IRRQ_OFLOW] = errs->res_irrq_oflow; 734 stats->value[BNXT_RE_RES_UNSUP_OPCODE] = errs->res_unsup_opcode; 735 stats->value[BNXT_RE_RES_UNALIGNED_ATOMIC] = errs->res_unaligned_atomic; 736 stats->value[BNXT_RE_RES_REM_INV_ERR] = errs->res_rem_inv_err; 737 stats->value[BNXT_RE_RES_MEM_ERROR64] = errs->res_mem_error; 738 stats->value[BNXT_RE_RES_SRQ_ERR] = errs->res_srq_err; 739 stats->value[BNXT_RE_RES_CMP_ERR] = errs->res_cmp_err; 740 stats->value[BNXT_RE_RES_INVALID_DUP_RKEY] = errs->res_invalid_dup_rkey; 741 stats->value[BNXT_RE_RES_WQE_FORMAT_ERR] = errs->res_wqe_format_err; 742 stats->value[BNXT_RE_RES_CQ_LOAD_ERR] = errs->res_cq_load_err; 743 stats->value[BNXT_RE_RES_SRQ_LOAD_ERR] = errs->res_srq_load_err; 744 stats->value[BNXT_RE_RES_TX_PCI_ERR] = errs->res_tx_pci_err; 745 stats->value[BNXT_RE_RES_RX_PCI_ERR] = errs->res_rx_pci_err; 746 747 748 if (bnxt_ext_stats_supported(rdev->chip_ctx, rdev->dev_attr->dev_cap_flags, 749 rdev->is_virtfn)) { 750 stats->value[BNXT_RE_RES_OOS_DROP_COUNT] = e_errs->oos; 751 } else { 752 /* Display on function 0 as OOS counters are chip-wide */ 753 if (PCI_FUNC(pdev->devfn) == 0) 754 stats->value[BNXT_RE_RES_OOS_DROP_COUNT] = errs->res_oos_drop_count; 755 } 756 stats->value[BNXT_RE_NUM_IRQ_STARTED] = rdev->rcfw.num_irq_started; 757 stats->value[BNXT_RE_NUM_IRQ_STOPPED] = rdev->rcfw.num_irq_stopped; 758 stats->value[BNXT_RE_POLL_IN_INTR_EN] = rdev->rcfw.poll_in_intr_en; 759 stats->value[BNXT_RE_POLL_IN_INTR_DIS] = rdev->rcfw.poll_in_intr_dis; 760 stats->value[BNXT_RE_CMDQ_FULL_DBG_CNT] = rdev->rcfw.cmdq_full_dbg; 761 if (!rdev->is_virtfn) 762 stats->value[BNXT_RE_FW_SERVICE_PROF_TYPE_SUP] = is_qport_service_type_supported(rdev); 763 764 return ARRAY_SIZE(bnxt_re_stat_descs); 765 } 766 767 struct rdma_hw_stats *bnxt_re_alloc_hw_port_stats(struct ib_device *ibdev, 768 u8 port_num) 769 { 770 return rdma_alloc_hw_stats_struct(bnxt_re_stat_descs, 771 ARRAY_SIZE(bnxt_re_stat_descs), 772 RDMA_HW_STATS_DEFAULT_LIFESPAN); 773 } 774