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