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 unsigned 248 fls_long(unsigned long l) 249 { 250 251 if (sizeof(l) == 4) 252 return (fls(l)); 253 return (fls64(l)); 254 } 255 256 static inline __attribute__((const)) 257 unsigned long __rounddown_pow_of_two(unsigned long n) 258 { 259 260 return (1UL << (fls_long(n) - 1)); 261 } 262 263 static inline int 264 get_ubuf(struct sysctl_req *req, char *ubuf) 265 { 266 int rc; 267 268 printf("%s: len:0x%li idx:0x%li\n", __func__, req->newlen, 269 req->newidx); 270 if (req->newlen >= SYSCTL_BUF_LEN) 271 return (-EINVAL); 272 273 rc = SYSCTL_IN(req, ubuf, req->newlen); 274 if (rc) 275 return (rc); 276 ubuf[req->newlen] = '\0'; 277 278 return (0); 279 } 280 281 char** 282 alloc_sysctl_buffer(void) 283 { 284 char **buffer; 285 int i; 286 287 buffer = malloc(sizeof(char *)*32, M_AXGBE, M_WAITOK | M_ZERO); 288 for(i = 0; i < 32; i++) 289 buffer[i] = malloc(sizeof(char)*32, M_AXGBE, M_WAITOK | M_ZERO); 290 291 return (buffer); 292 } 293 294 void 295 get_val(char *buf, char **op, char **val, int *n_op) 296 { 297 int blen = strlen(buf); 298 int count = 0; 299 int i, j; 300 301 *n_op = 0; 302 for (i = 0; i < blen; i++) { 303 count++; 304 /* Get sysctl command option */ 305 for (j = 0; buf[i] != ' '; j++) { 306 if (i >= blen) 307 break; 308 op[*n_op][j] = buf[i++]; 309 } 310 op[*n_op][j+1] = '\0'; 311 if (i >= strlen(buf)) 312 goto out; 313 314 /* Get sysctl value*/ 315 i++; 316 for (j = 0; buf[i] != ' '; j++) { 317 if (i >= blen) 318 break; 319 val[*n_op][j] = buf[i++]; 320 } 321 val[*n_op][j+1] = '\0'; 322 if (i >= strlen(buf)) 323 goto out; 324 325 *n_op = count; 326 } 327 328 out: 329 *n_op = count; 330 } 331 332 void 333 fill_data(struct sysctl_op *sys_op, int flag, unsigned int value) 334 { 335 336 switch(flag) { 337 case 1: 338 sys_op->rx_coalesce_usecs = value; 339 break; 340 case 2: 341 sys_op->rx_max_coalesced_frames = value; 342 break; 343 case 3: 344 sys_op->rx_coalesce_usecs_irq = value; 345 break; 346 case 4: 347 sys_op->rx_max_coalesced_frames_irq = value; 348 break; 349 case 5: 350 sys_op->tx_coalesce_usecs = value; 351 break; 352 case 6: 353 sys_op->tx_max_coalesced_frames = value; 354 break; 355 case 7: 356 sys_op->tx_coalesce_usecs_irq = value; 357 break; 358 case 8: 359 sys_op->tx_max_coalesced_frames_irq = value; 360 break; 361 case 9: 362 sys_op->stats_block_coalesce_usecs = value; 363 break; 364 case 10: 365 sys_op->use_adaptive_rx_coalesce = value; 366 break; 367 case 11: 368 sys_op->use_adaptive_tx_coalesce = value; 369 break; 370 case 12: 371 sys_op->pkt_rate_low = value; 372 break; 373 case 13: 374 sys_op->rx_coalesce_usecs_low = value; 375 break; 376 case 14: 377 sys_op->rx_max_coalesced_frames_low = value; 378 break; 379 case 15: 380 sys_op->tx_coalesce_usecs_low = value; 381 break; 382 case 16: 383 sys_op->tx_max_coalesced_frames_low = value; 384 break; 385 case 17: 386 sys_op->pkt_rate_high = value; 387 break; 388 case 18: 389 sys_op->rx_coalesce_usecs_high = value; 390 break; 391 case 19: 392 sys_op->rx_max_coalesced_frames_high = value; 393 break; 394 case 20: 395 sys_op->tx_coalesce_usecs_high = value; 396 break; 397 case 21: 398 sys_op->tx_max_coalesced_frames_high = value; 399 break; 400 case 22: 401 sys_op->rate_sample_interval = value; 402 break; 403 case 23: 404 sys_op->autoneg = value; 405 break; 406 case 24: 407 sys_op->rx_pause = value; 408 break; 409 case 25: 410 sys_op->tx_pause = value; 411 break; 412 case 26: 413 sys_op->speed = value; 414 break; 415 case 27: 416 sys_op->duplex = value; 417 break; 418 case 28: 419 sys_op->rx_pending = value; 420 break; 421 case 29: 422 sys_op->rx_mini_pending = value; 423 break; 424 case 30: 425 sys_op->rx_jumbo_pending = value; 426 break; 427 case 31: 428 sys_op->tx_pending = value; 429 break; 430 default: 431 printf("Option error\n"); 432 } 433 } 434 435 static int 436 parse_generic_sysctl(struct xgbe_prv_data *pdata, char *buf, 437 struct sysctl_info *info, unsigned int n_info) 438 { 439 struct sysctl_op *sys_op = pdata->sys_op; 440 unsigned int value; 441 char **op, **val; 442 int n_op = 0; 443 int rc = 0; 444 int i, idx; 445 446 op = alloc_sysctl_buffer(); 447 val = alloc_sysctl_buffer(); 448 get_val(buf, op, val, &n_op); 449 450 for (i = 0; i < n_op; i++) { 451 for (idx = 0; idx < n_info; idx++) { 452 if (strcmp(info[idx].name, op[i]) == 0) { 453 if (strcmp(info[idx].support, 454 "not-supported") == 0){ 455 axgbe_printf(1, "ignoring not-supported " 456 "option \"%s\"\n", info[idx].name); 457 break; 458 } 459 switch(info[idx].type) { 460 case SYSL_BOOL: { 461 if (!strcmp(val[i], "on")) 462 fill_data(sys_op, 463 info[idx].flag, 1); 464 else if (!strcmp(val[i], "off")) 465 fill_data(sys_op, 466 info[idx].flag, 0); 467 else 468 rc = exit_bad_op(); 469 break; 470 } 471 case SYSL_S32: 472 sscanf(val[i], "%u", &value); 473 fill_data(sys_op, info[idx].flag, value); 474 break; 475 case SYSL_U8: 476 if (!strcmp(val[i], "half")) 477 fill_data(sys_op, 478 info[idx].flag, DUPLEX_HALF); 479 else if (!strcmp(val[i], "full")) 480 fill_data(sys_op, 481 info[idx].flag, DUPLEX_FULL); 482 else 483 exit_bad_op(); 484 default: 485 rc = exit_bad_op(); 486 } 487 } 488 } 489 } 490 491 for(i = 0; i < 32; i++) 492 free(op[i], M_AXGBE); 493 free(op, M_AXGBE); 494 495 for(i = 0; i < 32; i++) 496 free(val[i], M_AXGBE); 497 free(val, M_AXGBE); 498 return (rc); 499 } 500 501 502 static int 503 sysctl_xgmac_reg_addr_handler(SYSCTL_HANDLER_ARGS) 504 { 505 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 506 ssize_t buf_size = 64; 507 char buf[buf_size]; 508 struct sbuf *sb; 509 unsigned int reg; 510 int rc = 0; 511 512 if (req->newptr == NULL) { 513 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 514 if (sb == NULL) { 515 rc = ENOMEM; 516 return (rc); 517 } 518 519 axgbe_printf(2, "READ: %s: sysctl_xgmac_reg: 0x%x\n", __func__, 520 pdata->sysctl_xgmac_reg); 521 sbuf_printf(sb, "\nXGMAC reg_addr: 0x%x\n", 522 pdata->sysctl_xgmac_reg); 523 rc = sbuf_finish(sb); 524 sbuf_delete(sb); 525 return (rc); 526 } 527 528 rc = get_ubuf(req, buf); 529 if (rc == 0) { 530 sscanf(buf, "%x", ®); 531 axgbe_printf(2, "WRITE: %s: reg: 0x%x\n", __func__, reg); 532 pdata->sysctl_xgmac_reg = reg; 533 } 534 535 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 536 return (rc); 537 } 538 539 static int 540 sysctl_get_drv_info_handler(SYSCTL_HANDLER_ARGS) 541 { 542 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 543 struct xgbe_hw_features *hw_feat = &pdata->hw_feat; 544 ssize_t buf_size = 64; 545 struct sbuf *sb; 546 int rc = 0; 547 548 if (req->newptr == NULL) { 549 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 550 if (sb == NULL) { 551 rc = ENOMEM; 552 return (rc); 553 } 554 555 sbuf_printf(sb, "\ndriver: %s", XGBE_DRV_NAME); 556 sbuf_printf(sb, "\nversion: %s", XGBE_DRV_VERSION); 557 sbuf_printf(sb, "\nfirmware-version: %d.%d.%d", 558 XGMAC_GET_BITS(hw_feat->version, MAC_VR, USERVER), 559 XGMAC_GET_BITS(hw_feat->version, MAC_VR, DEVID), 560 XGMAC_GET_BITS(hw_feat->version, MAC_VR, SNPSVER)); 561 sbuf_printf(sb, "\nbus-info: %04d:%02d:%02d", 562 pdata->pcie_bus, pdata->pcie_device, pdata->pcie_func); 563 564 rc = sbuf_finish(sb); 565 sbuf_delete(sb); 566 return (rc); 567 } 568 569 return (-EINVAL); 570 } 571 572 static int 573 sysctl_get_link_info_handler(SYSCTL_HANDLER_ARGS) 574 { 575 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 576 ssize_t buf_size = 64; 577 struct sbuf *sb; 578 int rc = 0; 579 580 if (req->newptr == NULL) { 581 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 582 if (sb == NULL) { 583 rc = ENOMEM; 584 return (rc); 585 } 586 587 sbuf_printf(sb, "\nLink is %s", pdata->phy.link ? "Up" : "Down"); 588 rc = sbuf_finish(sb); 589 sbuf_delete(sb); 590 return (0); 591 } 592 593 return (-EINVAL); 594 } 595 596 #define COALESCE_SYSCTL_INFO(__coalop) \ 597 { \ 598 { "adaptive-rx", SYSL_BOOL, use_adaptive_rx_coalesce, "not-supported" }, \ 599 { "adaptive-tx", SYSL_BOOL, use_adaptive_tx_coalesce, "not-supported" }, \ 600 { "sample-interval", SYSL_S32, rate_sample_interval, "not-supported" }, \ 601 { "stats-block-usecs", SYSL_S32, stats_block_coalesce_usecs, "not-supported" }, \ 602 { "pkt-rate-low", SYSL_S32, pkt_rate_low, "not-supported" }, \ 603 { "pkt-rate-high", SYSL_S32, pkt_rate_high, "not-supported" }, \ 604 { "rx-usecs", SYSL_S32, rx_coalesce_usecs, "supported" }, \ 605 { "rx-frames", SYSL_S32, rx_max_coalesced_frames, "supported" }, \ 606 { "rx-usecs-irq", SYSL_S32, rx_coalesce_usecs_irq, "not-supported" }, \ 607 { "rx-frames-irq", SYSL_S32, rx_max_coalesced_frames_irq, "not-supported" }, \ 608 { "tx-usecs", SYSL_S32, tx_coalesce_usecs, "not-supported" }, \ 609 { "tx-frames", SYSL_S32, tx_max_coalesced_frames, "supported" }, \ 610 { "tx-usecs-irq", SYSL_S32, tx_coalesce_usecs_irq, "not-supported" }, \ 611 { "tx-frames-irq", SYSL_S32, tx_max_coalesced_frames_irq, "not-supported" }, \ 612 { "rx-usecs-low", SYSL_S32, rx_coalesce_usecs_low, "not-supported" }, \ 613 { "rx-frames-low", SYSL_S32, rx_max_coalesced_frames_low, "not-supported"}, \ 614 { "tx-usecs-low", SYSL_S32, tx_coalesce_usecs_low, "not-supported" }, \ 615 { "tx-frames-low", SYSL_S32, tx_max_coalesced_frames_low, "not-supported" }, \ 616 { "rx-usecs-high", SYSL_S32, rx_coalesce_usecs_high, "not-supported" }, \ 617 { "rx-frames-high", SYSL_S32, rx_max_coalesced_frames_high, "not-supported" }, \ 618 { "tx-usecs-high", SYSL_S32, tx_coalesce_usecs_high, "not-supported" }, \ 619 { "tx-frames-high", SYSL_S32, tx_max_coalesced_frames_high, "not-supported" }, \ 620 } 621 622 static int 623 sysctl_coalesce_handler(SYSCTL_HANDLER_ARGS) 624 { 625 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 626 struct xgbe_hw_if *hw_if = &pdata->hw_if; 627 struct sysctl_op *sys_op = pdata->sys_op; 628 struct sysctl_info sysctl_coalesce[] = COALESCE_SYSCTL_INFO(coalop); 629 unsigned int rx_frames, rx_riwt, rx_usecs; 630 unsigned int tx_frames; 631 ssize_t buf_size = 64; 632 char buf[buf_size]; 633 struct sbuf *sb; 634 int rc = 0; 635 636 if (req->newptr == NULL) { 637 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 638 if (sb == NULL) { 639 rc = ENOMEM; 640 return (rc); 641 } 642 sys_op->rx_coalesce_usecs = pdata->rx_usecs; 643 sys_op->rx_max_coalesced_frames = pdata->rx_frames; 644 sys_op->tx_max_coalesced_frames = pdata->tx_frames; 645 646 sbuf_printf(sb, "\nAdaptive RX: %s TX: %s\n", 647 sys_op->use_adaptive_rx_coalesce ? "on" : "off", 648 sys_op->use_adaptive_tx_coalesce ? "on" : "off"); 649 650 sbuf_printf(sb, "stats-block-usecs: %u\n" 651 "sample-interval: %u\n" 652 "pkt-rate-low: %u\n" 653 "pkt-rate-high: %u\n" 654 "\n" 655 "rx-usecs: %u\n" 656 "rx-frames: %u\n" 657 "rx-usecs-irq: %u\n" 658 "rx-frames-irq: %u\n" 659 "\n" 660 "tx-usecs: %u\n" 661 "tx-frames: %u\n" 662 "tx-usecs-irq: %u\n" 663 "tx-frames-irq: %u\n" 664 "\n" 665 "rx-usecs-low: %u\n" 666 "rx-frames-low: %u\n" 667 "tx-usecs-low: %u\n" 668 "tx-frames-low: %u\n" 669 "\n" 670 "rx-usecs-high: %u\n" 671 "rx-frames-high: %u\n" 672 "tx-usecs-high: %u\n" 673 "tx-frames-high: %u\n", 674 sys_op->stats_block_coalesce_usecs, 675 sys_op->rate_sample_interval, 676 sys_op->pkt_rate_low, 677 sys_op->pkt_rate_high, 678 679 sys_op->rx_coalesce_usecs, 680 sys_op->rx_max_coalesced_frames, 681 sys_op->rx_coalesce_usecs_irq, 682 sys_op->rx_max_coalesced_frames_irq, 683 684 sys_op->tx_coalesce_usecs, 685 sys_op->tx_max_coalesced_frames, 686 sys_op->tx_coalesce_usecs_irq, 687 sys_op->tx_max_coalesced_frames_irq, 688 689 sys_op->rx_coalesce_usecs_low, 690 sys_op->rx_max_coalesced_frames_low, 691 sys_op->tx_coalesce_usecs_low, 692 sys_op->tx_max_coalesced_frames_low, 693 694 sys_op->rx_coalesce_usecs_high, 695 sys_op->rx_max_coalesced_frames_high, 696 sys_op->tx_coalesce_usecs_high, 697 sys_op->tx_max_coalesced_frames_high); 698 699 rc = sbuf_finish(sb); 700 sbuf_delete(sb); 701 return (0); 702 } 703 704 rc = get_ubuf(req, buf); 705 if (rc == 0) { 706 parse_generic_sysctl(pdata, buf, sysctl_coalesce, 707 ARRAY_SIZE(sysctl_coalesce)); 708 709 rx_riwt = hw_if->usec_to_riwt(pdata, sys_op->rx_coalesce_usecs); 710 rx_usecs = sys_op->rx_coalesce_usecs; 711 rx_frames = sys_op->rx_max_coalesced_frames; 712 713 /* Use smallest possible value if conversion resulted in zero */ 714 if (rx_usecs && !rx_riwt) 715 rx_riwt = 1; 716 717 /* Check the bounds of values for Rx */ 718 if (rx_riwt > XGMAC_MAX_DMA_RIWT) { 719 axgbe_printf(2, "rx-usec is limited to %d usecs\n", 720 hw_if->riwt_to_usec(pdata, XGMAC_MAX_DMA_RIWT)); 721 return (-EINVAL); 722 } 723 if (rx_frames > pdata->rx_desc_count) { 724 axgbe_printf(2, "rx-frames is limited to %d frames\n", 725 pdata->rx_desc_count); 726 return (-EINVAL); 727 } 728 729 tx_frames = sys_op->tx_max_coalesced_frames; 730 731 /* Check the bounds of values for Tx */ 732 if (tx_frames > pdata->tx_desc_count) { 733 axgbe_printf(2, "tx-frames is limited to %d frames\n", 734 pdata->tx_desc_count); 735 return (-EINVAL); 736 } 737 738 pdata->rx_riwt = rx_riwt; 739 pdata->rx_usecs = rx_usecs; 740 pdata->rx_frames = rx_frames; 741 hw_if->config_rx_coalesce(pdata); 742 743 pdata->tx_frames = tx_frames; 744 hw_if->config_tx_coalesce(pdata); 745 } 746 747 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 748 749 return (rc); 750 } 751 752 static int 753 sysctl_pauseparam_handler(SYSCTL_HANDLER_ARGS) 754 { 755 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 756 struct sysctl_op *sys_op = pdata->sys_op; 757 struct sysctl_info sysctl_pauseparam[] = { 758 { "autoneg", SYSL_BOOL, autoneg, "supported" }, 759 { "rx", SYSL_BOOL, rx_pause, "supported" }, 760 { "tx", SYSL_BOOL, tx_pause, "supported" }, 761 }; 762 ssize_t buf_size = 512; 763 char buf[buf_size]; 764 struct sbuf *sb; 765 int rc = 0; 766 767 if (req->newptr == NULL) { 768 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 769 if (sb == NULL) { 770 rc = ENOMEM; 771 return (rc); 772 } 773 sys_op->autoneg = pdata->phy.pause_autoneg; 774 sys_op->tx_pause = pdata->phy.tx_pause; 775 sys_op->rx_pause = pdata->phy.rx_pause; 776 777 sbuf_printf(sb, 778 "\nAutonegotiate: %s\n" 779 "RX: %s\n" 780 "TX: %s\n", 781 sys_op->autoneg ? "on" : "off", 782 sys_op->rx_pause ? "on" : "off", 783 sys_op->tx_pause ? "on" : "off"); 784 785 if (pdata->phy.lp_advertising) { 786 int an_rx = 0, an_tx = 0; 787 788 if (pdata->phy.advertising & pdata->phy.lp_advertising & 789 ADVERTISED_Pause) { 790 an_tx = 1; 791 an_rx = 1; 792 } else if (pdata->phy.advertising & 793 pdata->phy.lp_advertising & ADVERTISED_Asym_Pause) { 794 if (pdata->phy.advertising & ADVERTISED_Pause) 795 an_rx = 1; 796 else if (pdata->phy.lp_advertising & 797 ADVERTISED_Pause) 798 an_tx = 1; 799 } 800 sbuf_printf(sb, 801 "\n->\nRX negotiated: %s\n" 802 "TX negotiated: %s\n", 803 an_rx ? "on" : "off", 804 an_tx ? "on" : "off"); 805 } 806 rc = sbuf_finish(sb); 807 sbuf_delete(sb); 808 return (0); 809 } 810 811 rc = get_ubuf(req, buf); 812 if (rc == 0) { 813 parse_generic_sysctl(pdata, buf, sysctl_pauseparam, 814 ARRAY_SIZE(sysctl_pauseparam)); 815 816 if (sys_op->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE)) { 817 axgbe_error("autoneg disabled, pause autoneg not available\n"); 818 return (-EINVAL); 819 } 820 821 pdata->phy.pause_autoneg = sys_op->autoneg; 822 pdata->phy.tx_pause = sys_op->tx_pause; 823 pdata->phy.rx_pause = sys_op->rx_pause; 824 825 XGBE_CLR_ADV(&pdata->phy, Pause); 826 XGBE_CLR_ADV(&pdata->phy, Asym_Pause); 827 828 if (sys_op->rx_pause) { 829 XGBE_SET_ADV(&pdata->phy, Pause); 830 XGBE_SET_ADV(&pdata->phy, Asym_Pause); 831 } 832 833 if (sys_op->tx_pause) { 834 /* Equivalent to XOR of Asym_Pause */ 835 if (XGBE_ADV(&pdata->phy, Asym_Pause)) 836 XGBE_CLR_ADV(&pdata->phy, Asym_Pause); 837 else 838 XGBE_SET_ADV(&pdata->phy, Asym_Pause); 839 } 840 841 if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) 842 rc = pdata->phy_if.phy_config_aneg(pdata); 843 844 } 845 846 return (rc); 847 } 848 849 static int 850 sysctl_link_ksettings_handler(SYSCTL_HANDLER_ARGS) 851 { 852 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 853 struct sysctl_op *sys_op = pdata->sys_op; 854 struct sysctl_info sysctl_linksettings[] = { 855 { "autoneg", SYSL_BOOL, autoneg, "supported" }, 856 { "speed", SYSL_U32, speed, "supported" }, 857 { "duplex", SYSL_U8, duplex, "supported" }, 858 }; 859 ssize_t buf_size = 512; 860 char buf[buf_size], link_modes[16], speed_modes[16]; 861 struct sbuf *sb; 862 uint32_t speed; 863 int rc = 0; 864 865 if (req->newptr == NULL) { 866 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 867 if (sb == NULL) { 868 rc = ENOMEM; 869 return (rc); 870 } 871 sys_op->autoneg = pdata->phy.autoneg; 872 sys_op->speed = pdata->phy.speed; 873 sys_op->duplex = pdata->phy.duplex; 874 875 XGBE_LM_COPY(&pdata->phy, supported, &pdata->phy, supported); 876 XGBE_LM_COPY(&pdata->phy, advertising, &pdata->phy, advertising); 877 XGBE_LM_COPY(&pdata->phy, lp_advertising, &pdata->phy, lp_advertising); 878 879 switch (sys_op->speed) { 880 case 1: 881 strcpy(link_modes, "Unknown"); 882 strcpy(speed_modes, "Unknown"); 883 break; 884 case 2: 885 strcpy(link_modes, "10Gbps/Full"); 886 strcpy(speed_modes, "10000"); 887 break; 888 case 3: 889 strcpy(link_modes, "2.5Gbps/Full"); 890 strcpy(speed_modes, "2500"); 891 break; 892 case 4: 893 strcpy(link_modes, "1Gbps/Full"); 894 strcpy(speed_modes, "1000"); 895 break; 896 case 5: 897 strcpy(link_modes, "100Mbps/Full"); 898 strcpy(speed_modes, "100"); 899 break; 900 case 6: 901 strcpy(link_modes, "10Mbps/Full"); 902 strcpy(speed_modes, "10"); 903 break; 904 } 905 906 sbuf_printf(sb, 907 "\nlink_modes: %s\n" 908 "autonegotiation: %s\n" 909 "speed: %sMbps\n", 910 link_modes, 911 (sys_op->autoneg == AUTONEG_DISABLE) ? "off" : "on", 912 speed_modes); 913 914 switch (sys_op->duplex) { 915 case DUPLEX_HALF: 916 sbuf_printf(sb, "Duplex: Half\n"); 917 break; 918 case DUPLEX_FULL: 919 sbuf_printf(sb, "Duplex: Full\n"); 920 break; 921 default: 922 sbuf_printf(sb, "Duplex: Unknown\n"); 923 break; 924 } 925 rc = sbuf_finish(sb); 926 sbuf_delete(sb); 927 return (0); 928 } 929 930 rc = get_ubuf(req, buf); 931 if (rc == 0) { 932 parse_generic_sysctl(pdata, buf, sysctl_linksettings, 933 ARRAY_SIZE(sysctl_linksettings)); 934 935 speed = sys_op->speed; 936 937 if ((sys_op->autoneg != AUTONEG_ENABLE) && 938 (sys_op->autoneg != AUTONEG_DISABLE)) { 939 axgbe_error("unsupported autoneg %hhu\n", 940 (unsigned char)sys_op->autoneg); 941 return (-EINVAL); 942 } 943 944 if (sys_op->autoneg == AUTONEG_DISABLE) { 945 if (!pdata->phy_if.phy_valid_speed(pdata, speed)) { 946 axgbe_error("unsupported speed %u\n", speed); 947 return (-EINVAL); 948 } 949 950 if (sys_op->duplex != DUPLEX_FULL) { 951 axgbe_error("unsupported duplex %hhu\n", 952 (unsigned char)sys_op->duplex); 953 return (-EINVAL); 954 } 955 } 956 957 pdata->phy.autoneg = sys_op->autoneg; 958 pdata->phy.speed = speed; 959 pdata->phy.duplex = sys_op->duplex; 960 961 if (sys_op->autoneg == AUTONEG_ENABLE) 962 XGBE_SET_ADV(&pdata->phy, Autoneg); 963 else 964 XGBE_CLR_ADV(&pdata->phy, Autoneg); 965 966 if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) 967 rc = pdata->phy_if.phy_config_aneg(pdata); 968 } 969 970 return (rc); 971 } 972 973 static int 974 sysctl_ringparam_handler(SYSCTL_HANDLER_ARGS) 975 { 976 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 977 struct sysctl_op *sys_op = pdata->sys_op; 978 struct sysctl_info sysctl_ringparam[] = { 979 { "rx", SYSL_S32, rx_pending, "supported" }, 980 { "rx-mini", SYSL_S32, rx_mini_pending, "supported" }, 981 { "rx-jumbo", SYSL_S32, rx_jumbo_pending, "supported" }, 982 { "tx", SYSL_S32, tx_pending, "supported" }, 983 }; 984 ssize_t buf_size = 512; 985 unsigned int rx, tx; 986 char buf[buf_size]; 987 struct sbuf *sb; 988 int rc = 0; 989 990 if (req->newptr == NULL) { 991 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 992 if (sb == NULL) { 993 rc = ENOMEM; 994 return (rc); 995 } 996 sys_op->rx_max_pending = XGBE_RX_DESC_CNT_MAX; 997 sys_op->tx_max_pending = XGBE_TX_DESC_CNT_MAX; 998 sys_op->rx_pending = pdata->rx_desc_count; 999 sys_op->tx_pending = pdata->tx_desc_count; 1000 1001 sbuf_printf(sb, 1002 "\nPre-set maximums:\n" 1003 "RX: %u\n" 1004 "RX Mini: %u\n" 1005 "RX Jumbo: %u\n" 1006 "TX: %u\n", 1007 sys_op->rx_max_pending, 1008 sys_op->rx_mini_max_pending, 1009 sys_op->rx_jumbo_max_pending, 1010 sys_op->tx_max_pending); 1011 1012 sbuf_printf(sb, 1013 "\nCurrent hardware settings:\n" 1014 "RX: %u\n" 1015 "RX Mini: %u\n" 1016 "RX Jumbo: %u\n" 1017 "TX: %u\n", 1018 sys_op->rx_pending, 1019 sys_op->rx_mini_pending, 1020 sys_op->rx_jumbo_pending, 1021 sys_op->tx_pending); 1022 1023 rc = sbuf_finish(sb); 1024 sbuf_delete(sb); 1025 return (0); 1026 } 1027 1028 rc = get_ubuf(req, buf); 1029 if (rc == 0) { 1030 parse_generic_sysctl(pdata, buf, sysctl_ringparam, 1031 ARRAY_SIZE(sysctl_ringparam)); 1032 1033 if (sys_op->rx_mini_pending || sys_op->rx_jumbo_pending) { 1034 axgbe_error("unsupported ring parameter\n"); 1035 return (-EINVAL); 1036 } 1037 1038 if ((sys_op->rx_pending < XGBE_RX_DESC_CNT_MIN) || 1039 (sys_op->rx_pending > XGBE_RX_DESC_CNT_MAX)) { 1040 axgbe_error("rx ring param must be between %u and %u\n", 1041 XGBE_RX_DESC_CNT_MIN, XGBE_RX_DESC_CNT_MAX); 1042 return (-EINVAL); 1043 } 1044 1045 if ((sys_op->tx_pending < XGBE_TX_DESC_CNT_MIN) || 1046 (sys_op->tx_pending > XGBE_TX_DESC_CNT_MAX)) { 1047 axgbe_error("tx ring param must be between %u and %u\n", 1048 XGBE_TX_DESC_CNT_MIN, XGBE_TX_DESC_CNT_MAX); 1049 return (-EINVAL); 1050 } 1051 1052 rx = __rounddown_pow_of_two(sys_op->rx_pending); 1053 if (rx != sys_op->rx_pending) 1054 axgbe_printf(1, "rx ring param rounded to power of 2: %u\n", 1055 rx); 1056 1057 tx = __rounddown_pow_of_two(sys_op->tx_pending); 1058 if (tx != sys_op->tx_pending) 1059 axgbe_printf(1, "tx ring param rounded to power of 2: %u\n", 1060 tx); 1061 1062 if ((rx == pdata->rx_desc_count) && 1063 (tx == pdata->tx_desc_count)) 1064 goto out; 1065 1066 pdata->rx_desc_count = rx; 1067 pdata->tx_desc_count = tx; 1068 1069 /* TODO - restart dev */ 1070 } 1071 1072 out: 1073 return (0); 1074 } 1075 1076 static int 1077 sysctl_channels_handler(SYSCTL_HANDLER_ARGS) 1078 { 1079 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1080 struct sysctl_op *sys_op = pdata->sys_op; 1081 struct sysctl_info sysctl_channels[] = { 1082 { "rx", SYSL_S32, rx_count, "supported" }, 1083 { "tx", SYSL_S32, tx_count, "supported" }, 1084 { "other", SYSL_S32, other_count, "supported" }, 1085 { "combined", SYSL_S32, combined_count, "supported" }, 1086 }; 1087 unsigned int rx, tx, combined; 1088 ssize_t buf_size = 512; 1089 char buf[buf_size]; 1090 struct sbuf *sb; 1091 int rc = 0; 1092 1093 if (req->newptr == NULL) { 1094 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1095 if (sb == NULL) { 1096 rc = ENOMEM; 1097 return (rc); 1098 } 1099 rx = min(pdata->hw_feat.rx_ch_cnt, pdata->rx_max_channel_count); 1100 rx = min(rx, pdata->channel_irq_count); 1101 tx = min(pdata->hw_feat.tx_ch_cnt, pdata->tx_max_channel_count); 1102 tx = min(tx, pdata->channel_irq_count); 1103 tx = min(tx, pdata->tx_max_q_count); 1104 1105 combined = min(rx, tx); 1106 1107 sys_op->max_combined = combined; 1108 sys_op->max_rx = rx ? rx - 1 : 0; 1109 sys_op->max_tx = tx ? tx - 1 : 0; 1110 1111 /* Get current settings based on device state */ 1112 rx = pdata->rx_ring_count; 1113 tx = pdata->tx_ring_count; 1114 1115 combined = min(rx, tx); 1116 rx -= combined; 1117 tx -= combined; 1118 1119 sys_op->combined_count = combined; 1120 sys_op->rx_count = rx; 1121 sys_op->tx_count = tx; 1122 1123 sbuf_printf(sb, 1124 "\nPre-set maximums:\n" 1125 "RX: %u\n" 1126 "TX: %u\n" 1127 "Other: %u\n" 1128 "Combined: %u\n", 1129 sys_op->max_rx, sys_op->max_tx, 1130 sys_op->max_other, 1131 sys_op->max_combined); 1132 1133 sbuf_printf(sb, 1134 "\nCurrent hardware settings:\n" 1135 "RX: %u\n" 1136 "TX: %u\n" 1137 "Other: %u\n" 1138 "Combined: %u\n", 1139 sys_op->rx_count, sys_op->tx_count, 1140 sys_op->other_count, 1141 sys_op->combined_count); 1142 1143 rc = sbuf_finish(sb); 1144 sbuf_delete(sb); 1145 return (0); 1146 } 1147 1148 rc = get_ubuf(req, buf); 1149 if (rc == 0) { 1150 parse_generic_sysctl(pdata, buf, sysctl_channels, 1151 ARRAY_SIZE(sysctl_channels)); 1152 1153 axgbe_error( "channel inputs: combined=%u, rx-only=%u," 1154 " tx-only=%u\n", sys_op->combined_count, 1155 sys_op->rx_count, sys_op->tx_count); 1156 } 1157 1158 return (rc); 1159 } 1160 1161 1162 static int 1163 sysctl_mac_stats_handler(SYSCTL_HANDLER_ARGS) 1164 { 1165 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1166 ssize_t buf_size = 64; 1167 struct sbuf *sb; 1168 int rc = 0; 1169 int i; 1170 1171 if (req->newptr == NULL) { 1172 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1173 if (sb == NULL) { 1174 rc = ENOMEM; 1175 return (rc); 1176 } 1177 1178 pdata->hw_if.read_mmc_stats(pdata); 1179 for (i = 0; i < XGBE_STATS_COUNT; i++) { 1180 sbuf_printf(sb, "\n %s: %lu", 1181 xgbe_gstring_stats[i].stat_string, 1182 *(uint64_t *)((uint8_t *)pdata + xgbe_gstring_stats[i].stat_offset)); 1183 } 1184 for (i = 0; i < pdata->tx_ring_count; i++) { 1185 sbuf_printf(sb, 1186 "\n txq_packets[%d]: %lu" 1187 "\n txq_bytes[%d]: %lu", 1188 i, pdata->ext_stats.txq_packets[i], 1189 i, pdata->ext_stats.txq_bytes[i]); 1190 } 1191 for (i = 0; i < pdata->rx_ring_count; i++) { 1192 sbuf_printf(sb, 1193 "\n rxq_packets[%d]: %lu" 1194 "\n rxq_bytes[%d]: %lu", 1195 i, pdata->ext_stats.rxq_packets[i], 1196 i, pdata->ext_stats.rxq_bytes[i]); 1197 } 1198 1199 rc = sbuf_finish(sb); 1200 sbuf_delete(sb); 1201 return (rc); 1202 } 1203 1204 return (-EINVAL); 1205 } 1206 1207 static int 1208 sysctl_xgmac_reg_value_handler(SYSCTL_HANDLER_ARGS) 1209 { 1210 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1211 ssize_t buf_size = 64; 1212 char buf[buf_size]; 1213 unsigned int value; 1214 struct sbuf *sb; 1215 int rc = 0; 1216 1217 if (req->newptr == NULL) { 1218 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1219 if (sb == NULL) { 1220 rc = ENOMEM; 1221 return (rc); 1222 } 1223 1224 value = XGMAC_IOREAD(pdata, pdata->sysctl_xgmac_reg); 1225 axgbe_printf(2, "READ: %s: value: 0x%x\n", __func__, value); 1226 sbuf_printf(sb, "\nXGMAC reg_value: 0x%x\n", value); 1227 rc = sbuf_finish(sb); 1228 sbuf_delete(sb); 1229 return (rc); 1230 } 1231 1232 rc = get_ubuf(req, buf); 1233 if (rc == 0) { 1234 sscanf(buf, "%x", &value); 1235 axgbe_printf(2, "WRITE: %s: value: 0x%x\n", __func__, value); 1236 XGMAC_IOWRITE(pdata, pdata->sysctl_xgmac_reg, value); 1237 } 1238 1239 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1240 return (rc); 1241 } 1242 1243 static int 1244 sysctl_xpcs_mmd_reg_handler(SYSCTL_HANDLER_ARGS) 1245 { 1246 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1247 ssize_t buf_size = 64; 1248 char buf[buf_size]; 1249 struct sbuf *sb; 1250 unsigned int reg; 1251 int rc = 0; 1252 1253 if (req->newptr == NULL) { 1254 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1255 if (sb == NULL) { 1256 rc = ENOMEM; 1257 return (rc); 1258 } 1259 1260 axgbe_printf(2, "READ: %s: xpcs_mmd: 0x%x\n", __func__, 1261 pdata->sysctl_xpcs_mmd); 1262 sbuf_printf(sb, "\nXPCS mmd_reg: 0x%x\n", 1263 pdata->sysctl_xpcs_mmd); 1264 rc = sbuf_finish(sb); 1265 sbuf_delete(sb); 1266 return (rc); 1267 } 1268 1269 rc = get_ubuf(req, buf); 1270 if (rc == 0) { 1271 sscanf(buf, "%x", ®); 1272 axgbe_printf(2, "WRITE: %s: mmd_reg: 0x%x\n", __func__, reg); 1273 pdata->sysctl_xpcs_mmd = reg; 1274 } 1275 1276 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1277 return (rc); 1278 } 1279 1280 static int 1281 sysctl_xpcs_reg_addr_handler(SYSCTL_HANDLER_ARGS) 1282 { 1283 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1284 ssize_t buf_size = 64; 1285 char buf[buf_size]; 1286 struct sbuf *sb; 1287 unsigned int reg; 1288 int rc = 0; 1289 1290 if (req->newptr == NULL) { 1291 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1292 if (sb == NULL) { 1293 rc = ENOMEM; 1294 return (rc); 1295 } 1296 1297 axgbe_printf(2, "READ: %s: sysctl_xpcs_reg: 0x%x\n", __func__, 1298 pdata->sysctl_xpcs_reg); 1299 sbuf_printf(sb, "\nXPCS reg_addr: 0x%x\n", 1300 pdata->sysctl_xpcs_reg); 1301 rc = sbuf_finish(sb); 1302 sbuf_delete(sb); 1303 return (rc); 1304 } 1305 1306 rc = get_ubuf(req, buf); 1307 if (rc == 0) { 1308 sscanf(buf, "%x", ®); 1309 axgbe_printf(2, "WRITE: %s: reg: 0x%x\n", __func__, reg); 1310 pdata->sysctl_xpcs_reg = reg; 1311 } 1312 1313 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1314 return (rc); 1315 } 1316 1317 static int 1318 sysctl_xpcs_reg_value_handler(SYSCTL_HANDLER_ARGS) 1319 { 1320 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1321 ssize_t buf_size = 64; 1322 char buf[buf_size]; 1323 unsigned int value; 1324 struct sbuf *sb; 1325 int rc = 0; 1326 1327 if (req->newptr == NULL) { 1328 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1329 if (sb == NULL) { 1330 rc = ENOMEM; 1331 return (rc); 1332 } 1333 1334 value = XMDIO_READ(pdata, pdata->sysctl_xpcs_mmd, 1335 pdata->sysctl_xpcs_reg); 1336 axgbe_printf(2, "READ: %s: value: 0x%x\n", __func__, value); 1337 sbuf_printf(sb, "\nXPCS reg_value: 0x%x\n", value); 1338 rc = sbuf_finish(sb); 1339 sbuf_delete(sb); 1340 return (rc); 1341 } 1342 1343 rc = get_ubuf(req, buf); 1344 if (rc == 0) { 1345 sscanf(buf, "%x", &value); 1346 axgbe_printf(2, "WRITE: %s: value: 0x%x\n", __func__, value); 1347 XMDIO_WRITE(pdata, pdata->sysctl_xpcs_mmd, 1348 pdata->sysctl_xpcs_reg, value); 1349 } 1350 1351 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1352 return (rc); 1353 } 1354 1355 static int 1356 sysctl_xprop_reg_addr_handler(SYSCTL_HANDLER_ARGS) 1357 { 1358 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1359 ssize_t buf_size = 64; 1360 char buf[buf_size]; 1361 struct sbuf *sb; 1362 unsigned int reg; 1363 int rc = 0; 1364 1365 if (req->newptr == NULL) { 1366 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1367 if (sb == NULL) { 1368 rc = ENOMEM; 1369 return (rc); 1370 } 1371 1372 axgbe_printf(2, "READ: %s: sysctl_xprop_reg: 0x%x\n", __func__, 1373 pdata->sysctl_xprop_reg); 1374 sbuf_printf(sb, "\nXPROP reg_addr: 0x%x\n", 1375 pdata->sysctl_xprop_reg); 1376 rc = sbuf_finish(sb); 1377 sbuf_delete(sb); 1378 return (rc); 1379 } 1380 1381 rc = get_ubuf(req, buf); 1382 if (rc == 0) { 1383 sscanf(buf, "%x", ®); 1384 axgbe_printf(2, "WRITE: %s: reg: 0x%x\n", __func__, reg); 1385 pdata->sysctl_xprop_reg = reg; 1386 } 1387 1388 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1389 return (rc); 1390 } 1391 1392 static int 1393 sysctl_xprop_reg_value_handler(SYSCTL_HANDLER_ARGS) 1394 { 1395 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1396 ssize_t buf_size = 64; 1397 char buf[buf_size]; 1398 unsigned int value; 1399 struct sbuf *sb; 1400 int rc = 0; 1401 1402 if (req->newptr == NULL) { 1403 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1404 if (sb == NULL) { 1405 rc = ENOMEM; 1406 return (rc); 1407 } 1408 1409 value = XP_IOREAD(pdata, pdata->sysctl_xprop_reg); 1410 axgbe_printf(2, "READ: %s: value: 0x%x\n", __func__, value); 1411 sbuf_printf(sb, "\nXPROP reg_value: 0x%x\n", value); 1412 rc = sbuf_finish(sb); 1413 sbuf_delete(sb); 1414 return (rc); 1415 } 1416 1417 rc = get_ubuf(req, buf); 1418 if (rc == 0) { 1419 sscanf(buf, "%x", &value); 1420 axgbe_printf(2, "WRITE: %s: value: 0x%x\n", __func__, value); 1421 XP_IOWRITE(pdata, pdata->sysctl_xprop_reg, value); 1422 } 1423 1424 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1425 return (rc); 1426 } 1427 1428 static int 1429 sysctl_xi2c_reg_addr_handler(SYSCTL_HANDLER_ARGS) 1430 { 1431 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1432 ssize_t buf_size = 64; 1433 char buf[buf_size]; 1434 struct sbuf *sb; 1435 unsigned int reg; 1436 int rc = 0; 1437 1438 if (req->newptr == NULL) { 1439 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1440 if (sb == NULL) { 1441 rc = ENOMEM; 1442 return (rc); 1443 } 1444 1445 axgbe_printf(2, "READ: %s: sysctl_xi2c_reg: 0x%x\n", __func__, 1446 pdata->sysctl_xi2c_reg); 1447 sbuf_printf(sb, "\nXI2C reg_addr: 0x%x\n", 1448 pdata->sysctl_xi2c_reg); 1449 rc = sbuf_finish(sb); 1450 sbuf_delete(sb); 1451 return (rc); 1452 } 1453 1454 rc = get_ubuf(req, buf); 1455 if (rc == 0) { 1456 sscanf(buf, "%x", ®); 1457 axgbe_printf(2, "WRITE: %s: reg: 0x%x\n", __func__, reg); 1458 pdata->sysctl_xi2c_reg = reg; 1459 } 1460 1461 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1462 return (rc); 1463 } 1464 1465 static int 1466 sysctl_xi2c_reg_value_handler(SYSCTL_HANDLER_ARGS) 1467 { 1468 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1469 ssize_t buf_size = 64; 1470 char buf[buf_size]; 1471 unsigned int value; 1472 struct sbuf *sb; 1473 int rc = 0; 1474 1475 if (req->newptr == NULL) { 1476 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1477 if (sb == NULL) { 1478 rc = ENOMEM; 1479 return (rc); 1480 } 1481 1482 value = XI2C_IOREAD(pdata, pdata->sysctl_xi2c_reg); 1483 axgbe_printf(2, "READ: %s: value: 0x%x\n", __func__, value); 1484 sbuf_printf(sb, "\nXI2C reg_value: 0x%x\n", value); 1485 rc = sbuf_finish(sb); 1486 sbuf_delete(sb); 1487 return (rc); 1488 } 1489 1490 rc = get_ubuf(req, buf); 1491 if (rc == 0) { 1492 sscanf(buf, "%x", &value); 1493 axgbe_printf(2, "WRITE: %s: value: 0x%x\n", __func__, value); 1494 XI2C_IOWRITE(pdata, pdata->sysctl_xi2c_reg, value); 1495 } 1496 1497 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1498 return (rc); 1499 } 1500 1501 static int 1502 sysctl_an_cdr_wr_handler(SYSCTL_HANDLER_ARGS) 1503 { 1504 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1505 unsigned int an_cdr_wr = 0; 1506 ssize_t buf_size = 64; 1507 char buf[buf_size]; 1508 struct sbuf *sb; 1509 int rc = 0; 1510 1511 if (req->newptr == NULL) { 1512 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1513 if (sb == NULL) { 1514 rc = ENOMEM; 1515 return (rc); 1516 } 1517 1518 axgbe_printf(2, "READ: %s: an_cdr_wr: %d\n", __func__, 1519 pdata->sysctl_an_cdr_workaround); 1520 sbuf_printf(sb, "%d\n", pdata->sysctl_an_cdr_workaround); 1521 rc = sbuf_finish(sb); 1522 sbuf_delete(sb); 1523 return (rc); 1524 } 1525 1526 rc = get_ubuf(req, buf); 1527 if (rc == 0) { 1528 sscanf(buf, "%u", &an_cdr_wr); 1529 axgbe_printf(2, "WRITE: %s: an_cdr_wr: 0x%d\n", __func__, 1530 an_cdr_wr); 1531 1532 if (an_cdr_wr) 1533 pdata->sysctl_an_cdr_workaround = 1; 1534 else 1535 pdata->sysctl_an_cdr_workaround = 0; 1536 } 1537 1538 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1539 return (rc); 1540 } 1541 1542 static int 1543 sysctl_an_cdr_track_early_handler(SYSCTL_HANDLER_ARGS) 1544 { 1545 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; 1546 unsigned int an_cdr_track_early = 0; 1547 ssize_t buf_size = 64; 1548 char buf[buf_size]; 1549 struct sbuf *sb; 1550 int rc = 0; 1551 1552 if (req->newptr == NULL) { 1553 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); 1554 if (sb == NULL) { 1555 rc = ENOMEM; 1556 return (rc); 1557 } 1558 1559 axgbe_printf(2, "READ: %s: an_cdr_track_early %d\n", __func__, 1560 pdata->sysctl_an_cdr_track_early); 1561 sbuf_printf(sb, "%d\n", pdata->sysctl_an_cdr_track_early); 1562 rc = sbuf_finish(sb); 1563 sbuf_delete(sb); 1564 return (rc); 1565 } 1566 1567 rc = get_ubuf(req, buf); 1568 if (rc == 0) { 1569 sscanf(buf, "%u", &an_cdr_track_early); 1570 axgbe_printf(2, "WRITE: %s: an_cdr_track_early: %d\n", __func__, 1571 an_cdr_track_early); 1572 1573 if (an_cdr_track_early) 1574 pdata->sysctl_an_cdr_track_early = 1; 1575 else 1576 pdata->sysctl_an_cdr_track_early = 0; 1577 } 1578 1579 axgbe_printf(2, "%s: rc= %d\n", __func__, rc); 1580 return (rc); 1581 } 1582 1583 void 1584 axgbe_sysctl_exit(struct xgbe_prv_data *pdata) 1585 { 1586 1587 if (pdata->sys_op) 1588 free(pdata->sys_op, M_AXGBE); 1589 } 1590 1591 void 1592 axgbe_sysctl_init(struct xgbe_prv_data *pdata) 1593 { 1594 struct sysctl_ctx_list *clist; 1595 struct sysctl_oid_list *top; 1596 struct sysctl_oid *parent; 1597 struct sysctl_op *sys_op; 1598 1599 sys_op = malloc(sizeof(*sys_op), M_AXGBE, M_WAITOK | M_ZERO); 1600 pdata->sys_op = sys_op; 1601 1602 clist = device_get_sysctl_ctx(pdata->dev); 1603 parent = device_get_sysctl_tree(pdata->dev); 1604 top = SYSCTL_CHILDREN(parent); 1605 1606 /* Set defaults */ 1607 pdata->sysctl_xgmac_reg = 0; 1608 pdata->sysctl_xpcs_mmd = 1; 1609 pdata->sysctl_xpcs_reg = 0; 1610 1611 SYSCTL_ADD_UINT(clist, top, OID_AUTO, "axgbe_debug_level", CTLFLAG_RWTUN, 1612 &pdata->debug_level, 0, "axgbe log level -- higher is verbose"); 1613 1614 SYSCTL_ADD_UINT(clist, top, OID_AUTO, "sph_enable", 1615 CTLFLAG_RDTUN, &pdata->sph_enable, 1, 1616 "shows the split header feature state (1 - enable, 0 - disable"); 1617 1618 SYSCTL_ADD_UINT(clist, top, OID_AUTO, "link_workaround", 1619 CTLFLAG_RWTUN, &pdata->link_workaround, 0, 1620 "enable the workaround for link issue in coming up"); 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