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