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