1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include "nge.h" 30 31 #undef NGE_DBG 32 #define NGE_DBG NGE_DBG_STATS /* debug flag for this code */ 33 34 /* 35 * Table of Hardware-defined Statistics Block Offsets and Names 36 */ 37 #define KS_NAME(s) { KS_ ## s, #s } 38 39 const nge_ksindex_t nge_statistics[] = { 40 41 KS_NAME(ifHOutOctets), 42 KS_NAME(ifHOutZeroRetranCount), 43 KS_NAME(ifHOutOneRetranCount), 44 KS_NAME(ifHOutMoreRetranCount), 45 KS_NAME(ifHOutColCount), 46 KS_NAME(ifHOutFifoovCount), 47 KS_NAME(ifHOutLOCCount), 48 KS_NAME(ifHOutExDecCount), 49 KS_NAME(ifHOutRetryCount), 50 KS_NAME(ifHInFrameErrCount), 51 KS_NAME(ifHInExtraOctErrCount), 52 KS_NAME(ifHInLColErrCount), 53 KS_NAME(ifHInOversizeErrCount), 54 KS_NAME(ifHInFovErrCount), 55 KS_NAME(ifHInFCSErrCount), 56 KS_NAME(ifHInAlignErrCount), 57 KS_NAME(ifHInLenErrCount), 58 KS_NAME(ifHInUniPktsCount), 59 KS_NAME(ifHInBroadPksCount), 60 KS_NAME(ifHInMulPksCount), 61 { KS_STATS_SIZE, NULL } 62 }; 63 64 /* 65 * Local datatype for defining tables of (Offset, Name) pairs 66 */ 67 static int 68 nge_statistics_update(kstat_t *ksp, int flag) 69 { 70 uint32_t regno; 71 nge_t *ngep; 72 nge_statistics_t *istp; 73 nge_hw_statistics_t *hw_stp; 74 kstat_named_t *knp; 75 const nge_ksindex_t *ksip; 76 77 if (flag != KSTAT_READ) 78 return (EACCES); 79 80 ngep = ksp->ks_private; 81 istp = &ngep->statistics; 82 hw_stp = &istp->hw_statistics; 83 knp = ksp->ks_data; 84 85 /* 86 * Transfer the statistics values from the hardware statistics regs 87 */ 88 for (ksip = nge_statistics; ksip->name != NULL; ++knp, ++ksip) { 89 regno = KS_BASE + ksip->index * sizeof (uint32_t); 90 hw_stp->a[ksip->index] += nge_reg_get32(ngep, regno); 91 knp->value.ui64 = hw_stp->a[ksip->index]; 92 } 93 94 return (0); 95 } 96 97 98 static const nge_ksindex_t nge_chipinfo[] = { 99 { 0, "businfo" }, 100 { 1, "command" }, 101 { 2, "vendor_id" }, 102 { 3, "device_id" }, 103 { 4, "subsystem_vendor_id" }, 104 { 5, "subsystem_device_id" }, 105 { 6, "revision_id" }, 106 { 7, "cache_line_size" }, 107 { 8, "latency_timer" }, 108 { 9, "phy_mode" }, 109 { 10, "phy_id" }, 110 { 11, "hw_mac_addr" }, 111 { 12, "&bus_type" }, 112 { 13, "&bus_speed" }, 113 { 14, "&bus_size" }, 114 { -1, NULL } 115 }; 116 117 static const nge_ksindex_t nge_debuginfo[] = { 118 { 0, "rx_realloc" }, 119 { 1, "rx_realloc_fails" }, 120 { 2, "rx_realloc_DMA_fails" }, 121 { 3, "rx_realloc_MP_fails" }, 122 { 4, "rx_rcfree" }, 123 { 5, "context_switch" }, 124 { 6, "ip_hsum_err" }, 125 { 7, "tcp_hsum_err" }, 126 { 8, "tc_next" }, 127 { 9, "tx_next" }, 128 { 10, "tx_free" }, 129 { 11, "tx_flow" }, 130 { 12, "rx_prod" }, 131 { 13, "rx_hold" }, 132 { 14, "rx_nobuf" }, 133 { 15, "rx_err" }, 134 {16, "tx_err" }, 135 {17, "tx_stall" }, 136 { -1, NULL } 137 }; 138 139 static int 140 nge_chipinfo_update(kstat_t *ksp, int flag) 141 { 142 nge_t *ngep; 143 kstat_named_t *knp; 144 chip_info_t *infop; 145 146 if (flag != KSTAT_READ) 147 return (EACCES); 148 149 ngep = ksp->ks_private; 150 infop = &ngep->chipinfo; 151 knp = ksp->ks_data; 152 153 (knp++)->value.ui64 = infop->businfo; 154 (knp++)->value.ui64 = infop->command; 155 (knp++)->value.ui64 = infop->vendor; 156 (knp++)->value.ui64 = infop->device; 157 (knp++)->value.ui64 = infop->subven; 158 (knp++)->value.ui64 = infop->subdev; 159 (knp++)->value.ui64 = infop->revision; 160 (knp++)->value.ui64 = infop->clsize; 161 (knp++)->value.ui64 = infop->latency; 162 (knp++)->value.ui64 = ngep->phy_mode; 163 (knp++)->value.ui64 = ngep->phy_id; 164 (knp++)->value.ui64 = infop->hw_mac_addr; 165 return (0); 166 } 167 168 static int 169 nge_debuginfo_update(kstat_t *ksp, int flag) 170 { 171 nge_t *ngep; 172 kstat_named_t *knp; 173 nge_sw_statistics_t *sw_stp; 174 175 if (flag != KSTAT_READ) 176 return (EACCES); 177 178 ngep = ksp->ks_private; 179 sw_stp = &ngep->statistics.sw_statistics; 180 knp = ksp->ks_data; 181 182 (knp++)->value.ui64 = sw_stp->recv_realloc; 183 (knp++)->value.ui64 = sw_stp->kmem_alloc_err; 184 (knp++)->value.ui64 = sw_stp->dma_alloc_err; 185 (knp++)->value.ui64 = sw_stp->mp_alloc_err; 186 (knp++)->value.ui64 = sw_stp->recy_free; 187 (knp++)->value.ui64 = sw_stp->load_context; 188 (knp++)->value.ui64 = sw_stp->ip_hwsum_err; 189 (knp++)->value.ui64 = sw_stp->tcp_hwsum_err; 190 (knp++)->value.ui64 = ngep->send->tc_next; 191 (knp++)->value.ui64 = ngep->send->tx_next; 192 (knp++)->value.ui64 = ngep->send->tx_free; 193 (knp++)->value.ui64 = ngep->send->tx_flow; 194 (knp++)->value.ui64 = ngep->recv->prod_index; 195 (knp++)->value.ui64 = ngep->buff->rx_hold; 196 (knp++)->value.ui64 = sw_stp->rx_nobuffer; 197 (knp++)->value.ui64 = sw_stp->rx_err; 198 (knp++)->value.ui64 = sw_stp->tx_stop_err; 199 (knp++)->value.ui64 = sw_stp->tx_stall; 200 return (0); 201 } 202 203 static kstat_t * 204 nge_setup_named_kstat(nge_t *ngep, int instance, char *name, 205 const nge_ksindex_t *ksip, size_t size, int (*update)(kstat_t *, int)) 206 { 207 kstat_t *ksp; 208 kstat_named_t *knp; 209 char *np; 210 int type; 211 212 size /= sizeof (nge_ksindex_t); 213 ksp = kstat_create(NGE_DRIVER_NAME, instance, name, "net", 214 KSTAT_TYPE_NAMED, size-1, KSTAT_FLAG_PERSISTENT); 215 if (ksp == NULL) 216 return (NULL); 217 218 ksp->ks_private = ngep; 219 ksp->ks_update = update; 220 for (knp = ksp->ks_data; (np = ksip->name) != NULL; ++knp, ++ksip) { 221 switch (*np) { 222 default: 223 type = KSTAT_DATA_UINT64; 224 break; 225 case '%': 226 np += 1; 227 type = KSTAT_DATA_UINT32; 228 break; 229 230 case '$': 231 np ++; 232 type = KSTAT_DATA_STRING; 233 break; 234 case '&': 235 np ++; 236 type = KSTAT_DATA_CHAR; 237 break; 238 } 239 kstat_named_init(knp, np, type); 240 } 241 kstat_install(ksp); 242 243 return (ksp); 244 } 245 246 /* 247 * Create kstats corresponding to NDD parameters 248 */ 249 static kstat_t * 250 nge_setup_params_kstat(nge_t *ngep, int instance, char *name, 251 int (*update)(kstat_t *, int)) 252 { 253 kstat_t *ksp; 254 kstat_named_t *knp; 255 int i; 256 257 ksp = kstat_create(NGE_DRIVER_NAME, instance, name, "net", 258 KSTAT_TYPE_NAMED, PARAM_COUNT, KSTAT_FLAG_PERSISTENT); 259 if (ksp != NULL) { 260 ksp->ks_private = ngep; 261 ksp->ks_update = update; 262 for (knp = ksp->ks_data, i = 0; i < PARAM_COUNT; ++knp, ++i) 263 kstat_named_init(knp, ngep->nd_params[i].ndp_name+1, 264 KSTAT_DATA_UINT64); 265 kstat_install(ksp); 266 } 267 268 return (ksp); 269 } 270 271 void 272 nge_init_kstats(nge_t *ngep, int instance) 273 { 274 NGE_TRACE(("nge_init_kstats($%p, %d)", (void *)ngep, instance)); 275 276 ngep->nge_kstats[NGE_KSTAT_STATS] = nge_setup_named_kstat(ngep, 277 instance, "statistics", nge_statistics, 278 sizeof (nge_statistics), nge_statistics_update); 279 280 ngep->nge_kstats[NGE_KSTAT_CHIPID] = nge_setup_named_kstat(ngep, 281 instance, "chipinfo", nge_chipinfo, 282 sizeof (nge_chipinfo), nge_chipinfo_update); 283 284 ngep->nge_kstats[NGE_KSTAT_DEBUG] = nge_setup_named_kstat(ngep, 285 instance, "driver-debug", nge_debuginfo, 286 sizeof (nge_debuginfo), nge_debuginfo_update); 287 288 } 289 290 void 291 nge_fini_kstats(nge_t *ngep) 292 { 293 int i; 294 295 NGE_TRACE(("nge_fini_kstats($%p)", (void *)ngep)); 296 for (i = NGE_KSTAT_COUNT; --i >= 0; ) 297 if (ngep->nge_kstats[i] != NULL) 298 kstat_delete(ngep->nge_kstats[i]); 299 } 300 301 int 302 nge_m_stat(void *arg, uint_t stat, uint64_t *val) 303 { 304 nge_t *ngep = arg; 305 uint32_t regno; 306 nge_statistics_t *nstp = &ngep->statistics; 307 nge_hw_statistics_t *hw_stp = &nstp->hw_statistics; 308 nge_sw_statistics_t *sw_stp = &nstp->sw_statistics; 309 310 switch (stat) { 311 case MAC_STAT_IFSPEED: 312 *val = ngep->param_link_speed * 1000000ull; 313 break; 314 315 case MAC_STAT_MULTIRCV: 316 regno = KS_BASE + KS_ifHInMulPksCount * sizeof (uint32_t); 317 hw_stp->s.InMulPksCount += nge_reg_get32(ngep, regno); 318 *val = hw_stp->s.InMulPksCount; 319 break; 320 321 case MAC_STAT_BRDCSTRCV: 322 regno = KS_BASE + KS_ifHInBroadPksCount * sizeof (uint32_t); 323 hw_stp->s.InBroadPksCount += nge_reg_get32(ngep, regno); 324 *val = hw_stp->s.InBroadPksCount; 325 break; 326 327 case MAC_STAT_NORCVBUF: 328 *val = sw_stp->rx_nobuffer; 329 break; 330 331 case MAC_STAT_IERRORS: 332 regno = KS_BASE + KS_ifHInFrameErrCount * sizeof (uint32_t); 333 hw_stp->s.InFrameErrCount += nge_reg_get32(ngep, regno); 334 regno = KS_BASE + KS_ifHInExtraOctErrCount * sizeof (uint32_t); 335 hw_stp->s.InExtraOctErrCount += nge_reg_get32(ngep, regno); 336 regno = KS_BASE + KS_ifHInLColErrCount * sizeof (uint32_t); 337 hw_stp->s.InLColErrCount += nge_reg_get32(ngep, regno); 338 regno = KS_BASE + KS_ifHInOversizeErrCount * sizeof (uint32_t); 339 hw_stp->s.InOversizeErrCount += nge_reg_get32(ngep, regno); 340 regno = KS_BASE + KS_ifHInFovErrCount * sizeof (uint32_t); 341 hw_stp->s.InFovErrCount += nge_reg_get32(ngep, regno); 342 regno = KS_BASE + KS_ifHInFCSErrCount * sizeof (uint32_t); 343 hw_stp->s.InFCSErrCount += nge_reg_get32(ngep, regno); 344 regno = KS_BASE + KS_ifHInAlignErrCount * sizeof (uint32_t); 345 hw_stp->s.InAlignErrCount += nge_reg_get32(ngep, regno); 346 regno = KS_BASE + KS_ifHInLenErrCount * sizeof (uint32_t); 347 hw_stp->s.InLenErrCount += nge_reg_get32(ngep, regno); 348 *val = hw_stp->s.InFrameErrCount + 349 hw_stp->s.InExtraOctErrCount + 350 hw_stp->s.InLColErrCount + 351 hw_stp->s.InOversizeErrCount + 352 hw_stp->s.InFovErrCount + 353 hw_stp->s.InFCSErrCount + 354 hw_stp->s.InAlignErrCount + 355 hw_stp->s.InLenErrCount; 356 break; 357 358 case MAC_STAT_OERRORS: 359 regno = KS_BASE + KS_ifHOutFifoovCount * sizeof (uint32_t); 360 hw_stp->s.OutFifoovCount += nge_reg_get32(ngep, regno); 361 regno = KS_BASE + KS_ifHOutLOCCount * sizeof (uint32_t); 362 hw_stp->s.OutLOCCount += nge_reg_get32(ngep, regno); 363 regno = KS_BASE + KS_ifHOutExDecCount * sizeof (uint32_t); 364 hw_stp->s.OutExDecCount += nge_reg_get32(ngep, regno); 365 regno = KS_BASE + KS_ifHOutRetryCount * sizeof (uint32_t); 366 hw_stp->s.OutRetryCount += nge_reg_get32(ngep, regno); 367 *val = hw_stp->s.OutFifoovCount + 368 hw_stp->s.OutLOCCount + 369 hw_stp->s.OutExDecCount + 370 hw_stp->s.OutRetryCount; 371 break; 372 373 case MAC_STAT_COLLISIONS: 374 regno = KS_BASE + KS_ifHOutColCount * sizeof (uint32_t); 375 hw_stp->s.OutColCount += nge_reg_get32(ngep, regno); 376 *val = hw_stp->s.OutColCount; 377 break; 378 379 case MAC_STAT_RBYTES: 380 *val = sw_stp->rbytes; 381 break; 382 383 case MAC_STAT_IPACKETS: 384 *val = sw_stp->recv_count; 385 break; 386 387 case MAC_STAT_OBYTES: 388 *val = sw_stp->obytes; 389 break; 390 391 case MAC_STAT_OPACKETS: 392 *val = sw_stp->xmit_count; 393 break; 394 395 case ETHER_STAT_ALIGN_ERRORS: 396 regno = KS_BASE + KS_ifHInAlignErrCount * sizeof (uint32_t); 397 hw_stp->s.InAlignErrCount += nge_reg_get32(ngep, regno); 398 *val = hw_stp->s.InAlignErrCount; 399 break; 400 401 case ETHER_STAT_FCS_ERRORS: 402 regno = KS_BASE + KS_ifHInFCSErrCount * sizeof (uint32_t); 403 hw_stp->s.InFCSErrCount += nge_reg_get32(ngep, regno); 404 *val = hw_stp->s.InFCSErrCount; 405 break; 406 407 case ETHER_STAT_FIRST_COLLISIONS: 408 regno = KS_BASE + KS_ifHOutZeroRetranCount * sizeof (uint32_t); 409 hw_stp->s.OutZeroRetranCount += nge_reg_get32(ngep, regno); 410 *val = hw_stp->s.OutZeroRetranCount; 411 break; 412 413 case ETHER_STAT_MULTI_COLLISIONS: 414 regno = KS_BASE + KS_ifHOutOneRetranCount * sizeof (uint32_t); 415 hw_stp->s.OutOneRetranCount += nge_reg_get32(ngep, regno); 416 regno = KS_BASE + KS_ifHOutMoreRetranCount * sizeof (uint32_t); 417 hw_stp->s.OutMoreRetranCount += nge_reg_get32(ngep, regno); 418 *val = hw_stp->s.OutOneRetranCount + 419 hw_stp->s.OutMoreRetranCount; 420 break; 421 422 case ETHER_STAT_DEFER_XMTS: 423 regno = KS_BASE + KS_ifHOutExDecCount * sizeof (uint32_t); 424 hw_stp->s.OutExDecCount += nge_reg_get32(ngep, regno); 425 *val = hw_stp->s.OutExDecCount; 426 break; 427 428 case ETHER_STAT_TX_LATE_COLLISIONS: 429 regno = KS_BASE + KS_ifHOutColCount * sizeof (uint32_t); 430 hw_stp->s.OutColCount += nge_reg_get32(ngep, regno); 431 *val = hw_stp->s.OutColCount; 432 break; 433 434 case ETHER_STAT_EX_COLLISIONS: 435 regno = KS_BASE + KS_ifHOutOneRetranCount * sizeof (uint32_t); 436 hw_stp->s.OutOneRetranCount += nge_reg_get32(ngep, regno); 437 *val = hw_stp->s.OutOneRetranCount; 438 break; 439 440 case ETHER_STAT_CARRIER_ERRORS: 441 regno = KS_BASE + KS_ifHOutLOCCount * sizeof (uint32_t); 442 hw_stp->s.OutLOCCount += nge_reg_get32(ngep, regno); 443 *val = hw_stp->s.OutLOCCount; 444 break; 445 446 case ETHER_STAT_TOOLONG_ERRORS: 447 regno = KS_BASE + KS_ifHInOversizeErrCount * sizeof (uint32_t); 448 hw_stp->s.InOversizeErrCount += nge_reg_get32(ngep, regno); 449 *val = hw_stp->s.InOversizeErrCount; 450 break; 451 452 case ETHER_STAT_XCVR_ADDR: 453 *val = ngep->phy_xmii_addr; 454 break; 455 456 case ETHER_STAT_XCVR_ID: 457 *val = ngep->phy_id; 458 break; 459 460 case ETHER_STAT_XCVR_INUSE: 461 *val = XCVR_1000T; 462 break; 463 464 case ETHER_STAT_CAP_1000FDX: 465 *val = 1; 466 break; 467 468 case ETHER_STAT_CAP_1000HDX: 469 *val = 0; 470 break; 471 472 case ETHER_STAT_CAP_100FDX: 473 *val = 1; 474 break; 475 476 case ETHER_STAT_CAP_100HDX: 477 *val = 1; 478 break; 479 480 case ETHER_STAT_CAP_10FDX: 481 *val = 1; 482 break; 483 484 case ETHER_STAT_CAP_10HDX: 485 *val = 1; 486 break; 487 488 case ETHER_STAT_CAP_ASMPAUSE: 489 *val = 1; 490 break; 491 492 case ETHER_STAT_CAP_PAUSE: 493 *val = 1; 494 break; 495 496 case ETHER_STAT_CAP_AUTONEG: 497 *val = 1; 498 break; 499 500 case ETHER_STAT_ADV_CAP_1000FDX: 501 *val = ngep->param_adv_1000fdx; 502 break; 503 504 case ETHER_STAT_ADV_CAP_1000HDX: 505 *val = ngep->param_adv_1000hdx; 506 break; 507 508 case ETHER_STAT_ADV_CAP_100FDX: 509 *val = ngep->param_adv_100fdx; 510 break; 511 512 case ETHER_STAT_ADV_CAP_100HDX: 513 *val = ngep->param_adv_100hdx; 514 break; 515 516 case ETHER_STAT_ADV_CAP_10FDX: 517 *val = ngep->param_adv_10fdx; 518 break; 519 520 case ETHER_STAT_ADV_CAP_10HDX: 521 *val = ngep->param_adv_10hdx; 522 break; 523 524 case ETHER_STAT_ADV_CAP_ASMPAUSE: 525 *val = ngep->param_adv_asym_pause; 526 break; 527 528 case ETHER_STAT_ADV_CAP_PAUSE: 529 *val = ngep->param_adv_pause; 530 break; 531 532 case ETHER_STAT_ADV_CAP_AUTONEG: 533 *val = ngep->param_adv_autoneg; 534 break; 535 536 case ETHER_STAT_LP_CAP_1000FDX: 537 *val = ngep->param_lp_1000fdx; 538 break; 539 540 case ETHER_STAT_LP_CAP_1000HDX: 541 *val = ngep->param_lp_1000hdx; 542 break; 543 544 case ETHER_STAT_LP_CAP_100FDX: 545 *val = ngep->param_lp_100fdx; 546 break; 547 548 case ETHER_STAT_LP_CAP_100HDX: 549 *val = ngep->param_lp_100hdx; 550 break; 551 552 case ETHER_STAT_LP_CAP_10FDX: 553 *val = ngep->param_lp_10fdx; 554 break; 555 556 case ETHER_STAT_LP_CAP_10HDX: 557 *val = ngep->param_lp_10hdx; 558 break; 559 560 case ETHER_STAT_LP_CAP_ASMPAUSE: 561 *val = ngep->param_lp_asym_pause; 562 break; 563 564 case ETHER_STAT_LP_CAP_PAUSE: 565 *val = ngep->param_lp_pause; 566 break; 567 568 case ETHER_STAT_LP_CAP_AUTONEG: 569 *val = ngep->param_lp_autoneg; 570 break; 571 572 case ETHER_STAT_LINK_ASMPAUSE: 573 *val = ngep->param_adv_asym_pause && 574 ngep->param_lp_asym_pause && 575 ngep->param_adv_pause != ngep->param_lp_pause; 576 break; 577 578 case ETHER_STAT_LINK_PAUSE: 579 *val = ngep->param_link_rx_pause; 580 break; 581 582 case ETHER_STAT_LINK_AUTONEG: 583 *val = ngep->param_link_autoneg; 584 break; 585 586 case ETHER_STAT_LINK_DUPLEX: 587 *val = ngep->param_link_duplex; 588 break; 589 590 default: 591 return (ENOTSUP); 592 } 593 594 return (0); 595 } 596