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