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 void 247 nge_init_kstats(nge_t *ngep, int instance) 248 { 249 NGE_TRACE(("nge_init_kstats($%p, %d)", (void *)ngep, instance)); 250 251 ngep->nge_kstats[NGE_KSTAT_STATS] = nge_setup_named_kstat(ngep, 252 instance, "statistics", nge_statistics, 253 sizeof (nge_statistics), nge_statistics_update); 254 255 ngep->nge_kstats[NGE_KSTAT_CHIPID] = nge_setup_named_kstat(ngep, 256 instance, "chipinfo", nge_chipinfo, 257 sizeof (nge_chipinfo), nge_chipinfo_update); 258 259 ngep->nge_kstats[NGE_KSTAT_DEBUG] = nge_setup_named_kstat(ngep, 260 instance, "driver-debug", nge_debuginfo, 261 sizeof (nge_debuginfo), nge_debuginfo_update); 262 263 } 264 265 void 266 nge_fini_kstats(nge_t *ngep) 267 { 268 int i; 269 270 NGE_TRACE(("nge_fini_kstats($%p)", (void *)ngep)); 271 for (i = NGE_KSTAT_COUNT; --i >= 0; ) 272 if (ngep->nge_kstats[i] != NULL) 273 kstat_delete(ngep->nge_kstats[i]); 274 } 275 276 int 277 nge_m_stat(void *arg, uint_t stat, uint64_t *val) 278 { 279 nge_t *ngep = arg; 280 uint32_t regno; 281 nge_statistics_t *nstp = &ngep->statistics; 282 nge_hw_statistics_t *hw_stp = &nstp->hw_statistics; 283 nge_sw_statistics_t *sw_stp = &nstp->sw_statistics; 284 285 switch (stat) { 286 case MAC_STAT_IFSPEED: 287 *val = ngep->param_link_speed * 1000000ull; 288 break; 289 290 case MAC_STAT_MULTIRCV: 291 regno = KS_BASE + KS_ifHInMulPksCount * sizeof (uint32_t); 292 hw_stp->s.InMulPksCount += nge_reg_get32(ngep, regno); 293 *val = hw_stp->s.InMulPksCount; 294 break; 295 296 case MAC_STAT_BRDCSTRCV: 297 regno = KS_BASE + KS_ifHInBroadPksCount * sizeof (uint32_t); 298 hw_stp->s.InBroadPksCount += nge_reg_get32(ngep, regno); 299 *val = hw_stp->s.InBroadPksCount; 300 break; 301 302 case MAC_STAT_NORCVBUF: 303 *val = sw_stp->rx_nobuffer; 304 break; 305 306 case MAC_STAT_IERRORS: 307 regno = KS_BASE + KS_ifHInFrameErrCount * sizeof (uint32_t); 308 hw_stp->s.InFrameErrCount += nge_reg_get32(ngep, regno); 309 regno = KS_BASE + KS_ifHInExtraOctErrCount * sizeof (uint32_t); 310 hw_stp->s.InExtraOctErrCount += nge_reg_get32(ngep, regno); 311 regno = KS_BASE + KS_ifHInLColErrCount * sizeof (uint32_t); 312 hw_stp->s.InLColErrCount += nge_reg_get32(ngep, regno); 313 regno = KS_BASE + KS_ifHInOversizeErrCount * sizeof (uint32_t); 314 hw_stp->s.InOversizeErrCount += nge_reg_get32(ngep, regno); 315 regno = KS_BASE + KS_ifHInFovErrCount * sizeof (uint32_t); 316 hw_stp->s.InFovErrCount += nge_reg_get32(ngep, regno); 317 regno = KS_BASE + KS_ifHInFCSErrCount * sizeof (uint32_t); 318 hw_stp->s.InFCSErrCount += nge_reg_get32(ngep, regno); 319 regno = KS_BASE + KS_ifHInAlignErrCount * sizeof (uint32_t); 320 hw_stp->s.InAlignErrCount += nge_reg_get32(ngep, regno); 321 regno = KS_BASE + KS_ifHInLenErrCount * sizeof (uint32_t); 322 hw_stp->s.InLenErrCount += nge_reg_get32(ngep, regno); 323 *val = hw_stp->s.InFrameErrCount + 324 hw_stp->s.InExtraOctErrCount + 325 hw_stp->s.InLColErrCount + 326 hw_stp->s.InOversizeErrCount + 327 hw_stp->s.InFovErrCount + 328 hw_stp->s.InFCSErrCount + 329 hw_stp->s.InAlignErrCount + 330 hw_stp->s.InLenErrCount; 331 break; 332 333 case MAC_STAT_OERRORS: 334 regno = KS_BASE + KS_ifHOutFifoovCount * sizeof (uint32_t); 335 hw_stp->s.OutFifoovCount += nge_reg_get32(ngep, regno); 336 regno = KS_BASE + KS_ifHOutLOCCount * sizeof (uint32_t); 337 hw_stp->s.OutLOCCount += nge_reg_get32(ngep, regno); 338 regno = KS_BASE + KS_ifHOutExDecCount * sizeof (uint32_t); 339 hw_stp->s.OutExDecCount += nge_reg_get32(ngep, regno); 340 regno = KS_BASE + KS_ifHOutRetryCount * sizeof (uint32_t); 341 hw_stp->s.OutRetryCount += nge_reg_get32(ngep, regno); 342 *val = hw_stp->s.OutFifoovCount + 343 hw_stp->s.OutLOCCount + 344 hw_stp->s.OutExDecCount + 345 hw_stp->s.OutRetryCount; 346 break; 347 348 case MAC_STAT_COLLISIONS: 349 regno = KS_BASE + KS_ifHOutColCount * sizeof (uint32_t); 350 hw_stp->s.OutColCount += nge_reg_get32(ngep, regno); 351 *val = hw_stp->s.OutColCount; 352 break; 353 354 case MAC_STAT_RBYTES: 355 *val = sw_stp->rbytes; 356 break; 357 358 case MAC_STAT_IPACKETS: 359 *val = sw_stp->recv_count; 360 break; 361 362 case MAC_STAT_OBYTES: 363 *val = sw_stp->obytes; 364 break; 365 366 case MAC_STAT_OPACKETS: 367 *val = sw_stp->xmit_count; 368 break; 369 370 case ETHER_STAT_ALIGN_ERRORS: 371 regno = KS_BASE + KS_ifHInAlignErrCount * sizeof (uint32_t); 372 hw_stp->s.InAlignErrCount += nge_reg_get32(ngep, regno); 373 *val = hw_stp->s.InAlignErrCount; 374 break; 375 376 case ETHER_STAT_FCS_ERRORS: 377 regno = KS_BASE + KS_ifHInFCSErrCount * sizeof (uint32_t); 378 hw_stp->s.InFCSErrCount += nge_reg_get32(ngep, regno); 379 *val = hw_stp->s.InFCSErrCount; 380 break; 381 382 case ETHER_STAT_FIRST_COLLISIONS: 383 regno = KS_BASE + KS_ifHOutZeroRetranCount * sizeof (uint32_t); 384 hw_stp->s.OutZeroRetranCount += nge_reg_get32(ngep, regno); 385 *val = hw_stp->s.OutZeroRetranCount; 386 break; 387 388 case ETHER_STAT_MULTI_COLLISIONS: 389 regno = KS_BASE + KS_ifHOutOneRetranCount * sizeof (uint32_t); 390 hw_stp->s.OutOneRetranCount += nge_reg_get32(ngep, regno); 391 regno = KS_BASE + KS_ifHOutMoreRetranCount * sizeof (uint32_t); 392 hw_stp->s.OutMoreRetranCount += nge_reg_get32(ngep, regno); 393 *val = hw_stp->s.OutOneRetranCount + 394 hw_stp->s.OutMoreRetranCount; 395 break; 396 397 case ETHER_STAT_DEFER_XMTS: 398 regno = KS_BASE + KS_ifHOutExDecCount * sizeof (uint32_t); 399 hw_stp->s.OutExDecCount += nge_reg_get32(ngep, regno); 400 *val = hw_stp->s.OutExDecCount; 401 break; 402 403 case ETHER_STAT_TX_LATE_COLLISIONS: 404 regno = KS_BASE + KS_ifHOutColCount * sizeof (uint32_t); 405 hw_stp->s.OutColCount += nge_reg_get32(ngep, regno); 406 *val = hw_stp->s.OutColCount; 407 break; 408 409 case ETHER_STAT_EX_COLLISIONS: 410 regno = KS_BASE + KS_ifHOutOneRetranCount * sizeof (uint32_t); 411 hw_stp->s.OutOneRetranCount += nge_reg_get32(ngep, regno); 412 *val = hw_stp->s.OutOneRetranCount; 413 break; 414 415 case ETHER_STAT_CARRIER_ERRORS: 416 regno = KS_BASE + KS_ifHOutLOCCount * sizeof (uint32_t); 417 hw_stp->s.OutLOCCount += nge_reg_get32(ngep, regno); 418 *val = hw_stp->s.OutLOCCount; 419 break; 420 421 case ETHER_STAT_TOOLONG_ERRORS: 422 regno = KS_BASE + KS_ifHInOversizeErrCount * sizeof (uint32_t); 423 hw_stp->s.InOversizeErrCount += nge_reg_get32(ngep, regno); 424 *val = hw_stp->s.InOversizeErrCount; 425 break; 426 427 case ETHER_STAT_XCVR_ADDR: 428 *val = ngep->phy_xmii_addr; 429 break; 430 431 case ETHER_STAT_XCVR_ID: 432 *val = ngep->phy_id; 433 break; 434 435 case ETHER_STAT_XCVR_INUSE: 436 *val = XCVR_1000T; 437 break; 438 439 case ETHER_STAT_CAP_1000FDX: 440 *val = 1; 441 break; 442 443 case ETHER_STAT_CAP_1000HDX: 444 *val = 0; 445 break; 446 447 case ETHER_STAT_CAP_100FDX: 448 *val = 1; 449 break; 450 451 case ETHER_STAT_CAP_100HDX: 452 *val = 1; 453 break; 454 455 case ETHER_STAT_CAP_10FDX: 456 *val = 1; 457 break; 458 459 case ETHER_STAT_CAP_10HDX: 460 *val = 1; 461 break; 462 463 case ETHER_STAT_CAP_ASMPAUSE: 464 *val = 1; 465 break; 466 467 case ETHER_STAT_CAP_PAUSE: 468 *val = 1; 469 break; 470 471 case ETHER_STAT_CAP_AUTONEG: 472 *val = 1; 473 break; 474 475 case ETHER_STAT_ADV_CAP_1000FDX: 476 *val = ngep->param_adv_1000fdx; 477 break; 478 479 case ETHER_STAT_ADV_CAP_1000HDX: 480 *val = ngep->param_adv_1000hdx; 481 break; 482 483 case ETHER_STAT_ADV_CAP_100FDX: 484 *val = ngep->param_adv_100fdx; 485 break; 486 487 case ETHER_STAT_ADV_CAP_100HDX: 488 *val = ngep->param_adv_100hdx; 489 break; 490 491 case ETHER_STAT_ADV_CAP_10FDX: 492 *val = ngep->param_adv_10fdx; 493 break; 494 495 case ETHER_STAT_ADV_CAP_10HDX: 496 *val = ngep->param_adv_10hdx; 497 break; 498 499 case ETHER_STAT_ADV_CAP_ASMPAUSE: 500 *val = ngep->param_adv_asym_pause; 501 break; 502 503 case ETHER_STAT_ADV_CAP_PAUSE: 504 *val = ngep->param_adv_pause; 505 break; 506 507 case ETHER_STAT_ADV_CAP_AUTONEG: 508 *val = ngep->param_adv_autoneg; 509 break; 510 511 case ETHER_STAT_LP_CAP_1000FDX: 512 *val = ngep->param_lp_1000fdx; 513 break; 514 515 case ETHER_STAT_LP_CAP_1000HDX: 516 *val = ngep->param_lp_1000hdx; 517 break; 518 519 case ETHER_STAT_LP_CAP_100FDX: 520 *val = ngep->param_lp_100fdx; 521 break; 522 523 case ETHER_STAT_LP_CAP_100HDX: 524 *val = ngep->param_lp_100hdx; 525 break; 526 527 case ETHER_STAT_LP_CAP_10FDX: 528 *val = ngep->param_lp_10fdx; 529 break; 530 531 case ETHER_STAT_LP_CAP_10HDX: 532 *val = ngep->param_lp_10hdx; 533 break; 534 535 case ETHER_STAT_LP_CAP_ASMPAUSE: 536 *val = ngep->param_lp_asym_pause; 537 break; 538 539 case ETHER_STAT_LP_CAP_PAUSE: 540 *val = ngep->param_lp_pause; 541 break; 542 543 case ETHER_STAT_LP_CAP_AUTONEG: 544 *val = ngep->param_lp_autoneg; 545 break; 546 547 case ETHER_STAT_LINK_ASMPAUSE: 548 *val = ngep->param_adv_asym_pause && 549 ngep->param_lp_asym_pause && 550 ngep->param_adv_pause != ngep->param_lp_pause; 551 break; 552 553 case ETHER_STAT_LINK_PAUSE: 554 *val = ngep->param_link_rx_pause; 555 break; 556 557 case ETHER_STAT_LINK_AUTONEG: 558 *val = ngep->param_link_autoneg; 559 break; 560 561 case ETHER_STAT_LINK_DUPLEX: 562 *val = ngep->param_link_duplex; 563 break; 564 565 default: 566 return (ENOTSUP); 567 } 568 569 return (0); 570 } 571