1 /*- 2 * Broadcom NetXtreme-C/E network driver. 3 * 4 * Copyright (c) 2016 Broadcom, All Rights Reserved. 5 * The term Broadcom refers to Broadcom Limited and/or its subsidiaries 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 * THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/types.h> 33 #include <sys/sysctl.h> 34 35 #include "bnxt.h" 36 #include "bnxt_hwrm.h" 37 #include "bnxt_sysctl.h" 38 39 static int bnxt_vlan_only_sysctl(SYSCTL_HANDLER_ARGS); 40 /* 41 * We want to create: 42 * dev.bnxt.0.hwstats.txq0 43 * dev.bnxt.0.hwstats.txq0.txmbufs 44 * dev.bnxt.0.hwstats.rxq0 45 * dev.bnxt.0.hwstats.txq0.rxmbufs 46 * so the hwstats ctx list needs to be created in attach_post and populated 47 * during init. 48 * 49 * Then, it needs to be cleaned up in stop. 50 */ 51 52 int 53 bnxt_init_sysctl_ctx(struct bnxt_softc *softc) 54 { 55 struct sysctl_ctx_list *ctx; 56 57 sysctl_ctx_init(&softc->hw_stats); 58 ctx = device_get_sysctl_ctx(softc->dev); 59 softc->hw_stats_oid = SYSCTL_ADD_NODE(ctx, 60 SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO, 61 "hwstats", CTLFLAG_RD, 0, "hardware statistics"); 62 if (!softc->hw_stats_oid) { 63 sysctl_ctx_free(&softc->hw_stats); 64 return ENOMEM; 65 } 66 67 sysctl_ctx_init(&softc->ver_info->ver_ctx); 68 ctx = device_get_sysctl_ctx(softc->dev); 69 softc->ver_info->ver_oid = SYSCTL_ADD_NODE(ctx, 70 SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO, 71 "ver", CTLFLAG_RD, 0, "hardware/firmware version information"); 72 if (!softc->ver_info->ver_oid) { 73 sysctl_ctx_free(&softc->ver_info->ver_ctx); 74 return ENOMEM; 75 } 76 77 sysctl_ctx_init(&softc->nvm_info->nvm_ctx); 78 ctx = device_get_sysctl_ctx(softc->dev); 79 softc->nvm_info->nvm_oid = SYSCTL_ADD_NODE(ctx, 80 SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO, 81 "nvram", CTLFLAG_RD, 0, "nvram information"); 82 if (!softc->nvm_info->nvm_oid) { 83 sysctl_ctx_free(&softc->nvm_info->nvm_ctx); 84 return ENOMEM; 85 } 86 87 return 0; 88 } 89 90 int 91 bnxt_free_sysctl_ctx(struct bnxt_softc *softc) 92 { 93 int orc; 94 int rc = 0; 95 96 if (softc->hw_stats_oid != NULL) { 97 orc = sysctl_ctx_free(&softc->hw_stats); 98 if (orc) 99 rc = orc; 100 else 101 softc->hw_stats_oid = NULL; 102 } 103 if (softc->ver_info->ver_oid != NULL) { 104 orc = sysctl_ctx_free(&softc->ver_info->ver_ctx); 105 if (orc) 106 rc = orc; 107 else 108 softc->ver_info->ver_oid = NULL; 109 } 110 if (softc->nvm_info->nvm_oid != NULL) { 111 orc = sysctl_ctx_free(&softc->nvm_info->nvm_ctx); 112 if (orc) 113 rc = orc; 114 else 115 softc->nvm_info->nvm_oid = NULL; 116 } 117 118 return rc; 119 } 120 121 int 122 bnxt_create_tx_sysctls(struct bnxt_softc *softc, int txr) 123 { 124 struct sysctl_oid *oid; 125 struct ctx_hw_stats *tx_stats = (void *)softc->tx_stats.idi_vaddr; 126 char name[32]; 127 char desc[64]; 128 129 sprintf(name, "txq%d", txr); 130 sprintf(desc, "transmit queue %d", txr); 131 oid = SYSCTL_ADD_NODE(&softc->hw_stats, 132 SYSCTL_CHILDREN(softc->hw_stats_oid), OID_AUTO, name, CTLFLAG_RD, 0, 133 desc); 134 if (!oid) 135 return ENOMEM; 136 137 138 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 139 "ucast_pkts", CTLFLAG_RD, &tx_stats[txr].tx_ucast_pkts, 140 "unicast packets sent"); 141 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 142 "mcast_pkts", CTLFLAG_RD, &tx_stats[txr].tx_mcast_pkts, 143 "multicast packets sent"); 144 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 145 "bcast_pkts", CTLFLAG_RD, &tx_stats[txr].tx_bcast_pkts, 146 "broadcast packets sent"); 147 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 148 "discard_pkts", CTLFLAG_RD, 149 &tx_stats[txr].tx_discard_pkts, "discarded transmit packets"); 150 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 151 "drop_pkts", CTLFLAG_RD, &tx_stats[txr].tx_drop_pkts, 152 "dropped transmit packets"); 153 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 154 "ucast_bytes", CTLFLAG_RD, &tx_stats[txr].tx_ucast_bytes, 155 "unicast bytes sent"); 156 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 157 "mcast_bytes", CTLFLAG_RD, &tx_stats[txr].tx_mcast_bytes, 158 "multicast bytes sent"); 159 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 160 "bcast_bytes", CTLFLAG_RD, &tx_stats[txr].tx_bcast_bytes, 161 "broadcast bytes sent"); 162 163 return 0; 164 } 165 166 int 167 bnxt_create_rx_sysctls(struct bnxt_softc *softc, int rxr) 168 { 169 struct sysctl_oid *oid; 170 struct ctx_hw_stats *rx_stats = (void *)softc->rx_stats.idi_vaddr; 171 char name[32]; 172 char desc[64]; 173 174 sprintf(name, "rxq%d", rxr); 175 sprintf(desc, "receive queue %d", rxr); 176 oid = SYSCTL_ADD_NODE(&softc->hw_stats, 177 SYSCTL_CHILDREN(softc->hw_stats_oid), OID_AUTO, name, CTLFLAG_RD, 0, 178 desc); 179 if (!oid) 180 return ENOMEM; 181 182 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 183 "ucast_pkts", CTLFLAG_RD, &rx_stats[rxr].rx_ucast_pkts, 184 "unicast packets received"); 185 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 186 "mcast_pkts", CTLFLAG_RD, &rx_stats[rxr].rx_mcast_pkts, 187 "multicast packets received"); 188 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 189 "bcast_pkts", CTLFLAG_RD, &rx_stats[rxr].rx_bcast_pkts, 190 "broadcast packets received"); 191 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 192 "discard_pkts", CTLFLAG_RD, 193 &rx_stats[rxr].rx_discard_pkts, "discarded receive packets"); 194 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 195 "drop_pkts", CTLFLAG_RD, &rx_stats[rxr].rx_drop_pkts, 196 "dropped receive packets"); 197 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 198 "ucast_bytes", CTLFLAG_RD, &rx_stats[rxr].rx_ucast_bytes, 199 "unicast bytes received"); 200 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 201 "mcast_bytes", CTLFLAG_RD, &rx_stats[rxr].rx_mcast_bytes, 202 "multicast bytes received"); 203 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 204 "bcast_bytes", CTLFLAG_RD, &rx_stats[rxr].rx_bcast_bytes, 205 "broadcast bytes received"); 206 207 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 208 "tpa_pkts", CTLFLAG_RD, &rx_stats[rxr].tpa_pkts, 209 "TPA packets"); 210 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 211 "tpa_bytes", CTLFLAG_RD, &rx_stats[rxr].tpa_bytes, 212 "TPA bytes"); 213 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 214 "tpa_events", CTLFLAG_RD, &rx_stats[rxr].tpa_events, 215 "TPA events"); 216 SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, 217 "tpa_aborts", CTLFLAG_RD, &rx_stats[rxr].tpa_aborts, 218 "TPA aborts"); 219 220 return 0; 221 } 222 223 static char *bnxt_chip_type[] = { 224 "ASIC", 225 "FPGA", 226 "Palladium", 227 "Unknown" 228 }; 229 #define MAX_CHIP_TYPE 3 230 231 static int 232 bnxt_package_ver_sysctl(SYSCTL_HANDLER_ARGS) 233 { 234 struct bnxt_softc *softc = arg1; 235 struct iflib_dma_info dma_data; 236 char *pkglog = NULL; 237 char *p; 238 char *next; 239 char unk[] = "<unknown>"; 240 char *buf = unk; 241 int rc; 242 int field; 243 uint16_t ordinal = BNX_DIR_ORDINAL_FIRST; 244 uint16_t index; 245 uint32_t data_len; 246 247 rc = bnxt_hwrm_nvm_find_dir_entry(softc, BNX_DIR_TYPE_PKG_LOG, 248 &ordinal, BNX_DIR_EXT_NONE, &index, false, 249 HWRM_NVM_FIND_DIR_ENTRY_INPUT_OPT_ORDINAL_EQ, 250 &data_len, NULL, NULL); 251 dma_data.idi_vaddr = NULL; 252 if (rc == 0 && data_len) { 253 rc = iflib_dma_alloc(softc->ctx, data_len, &dma_data, 254 BUS_DMA_NOWAIT); 255 if (rc == 0) { 256 rc = bnxt_hwrm_nvm_read(softc, index, 0, data_len, 257 &dma_data); 258 if (rc == 0) { 259 pkglog = dma_data.idi_vaddr; 260 /* NULL terminate (removes last \n) */ 261 pkglog[data_len-1] = 0; 262 263 /* Set p = start of last line */ 264 p = strrchr(pkglog, '\n'); 265 if (p == NULL) 266 p = pkglog; 267 268 /* Now find the correct tab delimited field */ 269 for (field = 0, next = p, 270 p = strsep(&next, "\t"); 271 field < 272 BNX_PKG_LOG_FIELD_IDX_PKG_VERSION && p; 273 p = strsep(&next, "\t")) { 274 field++; 275 } 276 if (field == BNX_PKG_LOG_FIELD_IDX_PKG_VERSION) 277 buf = p; 278 } 279 } 280 else 281 dma_data.idi_vaddr = NULL; 282 } 283 284 rc = sysctl_handle_string(oidp, buf, 0, req); 285 if (dma_data.idi_vaddr) 286 iflib_dma_free(&dma_data); 287 return rc; 288 } 289 290 static int 291 bnxt_hwrm_min_ver_sysctl(SYSCTL_HANDLER_ARGS) 292 { 293 struct bnxt_softc *softc = arg1; 294 char buf[16]; 295 uint8_t newver[3]; 296 int rc; 297 298 sprintf(buf, "%hhu.%hhu.%hhu", softc->ver_info->hwrm_min_major, 299 softc->ver_info->hwrm_min_minor, softc->ver_info->hwrm_min_update); 300 301 rc = sysctl_handle_string(oidp, buf, sizeof(buf), req); 302 if (rc || req->newptr == NULL) 303 return rc; 304 if (sscanf(buf, "%hhu.%hhu.%hhu%*c", &newver[0], &newver[1], 305 &newver[2]) != 3) 306 return EINVAL; 307 softc->ver_info->hwrm_min_major = newver[0]; 308 softc->ver_info->hwrm_min_minor = newver[1]; 309 softc->ver_info->hwrm_min_update = newver[2]; 310 bnxt_check_hwrm_version(softc); 311 312 return rc; 313 } 314 315 int 316 bnxt_create_ver_sysctls(struct bnxt_softc *softc) 317 { 318 struct bnxt_ver_info *vi = softc->ver_info; 319 struct sysctl_oid *oid = vi->ver_oid; 320 321 if (!oid) 322 return ENOMEM; 323 324 SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 325 "hwrm_if", CTLFLAG_RD, vi->hwrm_if_ver, 0, 326 "HWRM interface version"); 327 SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 328 "driver_hwrm_if", CTLFLAG_RD, vi->driver_hwrm_if_ver, 0, 329 "HWRM firmware version"); 330 SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 331 "hwrm_fw", CTLFLAG_RD, vi->hwrm_fw_ver, 0, 332 "HWRM firmware version"); 333 SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 334 "mgmt_fw", CTLFLAG_RD, vi->mgmt_fw_ver, 0, 335 "management firmware version"); 336 SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 337 "netctrl_fw", CTLFLAG_RD, vi->netctrl_fw_ver, 0, 338 "network control firmware version"); 339 SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 340 "roce_fw", CTLFLAG_RD, vi->roce_fw_ver, 0, 341 "RoCE firmware version"); 342 SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 343 "phy", CTLFLAG_RD, vi->phy_ver, 0, 344 "PHY version"); 345 SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 346 "hwrm_fw_name", CTLFLAG_RD, vi->hwrm_fw_name, 0, 347 "HWRM firmware name"); 348 SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 349 "mgmt_fw_name", CTLFLAG_RD, vi->mgmt_fw_name, 0, 350 "management firmware name"); 351 SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 352 "netctrl_fw_name", CTLFLAG_RD, vi->netctrl_fw_name, 0, 353 "network control firmware name"); 354 SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 355 "roce_fw_name", CTLFLAG_RD, vi->roce_fw_name, 0, 356 "RoCE firmware name"); 357 SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 358 "phy_vendor", CTLFLAG_RD, vi->phy_vendor, 0, 359 "PHY vendor name"); 360 SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 361 "phy_partnumber", CTLFLAG_RD, vi->phy_partnumber, 0, 362 "PHY vendor part number"); 363 SYSCTL_ADD_U16(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 364 "chip_num", CTLFLAG_RD, &vi->chip_num, 0, "chip number"); 365 SYSCTL_ADD_U8(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 366 "chip_rev", CTLFLAG_RD, &vi->chip_rev, 0, "chip revision"); 367 SYSCTL_ADD_U8(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 368 "chip_metal", CTLFLAG_RD, &vi->chip_metal, 0, "chip metal number"); 369 SYSCTL_ADD_U8(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 370 "chip_bond_id", CTLFLAG_RD, &vi->chip_bond_id, 0, 371 "chip bond id"); 372 SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 373 "chip_type", CTLFLAG_RD, vi->chip_type > MAX_CHIP_TYPE ? 374 bnxt_chip_type[MAX_CHIP_TYPE] : bnxt_chip_type[vi->chip_type], 0, 375 "RoCE firmware name"); 376 SYSCTL_ADD_PROC(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 377 "package_ver", CTLTYPE_STRING|CTLFLAG_RD, softc, 0, 378 bnxt_package_ver_sysctl, "A", 379 "currently installed package version"); 380 SYSCTL_ADD_PROC(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 381 "hwrm_min_ver", CTLTYPE_STRING|CTLFLAG_RWTUN, softc, 0, 382 bnxt_hwrm_min_ver_sysctl, "A", 383 "minimum hwrm API vesion to support"); 384 385 return 0; 386 } 387 388 int 389 bnxt_create_nvram_sysctls(struct bnxt_nvram_info *ni) 390 { 391 struct sysctl_oid *oid = ni->nvm_oid; 392 393 if (!oid) 394 return ENOMEM; 395 396 SYSCTL_ADD_U16(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 397 "mfg_id", CTLFLAG_RD, &ni->mfg_id, 0, "manufacturer id"); 398 SYSCTL_ADD_U16(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 399 "device_id", CTLFLAG_RD, &ni->device_id, 0, "device id"); 400 SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 401 "sector_size", CTLFLAG_RD, &ni->sector_size, 0, "sector size"); 402 SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 403 "size", CTLFLAG_RD, &ni->size, 0, "nvram total size"); 404 SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 405 "reserved_size", CTLFLAG_RD, &ni->reserved_size, 0, 406 "total reserved space"); 407 SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 408 "available_size", CTLFLAG_RD, &ni->available_size, 0, 409 "total available space"); 410 411 return 0; 412 } 413 414 static int 415 bnxt_rss_key_sysctl(SYSCTL_HANDLER_ARGS) 416 { 417 struct bnxt_softc *softc = arg1; 418 char buf[HW_HASH_KEY_SIZE*2+1] = {0}; 419 char *p; 420 int i; 421 int rc; 422 423 for (p = buf, i=0; i<HW_HASH_KEY_SIZE; i++) 424 p += sprintf(p, "%02x", softc->vnic_info.rss_hash_key[i]); 425 426 rc = sysctl_handle_string(oidp, buf, sizeof(buf), req); 427 if (rc || req->newptr == NULL) 428 return rc; 429 430 if (strspn(buf, "0123456789abcdefABCDEF") != (HW_HASH_KEY_SIZE * 2)) 431 return EINVAL; 432 433 for (p = buf, i=0; i<HW_HASH_KEY_SIZE; i++) { 434 if (sscanf(p, "%02hhx", &softc->vnic_info.rss_hash_key[i]) != 1) 435 return EINVAL; 436 p += 2; 437 } 438 439 if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING) 440 bnxt_hwrm_rss_cfg(softc, &softc->vnic_info, 441 softc->vnic_info.rss_hash_type); 442 443 return rc; 444 } 445 446 static const char *bnxt_hash_types[] = {"ipv4", "tcp_ipv4", "udp_ipv4", "ipv6", 447 "tcp_ipv6", "udp_ipv6", NULL}; 448 449 static int bnxt_get_rss_type_str_bit(char *str) 450 { 451 int i; 452 453 for (i=0; bnxt_hash_types[i]; i++) 454 if (strcmp(bnxt_hash_types[i], str) == 0) 455 return i; 456 457 return -1; 458 } 459 460 static int 461 bnxt_rss_type_sysctl(SYSCTL_HANDLER_ARGS) 462 { 463 struct bnxt_softc *softc = arg1; 464 char buf[256] = {0}; 465 char *p; 466 char *next; 467 int rc; 468 int type; 469 int bit; 470 471 for (type = softc->vnic_info.rss_hash_type; type; 472 type &= ~(1<<bit)) { 473 bit = ffs(type) - 1; 474 if (bit >= sizeof(bnxt_hash_types) / sizeof(const char *)) 475 continue; 476 if (type != softc->vnic_info.rss_hash_type) 477 strcat(buf, ","); 478 strcat(buf, bnxt_hash_types[bit]); 479 } 480 481 rc = sysctl_handle_string(oidp, buf, sizeof(buf), req); 482 if (rc || req->newptr == NULL) 483 return rc; 484 485 for (type = 0, next = buf, p = strsep(&next, " ,"); p; 486 p = strsep(&next, " ,")) { 487 bit = bnxt_get_rss_type_str_bit(p); 488 if (bit == -1) 489 return EINVAL; 490 type |= 1<<bit; 491 } 492 if (type != softc->vnic_info.rss_hash_type) { 493 softc->vnic_info.rss_hash_type = type; 494 if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING) 495 bnxt_hwrm_rss_cfg(softc, &softc->vnic_info, 496 softc->vnic_info.rss_hash_type); 497 } 498 499 return rc; 500 } 501 502 static int 503 bnxt_rx_stall_sysctl(SYSCTL_HANDLER_ARGS) { 504 struct bnxt_softc *softc = arg1; 505 int rc; 506 int val; 507 508 if (softc == NULL) 509 return EBUSY; 510 511 val = (bool)(softc->vnic_info.flags & BNXT_VNIC_FLAG_BD_STALL); 512 rc = sysctl_handle_int(oidp, &val, 0, req); 513 if (rc || !req->newptr) 514 return rc; 515 516 if (val) 517 softc->vnic_info.flags |= BNXT_VNIC_FLAG_BD_STALL; 518 else 519 softc->vnic_info.flags &= ~BNXT_VNIC_FLAG_BD_STALL; 520 521 if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING) 522 rc = bnxt_hwrm_vnic_cfg(softc, &softc->vnic_info); 523 524 return rc; 525 } 526 527 static int 528 bnxt_vlan_strip_sysctl(SYSCTL_HANDLER_ARGS) { 529 struct bnxt_softc *softc = arg1; 530 int rc; 531 int val; 532 533 if (softc == NULL) 534 return EBUSY; 535 536 val = (bool)(softc->vnic_info.flags & BNXT_VNIC_FLAG_VLAN_STRIP); 537 rc = sysctl_handle_int(oidp, &val, 0, req); 538 if (rc || !req->newptr) 539 return rc; 540 541 if (val) 542 softc->vnic_info.flags |= BNXT_VNIC_FLAG_VLAN_STRIP; 543 else 544 softc->vnic_info.flags &= ~BNXT_VNIC_FLAG_VLAN_STRIP; 545 546 if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING) 547 rc = bnxt_hwrm_vnic_cfg(softc, &softc->vnic_info); 548 549 return rc; 550 } 551 552 static int 553 bnxt_set_coal_rx_usecs(SYSCTL_HANDLER_ARGS) { 554 struct bnxt_softc *softc = arg1; 555 int rc; 556 int val; 557 558 if (softc == NULL) 559 return EBUSY; 560 561 val = softc->rx_coal_usecs; 562 rc = sysctl_handle_int(oidp, &val, 0, req); 563 if (rc || !req->newptr) 564 return rc; 565 566 softc->rx_coal_usecs = val; 567 rc = bnxt_hwrm_set_coal(softc); 568 569 return rc; 570 } 571 572 static int 573 bnxt_set_coal_rx_frames(SYSCTL_HANDLER_ARGS) { 574 struct bnxt_softc *softc = arg1; 575 int rc; 576 int val; 577 578 if (softc == NULL) 579 return EBUSY; 580 581 val = softc->rx_coal_frames; 582 rc = sysctl_handle_int(oidp, &val, 0, req); 583 if (rc || !req->newptr) 584 return rc; 585 586 softc->rx_coal_frames = val; 587 rc = bnxt_hwrm_set_coal(softc); 588 589 return rc; 590 } 591 592 static int 593 bnxt_set_coal_rx_usecs_irq(SYSCTL_HANDLER_ARGS) { 594 struct bnxt_softc *softc = arg1; 595 int rc; 596 int val; 597 598 if (softc == NULL) 599 return EBUSY; 600 601 val = softc->rx_coal_usecs_irq; 602 rc = sysctl_handle_int(oidp, &val, 0, req); 603 if (rc || !req->newptr) 604 return rc; 605 606 softc->rx_coal_usecs_irq = val; 607 rc = bnxt_hwrm_set_coal(softc); 608 609 return rc; 610 } 611 612 static int 613 bnxt_set_coal_rx_frames_irq(SYSCTL_HANDLER_ARGS) { 614 struct bnxt_softc *softc = arg1; 615 int rc; 616 int val; 617 618 if (softc == NULL) 619 return EBUSY; 620 621 val = softc->rx_coal_frames_irq; 622 rc = sysctl_handle_int(oidp, &val, 0, req); 623 if (rc || !req->newptr) 624 return rc; 625 626 softc->rx_coal_frames_irq = val; 627 rc = bnxt_hwrm_set_coal(softc); 628 629 return rc; 630 } 631 632 static int 633 bnxt_set_coal_tx_usecs(SYSCTL_HANDLER_ARGS) { 634 struct bnxt_softc *softc = arg1; 635 int rc; 636 int val; 637 638 if (softc == NULL) 639 return EBUSY; 640 641 val = softc->tx_coal_usecs; 642 rc = sysctl_handle_int(oidp, &val, 0, req); 643 if (rc || !req->newptr) 644 return rc; 645 646 softc->tx_coal_usecs = val; 647 rc = bnxt_hwrm_set_coal(softc); 648 649 return rc; 650 } 651 652 static int 653 bnxt_set_coal_tx_frames(SYSCTL_HANDLER_ARGS) { 654 struct bnxt_softc *softc = arg1; 655 int rc; 656 int val; 657 658 if (softc == NULL) 659 return EBUSY; 660 661 val = softc->tx_coal_frames; 662 rc = sysctl_handle_int(oidp, &val, 0, req); 663 if (rc || !req->newptr) 664 return rc; 665 666 softc->tx_coal_frames = val; 667 rc = bnxt_hwrm_set_coal(softc); 668 669 return rc; 670 } 671 672 static int 673 bnxt_set_coal_tx_usecs_irq(SYSCTL_HANDLER_ARGS) { 674 struct bnxt_softc *softc = arg1; 675 int rc; 676 int val; 677 678 if (softc == NULL) 679 return EBUSY; 680 681 val = softc->tx_coal_usecs_irq; 682 rc = sysctl_handle_int(oidp, &val, 0, req); 683 if (rc || !req->newptr) 684 return rc; 685 686 softc->tx_coal_usecs_irq = val; 687 rc = bnxt_hwrm_set_coal(softc); 688 689 return rc; 690 } 691 692 static int 693 bnxt_set_coal_tx_frames_irq(SYSCTL_HANDLER_ARGS) { 694 struct bnxt_softc *softc = arg1; 695 int rc; 696 int val; 697 698 if (softc == NULL) 699 return EBUSY; 700 701 val = softc->tx_coal_frames_irq; 702 rc = sysctl_handle_int(oidp, &val, 0, req); 703 if (rc || !req->newptr) 704 return rc; 705 706 softc->tx_coal_frames_irq = val; 707 rc = bnxt_hwrm_set_coal(softc); 708 709 return rc; 710 } 711 712 int 713 bnxt_create_config_sysctls_pre(struct bnxt_softc *softc) 714 { 715 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(softc->dev); 716 struct sysctl_oid_list *children; 717 718 children = SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev));; 719 720 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rss_key", 721 CTLTYPE_STRING|CTLFLAG_RWTUN, softc, 0, bnxt_rss_key_sysctl, "A", 722 "RSS key"); 723 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rss_type", 724 CTLTYPE_STRING|CTLFLAG_RWTUN, softc, 0, bnxt_rss_type_sysctl, "A", 725 "RSS type bits"); 726 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_stall", 727 CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_rx_stall_sysctl, "I", 728 "buffer rx packets in hardware until the host posts new buffers"); 729 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "vlan_strip", 730 CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_vlan_strip_sysctl, "I", 731 "strip VLAN tag in the RX path"); 732 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "if_name", CTLFLAG_RD, 733 iflib_get_ifp(softc->ctx)->if_xname, 0, "interface name"); 734 735 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_usecs", 736 CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_set_coal_rx_usecs, 737 "I", "interrupt coalescing Rx Usecs"); 738 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_frames", 739 CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_set_coal_rx_frames, 740 "I", "interrupt coalescing Rx Frames"); 741 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_usecs_irq", 742 CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_set_coal_rx_usecs_irq, 743 "I", "interrupt coalescing Rx Usecs IRQ"); 744 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_frames_irq", 745 CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_set_coal_rx_frames_irq, 746 "I", "interrupt coalescing Rx Frames IRQ"); 747 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_usecs", 748 CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_set_coal_tx_usecs, 749 "I", "interrupt coalescing Tx Usces"); 750 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_frames", 751 CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_set_coal_tx_frames, 752 "I", "interrupt coalescing Tx Frames"); 753 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_usecs_irq", 754 CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_set_coal_tx_usecs_irq, 755 "I", "interrupt coalescing Tx Usecs IRQ"); 756 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_frames_irq", 757 CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_set_coal_tx_frames_irq, 758 "I", "interrupt coalescing Tx Frames IRQ"); 759 760 return 0; 761 } 762 763 static int 764 bnxt_vlan_only_sysctl(SYSCTL_HANDLER_ARGS) { 765 struct bnxt_softc *softc = arg1; 766 int rc; 767 int val; 768 769 if (softc == NULL) 770 return EBUSY; 771 772 val = softc->vnic_info.vlan_only; 773 rc = sysctl_handle_int(oidp, &val, 0, req); 774 if (rc || !req->newptr) 775 return rc; 776 777 if (val) 778 val = 1; 779 780 if (val != softc->vnic_info.vlan_only) { 781 softc->vnic_info.vlan_only = val; 782 if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING) 783 rc = bnxt_hwrm_cfa_l2_set_rx_mask(softc, 784 &softc->vnic_info); 785 } 786 787 return rc; 788 } 789 790 int 791 bnxt_create_config_sysctls_post(struct bnxt_softc *softc) 792 { 793 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(softc->dev); 794 struct sysctl_oid_list *children; 795 796 children = SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev));; 797 798 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "vlan_only", 799 CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_vlan_only_sysctl, "I", 800 "require vlan tag on received packets when vlan is enabled"); 801 802 return 0; 803 } 804