1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2020 Advanced Micro Devices, Inc. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 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 the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * Contact Information : 28 * Rajesh Kumar <rajesh1.kumar@amd.com> 29 * Arpan Palit <Arpan.Palit@amd.com> 30 */ 31 32 #include <sys/param.h> 33 #include <sys/sysctl.h> 34 #include <sys/sbuf.h> 35 36 #include "xgbe.h" 37 #include "xgbe-common.h" 38 39 #define SYSCTL_BUF_LEN 64 40 41 typedef enum{ 42 /* Coalesce flag */ 43 rx_coalesce_usecs = 1, 44 rx_max_coalesced_frames, 45 rx_coalesce_usecs_irq, 46 rx_max_coalesced_frames_irq, 47 tx_coalesce_usecs, 48 tx_max_coalesced_frames, 49 tx_coalesce_usecs_irq, 50 tx_max_coalesced_frames_irq, 51 stats_block_coalesce_usecs, 52 use_adaptive_rx_coalesce, 53 use_adaptive_tx_coalesce, 54 pkt_rate_low, 55 rx_coalesce_usecs_low, 56 rx_max_coalesced_frames_low, 57 tx_coalesce_usecs_low, 58 tx_max_coalesced_frames_low, 59 pkt_rate_high, 60 rx_coalesce_usecs_high, 61 rx_max_coalesced_frames_high, 62 tx_coalesce_usecs_high, 63 tx_max_coalesced_frames_high, 64 rate_sample_interval, 65 66 /* Pasue flag */ 67 autoneg, 68 tx_pause, 69 rx_pause, 70 71 /* link settings */ 72 speed, 73 duplex, 74 75 /* Ring settings */ 76 rx_pending, 77 rx_mini_pending, 78 rx_jumbo_pending, 79 tx_pending, 80 81 /* Channels settings */ 82 rx_count, 83 tx_count, 84 other_count, 85 combined_count, 86 } sysctl_variable_t; 87 88 typedef enum { 89 SYSL_NONE, 90 SYSL_BOOL, 91 SYSL_S32, 92 SYSL_U8, 93 SYSL_U16, 94 SYSL_U32, 95 SYSL_U64, 96 SYSL_BE16, 97 SYSL_IP4, 98 SYSL_STR, 99 SYSL_FLAG, 100 SYSL_MAC, 101 } sysctl_type_t; 102 103 struct sysctl_info { 104 uint8_t name[32]; 105 sysctl_type_t type; 106 sysctl_variable_t flag; 107 uint8_t support[16]; 108 }; 109 110 struct sysctl_op { 111 /* Coalesce options */ 112 unsigned int rx_coalesce_usecs; 113 unsigned int rx_max_coalesced_frames; 114 unsigned int rx_coalesce_usecs_irq; 115 unsigned int rx_max_coalesced_frames_irq; 116 unsigned int tx_coalesce_usecs; 117 unsigned int tx_max_coalesced_frames; 118 unsigned int tx_coalesce_usecs_irq; 119 unsigned int tx_max_coalesced_frames_irq; 120 unsigned int stats_block_coalesce_usecs; 121 unsigned int use_adaptive_rx_coalesce; 122 unsigned int use_adaptive_tx_coalesce; 123 unsigned int pkt_rate_low; 124 unsigned int rx_coalesce_usecs_low; 125 unsigned int rx_max_coalesced_frames_low; 126 unsigned int tx_coalesce_usecs_low; 127 unsigned int tx_max_coalesced_frames_low; 128 unsigned int pkt_rate_high; 129 unsigned int rx_coalesce_usecs_high; 130 unsigned int rx_max_coalesced_frames_high; 131 unsigned int tx_coalesce_usecs_high; 132 unsigned int tx_max_coalesced_frames_high; 133 unsigned int rate_sample_interval; 134 135 /* Pasue options */ 136 unsigned int autoneg; 137 unsigned int tx_pause; 138 unsigned int rx_pause; 139 140 /* Link settings options */ 141 unsigned int speed; 142 unsigned int duplex; 143 144 /* Ring param options */ 145 unsigned int rx_max_pending; 146 unsigned int rx_mini_max_pending; 147 unsigned int rx_jumbo_max_pending; 148 unsigned int tx_max_pending; 149 unsigned int rx_pending; 150 unsigned int rx_mini_pending; 151 unsigned int rx_jumbo_pending; 152 unsigned int tx_pending; 153 154 /* Channels options */ 155 unsigned int max_rx; 156 unsigned int max_tx; 157 unsigned int max_other; 158 unsigned int max_combined; 159 unsigned int rx_count; 160 unsigned int tx_count; 161 unsigned int other_count; 162 unsigned int combined_count; 163 } sys_op; 164 165 #define GSTRING_LEN 32 166 167 struct xgbe_stats { 168 char stat_string[GSTRING_LEN]; 169 int stat_size; 170 int stat_offset; 171 }; 172 173 #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) 174 175 #define XGMAC_MMC_STAT(_string, _var) \ 176 { _string, \ 177 FIELD_SIZEOF(struct xgbe_mmc_stats, _var), \ 178 offsetof(struct xgbe_prv_data, mmc_stats._var), \ 179 } 180 181 #define XGMAC_EXT_STAT(_string, _var) \ 182 { _string, \ 183 FIELD_SIZEOF(struct xgbe_ext_stats, _var), \ 184 offsetof(struct xgbe_prv_data, ext_stats._var), \ 185 } 186 static const struct xgbe_stats xgbe_gstring_stats[] = { 187 XGMAC_MMC_STAT("tx_bytes", txoctetcount_gb), 188 XGMAC_MMC_STAT("tx_packets", txframecount_gb), 189 XGMAC_MMC_STAT("tx_unicast_packets", txunicastframes_gb), 190 XGMAC_MMC_STAT("tx_broadcast_packets", txbroadcastframes_gb), 191 XGMAC_MMC_STAT("tx_multicast_packets", txmulticastframes_gb), 192 XGMAC_MMC_STAT("tx_vlan_packets", txvlanframes_g), 193 XGMAC_EXT_STAT("tx_vxlan_packets", tx_vxlan_packets), 194 XGMAC_EXT_STAT("tx_tso_packets", tx_tso_packets), 195 XGMAC_MMC_STAT("tx_64_byte_packets", tx64octets_gb), 196 XGMAC_MMC_STAT("tx_65_to_127_byte_packets", tx65to127octets_gb), 197 XGMAC_MMC_STAT("tx_128_to_255_byte_packets", tx128to255octets_gb), 198 XGMAC_MMC_STAT("tx_256_to_511_byte_packets", tx256to511octets_gb), 199 XGMAC_MMC_STAT("tx_512_to_1023_byte_packets", tx512to1023octets_gb), 200 XGMAC_MMC_STAT("tx_1024_to_max_byte_packets", tx1024tomaxoctets_gb), 201 XGMAC_MMC_STAT("tx_underflow_errors", txunderflowerror), 202 XGMAC_MMC_STAT("tx_pause_frames", txpauseframes), 203 204 XGMAC_MMC_STAT("rx_bytes", rxoctetcount_gb), 205 XGMAC_MMC_STAT("rx_packets", rxframecount_gb), 206 XGMAC_MMC_STAT("rx_unicast_packets", rxunicastframes_g), 207 XGMAC_MMC_STAT("rx_broadcast_packets", rxbroadcastframes_g), 208 XGMAC_MMC_STAT("rx_multicast_packets", rxmulticastframes_g), 209 XGMAC_MMC_STAT("rx_vlan_packets", rxvlanframes_gb), 210 XGMAC_EXT_STAT("rx_vxlan_packets", rx_vxlan_packets), 211 XGMAC_MMC_STAT("rx_64_byte_packets", rx64octets_gb), 212 XGMAC_MMC_STAT("rx_65_to_127_byte_packets", rx65to127octets_gb), 213 XGMAC_MMC_STAT("rx_128_to_255_byte_packets", rx128to255octets_gb), 214 XGMAC_MMC_STAT("rx_256_to_511_byte_packets", rx256to511octets_gb), 215 XGMAC_MMC_STAT("rx_512_to_1023_byte_packets", rx512to1023octets_gb), 216 XGMAC_MMC_STAT("rx_1024_to_max_byte_packets", rx1024tomaxoctets_gb), 217 XGMAC_MMC_STAT("rx_undersize_packets", rxundersize_g), 218 XGMAC_MMC_STAT("rx_oversize_packets", rxoversize_g), 219 XGMAC_MMC_STAT("rx_crc_errors", rxcrcerror), 220 XGMAC_MMC_STAT("rx_crc_errors_small_packets", rxrunterror), 221 XGMAC_MMC_STAT("rx_crc_errors_giant_packets", rxjabbererror), 222 XGMAC_MMC_STAT("rx_length_errors", rxlengtherror), 223 XGMAC_MMC_STAT("rx_out_of_range_errors", rxoutofrangetype), 224 XGMAC_MMC_STAT("rx_fifo_overflow_errors", rxfifooverflow), 225 XGMAC_MMC_STAT("rx_watchdog_errors", rxwatchdogerror), 226 XGMAC_EXT_STAT("rx_csum_errors", rx_csum_errors), 227 XGMAC_EXT_STAT("rx_vxlan_csum_errors", rx_vxlan_csum_errors), 228 XGMAC_MMC_STAT("rx_pause_frames", rxpauseframes), 229 XGMAC_EXT_STAT("rx_split_header_packets", rx_split_header_packets), 230 XGMAC_EXT_STAT("rx_buffer_unavailable", rx_buffer_unavailable), 231 }; 232 233 #define XGBE_STATS_COUNT ARRAY_SIZE(xgbe_gstring_stats) 234 235 char** alloc_sysctl_buffer(void); 236 void get_val(char *buf, char **op, char **val, int *n_op); 237 void fill_data(struct sysctl_op *sys_op, int flag, unsigned int value); 238 239 static int 240 exit_bad_op(void) 241 { 242 243 printf("SYSCTL: bad command line option (s)\n"); 244 return(-EINVAL); 245 } 246 247 static inline int 248 get_ubuf(struct sysctl_req *req, char *ubuf) 249 { 250 int rc; 251 252 printf("%s: len:0x%li idx:0x%li\n", __func__, req->newlen, 253 req->newidx); 254 if (req->newlen >= SYSCTL_BUF_LEN) 255 return (-EINVAL); 256 257 rc = SYSCTL_IN(req, ubuf, req->newlen); 258 if (rc) 259 return (rc); 260 ubuf[req->newlen] = '\0'; 261 262 return (0); 263 } 264 265 char** 266 alloc_sysctl_buffer(void) 267 { 268 char **buffer; 269 int i; 270 271 buffer = malloc(sizeof(char *)*32, M_AXGBE, M_WAITOK | M_ZERO); 272 for(i = 0; i < 32; i++) 273 buffer[i] = malloc(sizeof(char)*32, M_AXGBE, M_WAITOK | M_ZERO); 274 275 return (buffer); 276 } 277 278 void 279 get_val(char *buf, char **op, char **val, int *n_op) 280 { 281 int blen = strlen(buf); 282 int count = 0; 283 int i, j; 284 285 *n_op = 0; 286 for (i = 0; i < blen; i++) { 287 count++; 288 /* Get sysctl command option */ 289 for (j = 0; buf[i] != ' '; j++) { 290 if (i >= blen) 291 break; 292 op[*n_op][j] = buf[i++]; 293 } 294 op[*n_op][j+1] = '\0'; 295 if (i >= strlen(buf)) 296 goto out; 297 298 /* Get sysctl value*/ 299 i++; 300 for (j = 0; buf[i] != ' '; j++) { 301 if (i >= blen) 302 break; 303 val[*n_op][j] = buf[i++]; 304 } 305 val[*n_op][j+1] = '\0'; 306 if (i >= strlen(buf)) 307 goto out; 308 309 *n_op = count; 310 } 311 312 out: 313 *n_op = count; 314 } 315 316 void 317 fill_data(struct sysctl_op *sys_op, int flag, unsigned int value) 318 { 319 320 switch(flag) { 321 case 1: 322 sys_op->rx_coalesce_usecs = value; 323 break; 324 case 2: 325 sys_op->rx_max_coalesced_frames = value; 326 break; 327 case 3: 328 sys_op->rx_coalesce_usecs_irq = value; 329 break; 330 case 4: 331 sys_op->rx_max_coalesced_frames_irq = value; 332 break; 333 case 5: 334 sys_op->tx_coalesce_usecs = value; 335 break; 336 case 6: 337 sys_op->tx_max_coalesced_frames = value; 338 break; 339 case 7: 340 sys_op->tx_coalesce_usecs_irq = value; 341 break; 342 case 8: 343 sys_op->tx_max_coalesced_frames_irq = value; 344 break; 345 case 9: 346 sys_op->stats_block_coalesce_usecs = value; 347 break; 348 case 10: 349 sys_op->use_adaptive_rx_coalesce = value; 350 break; 351 case 11: 352 sys_op->use_adaptive_tx_coalesce = value; 353 break; 354 case 12: 355 sys_op->pkt_rate_low = value; 356 break; 357 case 13: 358 sys_op->rx_coalesce_usecs_low = value; 359 break; 360 case 14: 361 sys_op->rx_max_coalesced_frames_low = value; 362 break; 363 case 15: 364 sys_op->tx_coalesce_usecs_low = value; 365 break; 366 case 16: 367 sys_op->tx_max_coalesced_frames_low = value; 368 break; 369 case 17: 370 sys_op->pkt_rate_high = value; 371 break; 372 case 18: 373 sys_op->rx_coalesce_usecs_high = value; 374 break; 375 case 19: 376 sys_op->rx_max_coalesced_frames_high = value; 377 break; 378 case 20: 379 sys_op->tx_coalesce_usecs_high = value; 380 break; 381 case 21: 382 sys_op->tx_max_coalesced_frames_high = value; 383 break; 384 case 22: 385 sys_op->rate_sample_interval = value; 386 break; 387 case 23: 388 sys_op->autoneg = value; 389 break; 390 case 24: 391 sys_op->rx_pause = value; 392 break; 393 case 25: 394 sys_op->tx_pause = value; 395 break; 396 case 26: 397 sys_op->speed = value; 398 break; 399 case 27: 400 sys_op->duplex = value; 401 break; 402 case 28: 403 sys_op->rx_pending = value; 404 break; 405 case 29: 406 sys_op->rx_mini_pending = value; 407 break; 408 case 30: 409 sys_op->rx_jumbo_pending = value; 410 break; 411 case 31: 412 sys_op->tx_pending = value; 413 break; 414 default: 415 printf("Option error\n"); 416 } 417 } 418 419 static int 420 parse_generic_sysctl(struct xgbe_prv_data *pdata, char *buf, 421 struct sysctl_info *info, unsigned int n_info) 422 { 423 struct sysctl_op *sys_op = pdata->sys_op; 424 unsigned int value; 425 char **op, **val; 426 int n_op = 0; 427 int rc = 0; 428 int i, idx; 429 430 op = alloc_sysctl_buffer(); 431 val = alloc_sysctl_buffer(); 432 get_val(buf, op, val, &n_op); 433 434 for (i = 0; i < n_op; i++) { 435 for (idx = 0; idx < n_info; idx++) { 436 if (strcmp(info[idx].name, op[i]) == 0) { 437 if (strcmp(info[idx].support, 438 "not-supported") == 0){ 439 axgbe_printf(1, "ignoring not-supported " 440 "option \"%s\"\n", info[idx].name); 441 break; 442 } 443 switch(info[idx].type) { 444 case SYSL_BOOL: { 445 if (!strcmp(val[i], "on")) 446 fill_data(sys_op, 447 info[idx].flag, 1); 448 else if (!strcmp(val[i], "off")) 449 fill_data(sys_op, 450 info[idx].flag, 0); 451 else 452 rc = exit_bad_op(); 453 break; 454 } 455 case SYSL_S32: 456 sscanf(val[i], "%u", &value); 457 fill_data(sys_op, info[idx].flag, value); 458 break; 459 case SYSL_U8: 460 if (!strcmp(val[i], "half")) 461 fill_data(sys_op, 462 info[idx].flag, DUPLEX_HALF); 463 else if (!strcmp(val[i], "full")) 464 fill_data(sys_op, 465 info[idx].flag, DUPLEX_FULL); 466 else 467 exit_bad_op(); 468 default: 469 rc = exit_bad_op(); 470 } 471 } 472 } 473 } 474 475 for(i = 0; i < 32; i++) 476 free(op[i], M_AXGBE); 477 free(op, M_AXGBE); 478 479 for(i = 0; i < 32; i++) 480 free(val[i], M_AXGBE); 481 free(val, M_AXGBE); 482 return (rc); 483 } 484 485 486 static int 487 sysctl_xgmac_reg_addr_handler(SYSCTL_HANDLER_ARGS) 488 { 489 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 490 ssize_t buf_size = 64; 491 char buf[buf_size]; 492 struct sbuf *sb; 493 unsigned int reg; 494 int rc = 0; 495 496 if (req->newptr == NULL) { 497 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 498 if (sb == NULL) { 499 rc = ENOMEM; 500 return (rc); 501 } 502 503 axgbe_printf(2, "READ: %s: sysctl_xgmac_reg: 0x%x\n", __func__, 504 pdata->sysctl_xgmac_reg); 505 sbuf_printf(sb, "\nXGMAC reg_addr: 0x%x\n", 506 pdata->sysctl_xgmac_reg); 507 rc = sbuf_finish(sb); 508 sbuf_delete(sb); 509 return (rc); 510 } 511 512 rc = get_ubuf(req, buf); 513 if (rc == 0) { 514 sscanf(buf, "%x", ®); 515 axgbe_printf(2, "WRITE: %s: reg: 0x%x\n", __func__, reg); 516 pdata->sysctl_xgmac_reg = reg; 517 } 518 519 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 520 return (rc); 521 } 522 523 static int 524 sysctl_get_drv_info_handler(SYSCTL_HANDLER_ARGS) 525 { 526 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 527 struct xgbe_hw_features *hw_feat = &pdata->hw_feat; 528 ssize_t buf_size = 64; 529 struct sbuf *sb; 530 int rc = 0; 531 532 if (req->newptr == NULL) { 533 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 534 if (sb == NULL) { 535 rc = ENOMEM; 536 return (rc); 537 } 538 539 sbuf_printf(sb, "\ndriver: %s", XGBE_DRV_NAME); 540 sbuf_printf(sb, "\nversion: %s", XGBE_DRV_VERSION); 541 sbuf_printf(sb, "\nfirmware-version: %d.%d.%d", 542 XGMAC_GET_BITS(hw_feat->version, MAC_VR, USERVER), 543 XGMAC_GET_BITS(hw_feat->version, MAC_VR, DEVID), 544 XGMAC_GET_BITS(hw_feat->version, MAC_VR, SNPSVER)); 545 sbuf_printf(sb, "\nbus-info: %04d:%02d:%02d", 546 pdata->pcie_bus, pdata->pcie_device, pdata->pcie_func); 547 548 rc = sbuf_finish(sb); 549 sbuf_delete(sb); 550 return (rc); 551 } 552 553 return (-EINVAL); 554 } 555 556 static int 557 sysctl_get_link_info_handler(SYSCTL_HANDLER_ARGS) 558 { 559 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 560 ssize_t buf_size = 64; 561 struct sbuf *sb; 562 int rc = 0; 563 564 if (req->newptr == NULL) { 565 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 566 if (sb == NULL) { 567 rc = ENOMEM; 568 return (rc); 569 } 570 571 sbuf_printf(sb, "\nLink is %s", pdata->phy.link ? "Up" : "Down"); 572 rc = sbuf_finish(sb); 573 sbuf_delete(sb); 574 return (0); 575 } 576 577 return (-EINVAL); 578 } 579 580 #define COALESCE_SYSCTL_INFO(__coalop) \ 581 { \ 582 { "adaptive-rx", SYSL_BOOL, use_adaptive_rx_coalesce, "not-supported" }, \ 583 { "adaptive-tx", SYSL_BOOL, use_adaptive_tx_coalesce, "not-supported" }, \ 584 { "sample-interval", SYSL_S32, rate_sample_interval, "not-supported" }, \ 585 { "stats-block-usecs", SYSL_S32, stats_block_coalesce_usecs, "not-supported" }, \ 586 { "pkt-rate-low", SYSL_S32, pkt_rate_low, "not-supported" }, \ 587 { "pkt-rate-high", SYSL_S32, pkt_rate_high, "not-supported" }, \ 588 { "rx-usecs", SYSL_S32, rx_coalesce_usecs, "supported" }, \ 589 { "rx-frames", SYSL_S32, rx_max_coalesced_frames, "supported" }, \ 590 { "rx-usecs-irq", SYSL_S32, rx_coalesce_usecs_irq, "not-supported" }, \ 591 { "rx-frames-irq", SYSL_S32, rx_max_coalesced_frames_irq, "not-supported" }, \ 592 { "tx-usecs", SYSL_S32, tx_coalesce_usecs, "not-supported" }, \ 593 { "tx-frames", SYSL_S32, tx_max_coalesced_frames, "supported" }, \ 594 { "tx-usecs-irq", SYSL_S32, tx_coalesce_usecs_irq, "not-supported" }, \ 595 { "tx-frames-irq", SYSL_S32, tx_max_coalesced_frames_irq, "not-supported" }, \ 596 { "rx-usecs-low", SYSL_S32, rx_coalesce_usecs_low, "not-supported" }, \ 597 { "rx-frames-low", SYSL_S32, rx_max_coalesced_frames_low, "not-supported"}, \ 598 { "tx-usecs-low", SYSL_S32, tx_coalesce_usecs_low, "not-supported" }, \ 599 { "tx-frames-low", SYSL_S32, tx_max_coalesced_frames_low, "not-supported" }, \ 600 { "rx-usecs-high", SYSL_S32, rx_coalesce_usecs_high, "not-supported" }, \ 601 { "rx-frames-high", SYSL_S32, rx_max_coalesced_frames_high, "not-supported" }, \ 602 { "tx-usecs-high", SYSL_S32, tx_coalesce_usecs_high, "not-supported" }, \ 603 { "tx-frames-high", SYSL_S32, tx_max_coalesced_frames_high, "not-supported" }, \ 604 } 605 606 static int 607 sysctl_coalesce_handler(SYSCTL_HANDLER_ARGS) 608 { 609 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 610 struct xgbe_hw_if *hw_if = &pdata->hw_if; 611 struct sysctl_op *sys_op = pdata->sys_op; 612 struct sysctl_info sysctl_coalesce[] = COALESCE_SYSCTL_INFO(coalop); 613 unsigned int rx_frames, rx_riwt, rx_usecs; 614 unsigned int tx_frames; 615 ssize_t buf_size = 64; 616 char buf[buf_size]; 617 struct sbuf *sb; 618 int rc = 0; 619 620 if (req->newptr == NULL) { 621 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 622 if (sb == NULL) { 623 rc = ENOMEM; 624 return (rc); 625 } 626 sys_op->rx_coalesce_usecs = pdata->rx_usecs; 627 sys_op->rx_max_coalesced_frames = pdata->rx_frames; 628 sys_op->tx_max_coalesced_frames = pdata->tx_frames; 629 630 sbuf_printf(sb, "\nAdaptive RX: %s TX: %s\n", 631 sys_op->use_adaptive_rx_coalesce ? "on" : "off", 632 sys_op->use_adaptive_tx_coalesce ? "on" : "off"); 633 634 sbuf_printf(sb, "stats-block-usecs: %u\n" 635 "sample-interval: %u\n" 636 "pkt-rate-low: %u\n" 637 "pkt-rate-high: %u\n" 638 "\n" 639 "rx-usecs: %u\n" 640 "rx-frames: %u\n" 641 "rx-usecs-irq: %u\n" 642 "rx-frames-irq: %u\n" 643 "\n" 644 "tx-usecs: %u\n" 645 "tx-frames: %u\n" 646 "tx-usecs-irq: %u\n" 647 "tx-frames-irq: %u\n" 648 "\n" 649 "rx-usecs-low: %u\n" 650 "rx-frames-low: %u\n" 651 "tx-usecs-low: %u\n" 652 "tx-frames-low: %u\n" 653 "\n" 654 "rx-usecs-high: %u\n" 655 "rx-frames-high: %u\n" 656 "tx-usecs-high: %u\n" 657 "tx-frames-high: %u\n", 658 sys_op->stats_block_coalesce_usecs, 659 sys_op->rate_sample_interval, 660 sys_op->pkt_rate_low, 661 sys_op->pkt_rate_high, 662 663 sys_op->rx_coalesce_usecs, 664 sys_op->rx_max_coalesced_frames, 665 sys_op->rx_coalesce_usecs_irq, 666 sys_op->rx_max_coalesced_frames_irq, 667 668 sys_op->tx_coalesce_usecs, 669 sys_op->tx_max_coalesced_frames, 670 sys_op->tx_coalesce_usecs_irq, 671 sys_op->tx_max_coalesced_frames_irq, 672 673 sys_op->rx_coalesce_usecs_low, 674 sys_op->rx_max_coalesced_frames_low, 675 sys_op->tx_coalesce_usecs_low, 676 sys_op->tx_max_coalesced_frames_low, 677 678 sys_op->rx_coalesce_usecs_high, 679 sys_op->rx_max_coalesced_frames_high, 680 sys_op->tx_coalesce_usecs_high, 681 sys_op->tx_max_coalesced_frames_high); 682 683 rc = sbuf_finish(sb); 684 sbuf_delete(sb); 685 return (0); 686 } 687 688 rc = get_ubuf(req, buf); 689 if (rc == 0) { 690 parse_generic_sysctl(pdata, buf, sysctl_coalesce, 691 ARRAY_SIZE(sysctl_coalesce)); 692 693 rx_riwt = hw_if->usec_to_riwt(pdata, sys_op->rx_coalesce_usecs); 694 rx_usecs = sys_op->rx_coalesce_usecs; 695 rx_frames = sys_op->rx_max_coalesced_frames; 696 697 /* Use smallest possible value if conversion resulted in zero */ 698 if (rx_usecs && !rx_riwt) 699 rx_riwt = 1; 700 701 /* Check the bounds of values for Rx */ 702 if (rx_riwt > XGMAC_MAX_DMA_RIWT) { 703 axgbe_printf(2, "rx-usec is limited to %d usecs\n", 704 hw_if->riwt_to_usec(pdata, XGMAC_MAX_DMA_RIWT)); 705 return (-EINVAL); 706 } 707 if (rx_frames > pdata->rx_desc_count) { 708 axgbe_printf(2, "rx-frames is limited to %d frames\n", 709 pdata->rx_desc_count); 710 return (-EINVAL); 711 } 712 713 tx_frames = sys_op->tx_max_coalesced_frames; 714 715 /* Check the bounds of values for Tx */ 716 if (tx_frames > pdata->tx_desc_count) { 717 axgbe_printf(2, "tx-frames is limited to %d frames\n", 718 pdata->tx_desc_count); 719 return (-EINVAL); 720 } 721 722 pdata->rx_riwt = rx_riwt; 723 pdata->rx_usecs = rx_usecs; 724 pdata->rx_frames = rx_frames; 725 hw_if->config_rx_coalesce(pdata); 726 727 pdata->tx_frames = tx_frames; 728 hw_if->config_tx_coalesce(pdata); 729 } 730 731 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 732 733 return (rc); 734 } 735 736 static int 737 sysctl_pauseparam_handler(SYSCTL_HANDLER_ARGS) 738 { 739 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 740 struct sysctl_op *sys_op = pdata->sys_op; 741 struct sysctl_info sysctl_pauseparam[] = { 742 { "autoneg", SYSL_BOOL, autoneg, "supported" }, 743 { "rx", SYSL_BOOL, rx_pause, "supported" }, 744 { "tx", SYSL_BOOL, tx_pause, "supported" }, 745 }; 746 ssize_t buf_size = 512; 747 char buf[buf_size]; 748 struct sbuf *sb; 749 int rc = 0; 750 751 if (req->newptr == NULL) { 752 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 753 if (sb == NULL) { 754 rc = ENOMEM; 755 return (rc); 756 } 757 sys_op->autoneg = pdata->phy.pause_autoneg; 758 sys_op->tx_pause = pdata->phy.tx_pause; 759 sys_op->rx_pause = pdata->phy.rx_pause; 760 761 sbuf_printf(sb, 762 "\nAutonegotiate: %s\n" 763 "RX: %s\n" 764 "TX: %s\n", 765 sys_op->autoneg ? "on" : "off", 766 sys_op->rx_pause ? "on" : "off", 767 sys_op->tx_pause ? "on" : "off"); 768 769 if (pdata->phy.lp_advertising) { 770 int an_rx = 0, an_tx = 0; 771 772 if (pdata->phy.advertising & pdata->phy.lp_advertising & 773 ADVERTISED_Pause) { 774 an_tx = 1; 775 an_rx = 1; 776 } else if (pdata->phy.advertising & 777 pdata->phy.lp_advertising & ADVERTISED_Asym_Pause) { 778 if (pdata->phy.advertising & ADVERTISED_Pause) 779 an_rx = 1; 780 else if (pdata->phy.lp_advertising & 781 ADVERTISED_Pause) 782 an_tx = 1; 783 } 784 sbuf_printf(sb, 785 "\n->\nRX negotiated: %s\n" 786 "TX negotiated: %s\n", 787 an_rx ? "on" : "off", 788 an_tx ? "on" : "off"); 789 } 790 rc = sbuf_finish(sb); 791 sbuf_delete(sb); 792 return (0); 793 } 794 795 rc = get_ubuf(req, buf); 796 if (rc == 0) { 797 parse_generic_sysctl(pdata, buf, sysctl_pauseparam, 798 ARRAY_SIZE(sysctl_pauseparam)); 799 800 if (sys_op->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE)) { 801 axgbe_error("autoneg disabled, pause autoneg not available\n"); 802 return (-EINVAL); 803 } 804 805 pdata->phy.pause_autoneg = sys_op->autoneg; 806 pdata->phy.tx_pause = sys_op->tx_pause; 807 pdata->phy.rx_pause = sys_op->rx_pause; 808 809 XGBE_CLR_ADV(&pdata->phy, Pause); 810 XGBE_CLR_ADV(&pdata->phy, Asym_Pause); 811 812 if (sys_op->rx_pause) { 813 XGBE_SET_ADV(&pdata->phy, Pause); 814 XGBE_SET_ADV(&pdata->phy, Asym_Pause); 815 } 816 817 if (sys_op->tx_pause) { 818 /* Equivalent to XOR of Asym_Pause */ 819 if (XGBE_ADV(&pdata->phy, Asym_Pause)) 820 XGBE_CLR_ADV(&pdata->phy, Asym_Pause); 821 else 822 XGBE_SET_ADV(&pdata->phy, Asym_Pause); 823 } 824 825 if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) 826 rc = pdata->phy_if.phy_config_aneg(pdata); 827 828 } 829 830 return (rc); 831 } 832 833 static int 834 sysctl_link_ksettings_handler(SYSCTL_HANDLER_ARGS) 835 { 836 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 837 struct sysctl_op *sys_op = pdata->sys_op; 838 struct sysctl_info sysctl_linksettings[] = { 839 { "autoneg", SYSL_BOOL, autoneg, "supported" }, 840 { "speed", SYSL_U32, speed, "supported" }, 841 { "duplex", SYSL_U8, duplex, "supported" }, 842 }; 843 ssize_t buf_size = 512; 844 char buf[buf_size], link_modes[16], speed_modes[16]; 845 struct sbuf *sb; 846 uint32_t speed; 847 int rc = 0; 848 849 if (req->newptr == NULL) { 850 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 851 if (sb == NULL) { 852 rc = ENOMEM; 853 return (rc); 854 } 855 sys_op->autoneg = pdata->phy.autoneg; 856 sys_op->speed = pdata->phy.speed; 857 sys_op->duplex = pdata->phy.duplex; 858 859 XGBE_LM_COPY(&pdata->phy, supported, &pdata->phy, supported); 860 XGBE_LM_COPY(&pdata->phy, advertising, &pdata->phy, advertising); 861 XGBE_LM_COPY(&pdata->phy, lp_advertising, &pdata->phy, lp_advertising); 862 863 switch (sys_op->speed) { 864 case 1: 865 strcpy(link_modes, "Unknown"); 866 strcpy(speed_modes, "Unknown"); 867 break; 868 case 2: 869 strcpy(link_modes, "10Gbps/Full"); 870 strcpy(speed_modes, "10000"); 871 break; 872 case 3: 873 strcpy(link_modes, "2.5Gbps/Full"); 874 strcpy(speed_modes, "2500"); 875 break; 876 case 4: 877 strcpy(link_modes, "1Gbps/Full"); 878 strcpy(speed_modes, "1000"); 879 break; 880 case 5: 881 strcpy(link_modes, "100Mbps/Full"); 882 strcpy(speed_modes, "100"); 883 break; 884 case 6: 885 strcpy(link_modes, "10Mbps/Full"); 886 strcpy(speed_modes, "10"); 887 break; 888 } 889 890 sbuf_printf(sb, 891 "\nlink_modes: %s\n" 892 "autonegotiation: %s\n" 893 "speed: %sMbps\n", 894 link_modes, 895 (sys_op->autoneg == AUTONEG_DISABLE) ? "off" : "on", 896 speed_modes); 897 898 switch (sys_op->duplex) { 899 case DUPLEX_HALF: 900 sbuf_printf(sb, "Duplex: Half\n"); 901 break; 902 case DUPLEX_FULL: 903 sbuf_printf(sb, "Duplex: Full\n"); 904 break; 905 default: 906 sbuf_printf(sb, "Duplex: Unknown\n"); 907 break; 908 } 909 rc = sbuf_finish(sb); 910 sbuf_delete(sb); 911 return (0); 912 } 913 914 rc = get_ubuf(req, buf); 915 if (rc == 0) { 916 parse_generic_sysctl(pdata, buf, sysctl_linksettings, 917 ARRAY_SIZE(sysctl_linksettings)); 918 919 speed = sys_op->speed; 920 921 if ((sys_op->autoneg != AUTONEG_ENABLE) && 922 (sys_op->autoneg != AUTONEG_DISABLE)) { 923 axgbe_error("unsupported autoneg %hhu\n", 924 (unsigned char)sys_op->autoneg); 925 return (-EINVAL); 926 } 927 928 if (sys_op->autoneg == AUTONEG_DISABLE) { 929 if (!pdata->phy_if.phy_valid_speed(pdata, speed)) { 930 axgbe_error("unsupported speed %u\n", speed); 931 return (-EINVAL); 932 } 933 934 if (sys_op->duplex != DUPLEX_FULL) { 935 axgbe_error("unsupported duplex %hhu\n", 936 (unsigned char)sys_op->duplex); 937 return (-EINVAL); 938 } 939 } 940 941 pdata->phy.autoneg = sys_op->autoneg; 942 pdata->phy.speed = speed; 943 pdata->phy.duplex = sys_op->duplex; 944 945 if (sys_op->autoneg == AUTONEG_ENABLE) 946 XGBE_SET_ADV(&pdata->phy, Autoneg); 947 else 948 XGBE_CLR_ADV(&pdata->phy, Autoneg); 949 950 if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) 951 rc = pdata->phy_if.phy_config_aneg(pdata); 952 } 953 954 return (rc); 955 } 956 957 static int 958 sysctl_ringparam_handler(SYSCTL_HANDLER_ARGS) 959 { 960 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 961 struct sysctl_op *sys_op = pdata->sys_op; 962 struct sysctl_info sysctl_ringparam[] = { 963 { "rx", SYSL_S32, rx_pending, "supported" }, 964 { "rx-mini", SYSL_S32, rx_mini_pending, "supported" }, 965 { "rx-jumbo", SYSL_S32, rx_jumbo_pending, "supported" }, 966 { "tx", SYSL_S32, tx_pending, "supported" }, 967 }; 968 ssize_t buf_size = 512; 969 unsigned int rx, tx; 970 char buf[buf_size]; 971 struct sbuf *sb; 972 int rc = 0; 973 974 if (req->newptr == NULL) { 975 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 976 if (sb == NULL) { 977 rc = ENOMEM; 978 return (rc); 979 } 980 sys_op->rx_max_pending = XGBE_RX_DESC_CNT_MAX; 981 sys_op->tx_max_pending = XGBE_TX_DESC_CNT_MAX; 982 sys_op->rx_pending = pdata->rx_desc_count; 983 sys_op->tx_pending = pdata->tx_desc_count; 984 985 sbuf_printf(sb, 986 "\nPre-set maximums:\n" 987 "RX: %u\n" 988 "RX Mini: %u\n" 989 "RX Jumbo: %u\n" 990 "TX: %u\n", 991 sys_op->rx_max_pending, 992 sys_op->rx_mini_max_pending, 993 sys_op->rx_jumbo_max_pending, 994 sys_op->tx_max_pending); 995 996 sbuf_printf(sb, 997 "\nCurrent hardware settings:\n" 998 "RX: %u\n" 999 "RX Mini: %u\n" 1000 "RX Jumbo: %u\n" 1001 "TX: %u\n", 1002 sys_op->rx_pending, 1003 sys_op->rx_mini_pending, 1004 sys_op->rx_jumbo_pending, 1005 sys_op->tx_pending); 1006 1007 rc = sbuf_finish(sb); 1008 sbuf_delete(sb); 1009 return (0); 1010 } 1011 1012 rc = get_ubuf(req, buf); 1013 if (rc == 0) { 1014 parse_generic_sysctl(pdata, buf, sysctl_ringparam, 1015 ARRAY_SIZE(sysctl_ringparam)); 1016 1017 if (sys_op->rx_mini_pending || sys_op->rx_jumbo_pending) { 1018 axgbe_error("unsupported ring parameter\n"); 1019 return (-EINVAL); 1020 } 1021 1022 if ((sys_op->rx_pending < XGBE_RX_DESC_CNT_MIN) || 1023 (sys_op->rx_pending > XGBE_RX_DESC_CNT_MAX)) { 1024 axgbe_error("rx ring param must be between %u and %u\n", 1025 XGBE_RX_DESC_CNT_MIN, XGBE_RX_DESC_CNT_MAX); 1026 return (-EINVAL); 1027 } 1028 1029 if ((sys_op->tx_pending < XGBE_TX_DESC_CNT_MIN) || 1030 (sys_op->tx_pending > XGBE_TX_DESC_CNT_MAX)) { 1031 axgbe_error("tx ring param must be between %u and %u\n", 1032 XGBE_TX_DESC_CNT_MIN, XGBE_TX_DESC_CNT_MAX); 1033 return (-EINVAL); 1034 } 1035 1036 rx = rounddown_pow_of_two(sys_op->rx_pending); 1037 if (rx != sys_op->rx_pending) 1038 axgbe_printf(1, "rx ring param rounded to power of 2: %u\n", 1039 rx); 1040 1041 tx = rounddown_pow_of_two(sys_op->tx_pending); 1042 if (tx != sys_op->tx_pending) 1043 axgbe_printf(1, "tx ring param rounded to power of 2: %u\n", 1044 tx); 1045 1046 if ((rx == pdata->rx_desc_count) && 1047 (tx == pdata->tx_desc_count)) 1048 goto out; 1049 1050 pdata->rx_desc_count = rx; 1051 pdata->tx_desc_count = tx; 1052 1053 /* TODO - restart dev */ 1054 } 1055 1056 out: 1057 return (0); 1058 } 1059 1060 static int 1061 sysctl_channels_handler(SYSCTL_HANDLER_ARGS) 1062 { 1063 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1064 struct sysctl_op *sys_op = pdata->sys_op; 1065 struct sysctl_info sysctl_channels[] = { 1066 { "rx", SYSL_S32, rx_count, "supported" }, 1067 { "tx", SYSL_S32, tx_count, "supported" }, 1068 { "other", SYSL_S32, other_count, "supported" }, 1069 { "combined", SYSL_S32, combined_count, "supported" }, 1070 }; 1071 unsigned int rx, tx, combined; 1072 ssize_t buf_size = 512; 1073 char buf[buf_size]; 1074 struct sbuf *sb; 1075 int rc = 0; 1076 1077 if (req->newptr == NULL) { 1078 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1079 if (sb == NULL) { 1080 rc = ENOMEM; 1081 return (rc); 1082 } 1083 rx = min(pdata->hw_feat.rx_ch_cnt, pdata->rx_max_channel_count); 1084 rx = min(rx, pdata->channel_irq_count); 1085 tx = min(pdata->hw_feat.tx_ch_cnt, pdata->tx_max_channel_count); 1086 tx = min(tx, pdata->channel_irq_count); 1087 tx = min(tx, pdata->tx_max_q_count); 1088 1089 combined = min(rx, tx); 1090 1091 sys_op->max_combined = combined; 1092 sys_op->max_rx = rx ? rx - 1 : 0; 1093 sys_op->max_tx = tx ? tx - 1 : 0; 1094 1095 /* Get current settings based on device state */ 1096 rx = pdata->rx_ring_count; 1097 tx = pdata->tx_ring_count; 1098 1099 combined = min(rx, tx); 1100 rx -= combined; 1101 tx -= combined; 1102 1103 sys_op->combined_count = combined; 1104 sys_op->rx_count = rx; 1105 sys_op->tx_count = tx; 1106 1107 sbuf_printf(sb, 1108 "\nPre-set maximums:\n" 1109 "RX: %u\n" 1110 "TX: %u\n" 1111 "Other: %u\n" 1112 "Combined: %u\n", 1113 sys_op->max_rx, sys_op->max_tx, 1114 sys_op->max_other, 1115 sys_op->max_combined); 1116 1117 sbuf_printf(sb, 1118 "\nCurrent hardware settings:\n" 1119 "RX: %u\n" 1120 "TX: %u\n" 1121 "Other: %u\n" 1122 "Combined: %u\n", 1123 sys_op->rx_count, sys_op->tx_count, 1124 sys_op->other_count, 1125 sys_op->combined_count); 1126 1127 rc = sbuf_finish(sb); 1128 sbuf_delete(sb); 1129 return (0); 1130 } 1131 1132 rc = get_ubuf(req, buf); 1133 if (rc == 0) { 1134 parse_generic_sysctl(pdata, buf, sysctl_channels, 1135 ARRAY_SIZE(sysctl_channels)); 1136 1137 axgbe_error( "channel inputs: combined=%u, rx-only=%u," 1138 " tx-only=%u\n", sys_op->combined_count, 1139 sys_op->rx_count, sys_op->tx_count); 1140 } 1141 1142 return (rc); 1143 } 1144 1145 1146 static int 1147 sysctl_mac_stats_handler(SYSCTL_HANDLER_ARGS) 1148 { 1149 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1150 ssize_t buf_size = 64; 1151 struct sbuf *sb; 1152 int rc = 0; 1153 int i; 1154 1155 if (req->newptr == NULL) { 1156 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1157 if (sb == NULL) { 1158 rc = ENOMEM; 1159 return (rc); 1160 } 1161 1162 pdata->hw_if.read_mmc_stats(pdata); 1163 for (i = 0; i < XGBE_STATS_COUNT; i++) { 1164 sbuf_printf(sb, "\n %s: %lu", 1165 xgbe_gstring_stats[i].stat_string, 1166 *(uint64_t *)((uint8_t *)pdata + xgbe_gstring_stats[i].stat_offset)); 1167 } 1168 for (i = 0; i < pdata->tx_ring_count; i++) { 1169 sbuf_printf(sb, 1170 "\n txq_packets[%d]: %lu" 1171 "\n txq_bytes[%d]: %lu", 1172 i, pdata->ext_stats.txq_packets[i], 1173 i, pdata->ext_stats.txq_bytes[i]); 1174 } 1175 for (i = 0; i < pdata->rx_ring_count; i++) { 1176 sbuf_printf(sb, 1177 "\n rxq_packets[%d]: %lu" 1178 "\n rxq_bytes[%d]: %lu", 1179 i, pdata->ext_stats.rxq_packets[i], 1180 i, pdata->ext_stats.rxq_bytes[i]); 1181 } 1182 1183 rc = sbuf_finish(sb); 1184 sbuf_delete(sb); 1185 return (rc); 1186 } 1187 1188 return (-EINVAL); 1189 } 1190 1191 static int 1192 sysctl_xgmac_reg_value_handler(SYSCTL_HANDLER_ARGS) 1193 { 1194 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1195 ssize_t buf_size = 64; 1196 char buf[buf_size]; 1197 unsigned int value; 1198 struct sbuf *sb; 1199 int rc = 0; 1200 1201 if (req->newptr == NULL) { 1202 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1203 if (sb == NULL) { 1204 rc = ENOMEM; 1205 return (rc); 1206 } 1207 1208 value = XGMAC_IOREAD(pdata, pdata->sysctl_xgmac_reg); 1209 axgbe_printf(2, "READ: %s: value: 0x%x\n", __func__, value); 1210 sbuf_printf(sb, "\nXGMAC reg_value: 0x%x\n", value); 1211 rc = sbuf_finish(sb); 1212 sbuf_delete(sb); 1213 return (rc); 1214 } 1215 1216 rc = get_ubuf(req, buf); 1217 if (rc == 0) { 1218 sscanf(buf, "%x", &value); 1219 axgbe_printf(2, "WRITE: %s: value: 0x%x\n", __func__, value); 1220 XGMAC_IOWRITE(pdata, pdata->sysctl_xgmac_reg, value); 1221 } 1222 1223 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1224 return (rc); 1225 } 1226 1227 static int 1228 sysctl_xpcs_mmd_reg_handler(SYSCTL_HANDLER_ARGS) 1229 { 1230 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1231 ssize_t buf_size = 64; 1232 char buf[buf_size]; 1233 struct sbuf *sb; 1234 unsigned int reg; 1235 int rc = 0; 1236 1237 if (req->newptr == NULL) { 1238 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1239 if (sb == NULL) { 1240 rc = ENOMEM; 1241 return (rc); 1242 } 1243 1244 axgbe_printf(2, "READ: %s: xpcs_mmd: 0x%x\n", __func__, 1245 pdata->sysctl_xpcs_mmd); 1246 sbuf_printf(sb, "\nXPCS mmd_reg: 0x%x\n", 1247 pdata->sysctl_xpcs_mmd); 1248 rc = sbuf_finish(sb); 1249 sbuf_delete(sb); 1250 return (rc); 1251 } 1252 1253 rc = get_ubuf(req, buf); 1254 if (rc == 0) { 1255 sscanf(buf, "%x", ®); 1256 axgbe_printf(2, "WRITE: %s: mmd_reg: 0x%x\n", __func__, reg); 1257 pdata->sysctl_xpcs_mmd = reg; 1258 } 1259 1260 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1261 return (rc); 1262 } 1263 1264 static int 1265 sysctl_xpcs_reg_addr_handler(SYSCTL_HANDLER_ARGS) 1266 { 1267 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1268 ssize_t buf_size = 64; 1269 char buf[buf_size]; 1270 struct sbuf *sb; 1271 unsigned int reg; 1272 int rc = 0; 1273 1274 if (req->newptr == NULL) { 1275 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1276 if (sb == NULL) { 1277 rc = ENOMEM; 1278 return (rc); 1279 } 1280 1281 axgbe_printf(2, "READ: %s: sysctl_xpcs_reg: 0x%x\n", __func__, 1282 pdata->sysctl_xpcs_reg); 1283 sbuf_printf(sb, "\nXPCS reg_addr: 0x%x\n", 1284 pdata->sysctl_xpcs_reg); 1285 rc = sbuf_finish(sb); 1286 sbuf_delete(sb); 1287 return (rc); 1288 } 1289 1290 rc = get_ubuf(req, buf); 1291 if (rc == 0) { 1292 sscanf(buf, "%x", ®); 1293 axgbe_printf(2, "WRITE: %s: reg: 0x%x\n", __func__, reg); 1294 pdata->sysctl_xpcs_reg = reg; 1295 } 1296 1297 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1298 return (rc); 1299 } 1300 1301 static int 1302 sysctl_xpcs_reg_value_handler(SYSCTL_HANDLER_ARGS) 1303 { 1304 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1305 ssize_t buf_size = 64; 1306 char buf[buf_size]; 1307 unsigned int value; 1308 struct sbuf *sb; 1309 int rc = 0; 1310 1311 if (req->newptr == NULL) { 1312 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1313 if (sb == NULL) { 1314 rc = ENOMEM; 1315 return (rc); 1316 } 1317 1318 value = XMDIO_READ(pdata, pdata->sysctl_xpcs_mmd, 1319 pdata->sysctl_xpcs_reg); 1320 axgbe_printf(2, "READ: %s: value: 0x%x\n", __func__, value); 1321 sbuf_printf(sb, "\nXPCS reg_value: 0x%x\n", value); 1322 rc = sbuf_finish(sb); 1323 sbuf_delete(sb); 1324 return (rc); 1325 } 1326 1327 rc = get_ubuf(req, buf); 1328 if (rc == 0) { 1329 sscanf(buf, "%x", &value); 1330 axgbe_printf(2, "WRITE: %s: value: 0x%x\n", __func__, value); 1331 XMDIO_WRITE(pdata, pdata->sysctl_xpcs_mmd, 1332 pdata->sysctl_xpcs_reg, value); 1333 } 1334 1335 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1336 return (rc); 1337 } 1338 1339 static int 1340 sysctl_xprop_reg_addr_handler(SYSCTL_HANDLER_ARGS) 1341 { 1342 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1343 ssize_t buf_size = 64; 1344 char buf[buf_size]; 1345 struct sbuf *sb; 1346 unsigned int reg; 1347 int rc = 0; 1348 1349 if (req->newptr == NULL) { 1350 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1351 if (sb == NULL) { 1352 rc = ENOMEM; 1353 return (rc); 1354 } 1355 1356 axgbe_printf(2, "READ: %s: sysctl_xprop_reg: 0x%x\n", __func__, 1357 pdata->sysctl_xprop_reg); 1358 sbuf_printf(sb, "\nXPROP reg_addr: 0x%x\n", 1359 pdata->sysctl_xprop_reg); 1360 rc = sbuf_finish(sb); 1361 sbuf_delete(sb); 1362 return (rc); 1363 } 1364 1365 rc = get_ubuf(req, buf); 1366 if (rc == 0) { 1367 sscanf(buf, "%x", ®); 1368 axgbe_printf(2, "WRITE: %s: reg: 0x%x\n", __func__, reg); 1369 pdata->sysctl_xprop_reg = reg; 1370 } 1371 1372 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1373 return (rc); 1374 } 1375 1376 static int 1377 sysctl_xprop_reg_value_handler(SYSCTL_HANDLER_ARGS) 1378 { 1379 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1380 ssize_t buf_size = 64; 1381 char buf[buf_size]; 1382 unsigned int value; 1383 struct sbuf *sb; 1384 int rc = 0; 1385 1386 if (req->newptr == NULL) { 1387 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1388 if (sb == NULL) { 1389 rc = ENOMEM; 1390 return (rc); 1391 } 1392 1393 value = XP_IOREAD(pdata, pdata->sysctl_xprop_reg); 1394 axgbe_printf(2, "READ: %s: value: 0x%x\n", __func__, value); 1395 sbuf_printf(sb, "\nXPROP reg_value: 0x%x\n", value); 1396 rc = sbuf_finish(sb); 1397 sbuf_delete(sb); 1398 return (rc); 1399 } 1400 1401 rc = get_ubuf(req, buf); 1402 if (rc == 0) { 1403 sscanf(buf, "%x", &value); 1404 axgbe_printf(2, "WRITE: %s: value: 0x%x\n", __func__, value); 1405 XP_IOWRITE(pdata, pdata->sysctl_xprop_reg, value); 1406 } 1407 1408 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1409 return (rc); 1410 } 1411 1412 static int 1413 sysctl_xi2c_reg_addr_handler(SYSCTL_HANDLER_ARGS) 1414 { 1415 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1416 ssize_t buf_size = 64; 1417 char buf[buf_size]; 1418 struct sbuf *sb; 1419 unsigned int reg; 1420 int rc = 0; 1421 1422 if (req->newptr == NULL) { 1423 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1424 if (sb == NULL) { 1425 rc = ENOMEM; 1426 return (rc); 1427 } 1428 1429 axgbe_printf(2, "READ: %s: sysctl_xi2c_reg: 0x%x\n", __func__, 1430 pdata->sysctl_xi2c_reg); 1431 sbuf_printf(sb, "\nXI2C reg_addr: 0x%x\n", 1432 pdata->sysctl_xi2c_reg); 1433 rc = sbuf_finish(sb); 1434 sbuf_delete(sb); 1435 return (rc); 1436 } 1437 1438 rc = get_ubuf(req, buf); 1439 if (rc == 0) { 1440 sscanf(buf, "%x", ®); 1441 axgbe_printf(2, "WRITE: %s: reg: 0x%x\n", __func__, reg); 1442 pdata->sysctl_xi2c_reg = reg; 1443 } 1444 1445 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1446 return (rc); 1447 } 1448 1449 static int 1450 sysctl_xi2c_reg_value_handler(SYSCTL_HANDLER_ARGS) 1451 { 1452 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1453 ssize_t buf_size = 64; 1454 char buf[buf_size]; 1455 unsigned int value; 1456 struct sbuf *sb; 1457 int rc = 0; 1458 1459 if (req->newptr == NULL) { 1460 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1461 if (sb == NULL) { 1462 rc = ENOMEM; 1463 return (rc); 1464 } 1465 1466 value = XI2C_IOREAD(pdata, pdata->sysctl_xi2c_reg); 1467 axgbe_printf(2, "READ: %s: value: 0x%x\n", __func__, value); 1468 sbuf_printf(sb, "\nXI2C reg_value: 0x%x\n", value); 1469 rc = sbuf_finish(sb); 1470 sbuf_delete(sb); 1471 return (rc); 1472 } 1473 1474 rc = get_ubuf(req, buf); 1475 if (rc == 0) { 1476 sscanf(buf, "%x", &value); 1477 axgbe_printf(2, "WRITE: %s: value: 0x%x\n", __func__, value); 1478 XI2C_IOWRITE(pdata, pdata->sysctl_xi2c_reg, value); 1479 } 1480 1481 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1482 return (rc); 1483 } 1484 1485 static int 1486 sysctl_an_cdr_wr_handler(SYSCTL_HANDLER_ARGS) 1487 { 1488 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1489 unsigned int an_cdr_wr = 0; 1490 ssize_t buf_size = 64; 1491 char buf[buf_size]; 1492 struct sbuf *sb; 1493 int rc = 0; 1494 1495 if (req->newptr == NULL) { 1496 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1497 if (sb == NULL) { 1498 rc = ENOMEM; 1499 return (rc); 1500 } 1501 1502 axgbe_printf(2, "READ: %s: an_cdr_wr: %d\n", __func__, 1503 pdata->sysctl_an_cdr_workaround); 1504 sbuf_printf(sb, "%d\n", pdata->sysctl_an_cdr_workaround); 1505 rc = sbuf_finish(sb); 1506 sbuf_delete(sb); 1507 return (rc); 1508 } 1509 1510 rc = get_ubuf(req, buf); 1511 if (rc == 0) { 1512 sscanf(buf, "%u", &an_cdr_wr); 1513 axgbe_printf(2, "WRITE: %s: an_cdr_wr: 0x%d\n", __func__, 1514 an_cdr_wr); 1515 1516 if (an_cdr_wr) 1517 pdata->sysctl_an_cdr_workaround = 1; 1518 else 1519 pdata->sysctl_an_cdr_workaround = 0; 1520 } 1521 1522 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1523 return (rc); 1524 } 1525 1526 static int 1527 sysctl_an_cdr_track_early_handler(SYSCTL_HANDLER_ARGS) 1528 { 1529 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1530 unsigned int an_cdr_track_early = 0; 1531 ssize_t buf_size = 64; 1532 char buf[buf_size]; 1533 struct sbuf *sb; 1534 int rc = 0; 1535 1536 if (req->newptr == NULL) { 1537 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1538 if (sb == NULL) { 1539 rc = ENOMEM; 1540 return (rc); 1541 } 1542 1543 axgbe_printf(2, "READ: %s: an_cdr_track_early %d\n", __func__, 1544 pdata->sysctl_an_cdr_track_early); 1545 sbuf_printf(sb, "%d\n", pdata->sysctl_an_cdr_track_early); 1546 rc = sbuf_finish(sb); 1547 sbuf_delete(sb); 1548 return (rc); 1549 } 1550 1551 rc = get_ubuf(req, buf); 1552 if (rc == 0) { 1553 sscanf(buf, "%u", &an_cdr_track_early); 1554 axgbe_printf(2, "WRITE: %s: an_cdr_track_early: %d\n", __func__, 1555 an_cdr_track_early); 1556 1557 if (an_cdr_track_early) 1558 pdata->sysctl_an_cdr_track_early = 1; 1559 else 1560 pdata->sysctl_an_cdr_track_early = 0; 1561 } 1562 1563 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1564 return (rc); 1565 } 1566 1567 void 1568 axgbe_sysctl_exit(struct xgbe_prv_data *pdata) 1569 { 1570 1571 if (pdata->sys_op) 1572 free(pdata->sys_op, M_AXGBE); 1573 } 1574 1575 void 1576 axgbe_sysctl_init(struct xgbe_prv_data *pdata) 1577 { 1578 struct sysctl_ctx_list *clist; 1579 struct sysctl_oid_list *top; 1580 struct sysctl_oid *parent; 1581 struct sysctl_op *sys_op; 1582 1583 sys_op = malloc(sizeof(*sys_op), M_AXGBE, M_WAITOK | M_ZERO); 1584 pdata->sys_op = sys_op; 1585 1586 clist = device_get_sysctl_ctx(pdata->dev); 1587 parent = device_get_sysctl_tree(pdata->dev); 1588 top = SYSCTL_CHILDREN(parent); 1589 1590 /* Set defaults */ 1591 pdata->sysctl_xgmac_reg = 0; 1592 pdata->sysctl_xpcs_mmd = 1; 1593 pdata->sysctl_xpcs_reg = 0; 1594 pdata->link_workaround = 1; 1595 pdata->tx_pause = 1; 1596 pdata->rx_pause = 1; 1597 pdata->enable_rss = 1; 1598 1599 SYSCTL_ADD_UINT(clist, top, OID_AUTO, "axgbe_debug_level", CTLFLAG_RWTUN, 1600 &pdata->debug_level, 0, "axgbe log level -- higher is verbose"); 1601 1602 SYSCTL_ADD_UINT(clist, top, OID_AUTO, "sph_enable", 1603 CTLFLAG_RDTUN, &pdata->sph_enable, 1, 1604 "shows the split header feature state (1 - enable, 0 - disable"); 1605 1606 SYSCTL_ADD_UINT(clist, top, OID_AUTO, "link_workaround", 1607 CTLFLAG_RWTUN, &pdata->link_workaround, 0, 1608 "enable the workaround for link issue in coming up"); 1609 1610 SYSCTL_ADD_UINT(clist, top, OID_AUTO, "rss_enabled", 1611 CTLFLAG_RDTUN, &pdata->enable_rss, 1, 1612 "shows the RSS feature state (1 - enable, 0 - disable)"); 1613 1614 SYSCTL_ADD_UINT(clist, top, OID_AUTO, "tx_pause", 1615 CTLFLAG_RDTUN, &pdata->tx_pause, 1, 1616 "shows the Flow Control TX pause feature state (1 - enable, 0 - disable)"); 1617 1618 SYSCTL_ADD_UINT(clist, top, OID_AUTO, "rx_pause", 1619 CTLFLAG_RDTUN, &pdata->rx_pause, 1, 1620 "shows the Flow Control RX pause feature state (1 - enable, 0 - disable)"); 1621 1622 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xgmac_register", 1623 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1624 pdata, 0, sysctl_xgmac_reg_addr_handler, "IU", 1625 "xgmac register addr"); 1626 1627 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xgmac_register_value", 1628 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1629 pdata, 0, sysctl_xgmac_reg_value_handler, "IU", 1630 "xgmac register value"); 1631 1632 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xpcs_mmd", 1633 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1634 pdata, 0, sysctl_xpcs_mmd_reg_handler, "IU", "xpcs mmd register"); 1635 1636 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xpcs_register", 1637 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1638 pdata, 0, sysctl_xpcs_reg_addr_handler, "IU", "xpcs register"); 1639 1640 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xpcs_register_value", 1641 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1642 pdata, 0, sysctl_xpcs_reg_value_handler, "IU", 1643 "xpcs register value"); 1644 1645 if (pdata->xpcs_res) { 1646 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xprop_register", 1647 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1648 pdata, 0, sysctl_xprop_reg_addr_handler, 1649 "IU", "xprop register"); 1650 1651 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xprop_register_value", 1652 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1653 pdata, 0, sysctl_xprop_reg_value_handler, 1654 "IU", "xprop register value"); 1655 } 1656 1657 if (pdata->xpcs_res) { 1658 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xi2c_register", 1659 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1660 pdata, 0, sysctl_xi2c_reg_addr_handler, 1661 "IU", "xi2c register"); 1662 1663 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xi2c_register_value", 1664 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1665 pdata, 0, sysctl_xi2c_reg_value_handler, 1666 "IU", "xi2c register value"); 1667 } 1668 1669 if (pdata->vdata->an_cdr_workaround) { 1670 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "an_cdr_workaround", 1671 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1672 pdata, 0, sysctl_an_cdr_wr_handler, "IU", 1673 "an cdr workaround"); 1674 1675 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "an_cdr_track_early", 1676 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1677 pdata, 0, sysctl_an_cdr_track_early_handler, "IU", 1678 "an cdr track early"); 1679 } 1680 1681 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "drv_info", 1682 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1683 pdata, 0, sysctl_get_drv_info_handler, "IU", 1684 "xgbe drv info"); 1685 1686 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "link_info", 1687 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1688 pdata, 0, sysctl_get_link_info_handler, "IU", 1689 "xgbe link info"); 1690 1691 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "coalesce_info", 1692 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1693 pdata, 0, sysctl_coalesce_handler, "IU", 1694 "xgbe coalesce info"); 1695 1696 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "pauseparam_info", 1697 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1698 pdata, 0, sysctl_pauseparam_handler, "IU", 1699 "xgbe pauseparam info"); 1700 1701 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "link_ksettings_info", 1702 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1703 pdata, 0, sysctl_link_ksettings_handler, "IU", 1704 "xgbe link_ksettings info"); 1705 1706 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "ringparam_info", 1707 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1708 pdata, 0, sysctl_ringparam_handler, "IU", 1709 "xgbe ringparam info"); 1710 1711 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "channels_info", 1712 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1713 pdata, 0, sysctl_channels_handler, "IU", 1714 "xgbe channels info"); 1715 1716 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "mac_stats", 1717 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 1718 pdata, 0, sysctl_mac_stats_handler, "IU", 1719 "xgbe mac stats"); 1720 } 1721