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 Emulex. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Source file containing the implementation of the driver statistics 29 * and related helper functions 30 */ 31 32 #include <oce_impl.h> 33 #include <oce_stat.h> 34 #include <oce_buf.h> 35 36 int pow10[5] = { 37 0, 38 10, 39 100, 40 1000, 41 10000 42 }; 43 44 /* 45 * function called by kstat to update the stats counters 46 * 47 * ksp - pointer to the kstats structure 48 * rw - flags defining read/write 49 * 50 * return DDI_SUCCESS => success, failure otherwise 51 */ 52 static int 53 oce_update_stats(kstat_t *ksp, int rw) 54 { 55 struct oce_dev *dev; 56 struct oce_stat *stats; 57 struct rx_port_stats *port_stats; 58 int ret; 59 60 if (rw == KSTAT_WRITE) { 61 return (EACCES); 62 } 63 64 dev = ksp->ks_private; 65 stats = (struct oce_stat *)ksp->ks_data; 66 port_stats = &dev->hw_stats->params.rsp.rx.port[dev->port_id]; 67 68 mutex_enter(&dev->dev_lock); 69 if (dev->suspended) { 70 mutex_exit(&dev->dev_lock); 71 return (EIO); 72 } 73 ret = oce_get_hw_stats(dev); 74 if (ret != DDI_SUCCESS) { 75 oce_log(dev, CE_WARN, MOD_CONFIG, 76 "Failed to get stats:%d", ret); 77 mutex_exit(&dev->dev_lock); 78 return (EIO); 79 } 80 81 /* update the stats */ 82 stats->rx_bytes_lo.value.ul = port_stats->rx_bytes_lsd; 83 stats->rx_bytes_hi.value.ul = port_stats->rx_bytes_msd; 84 85 stats->rx_frames.value.ul = port_stats->rx_total_frames; 86 stats->rx_errors.value.ul = port_stats->rx_crc_errors + 87 port_stats->rx_alignment_symbol_errors + 88 port_stats->rx_in_range_errors + 89 port_stats->rx_out_range_errors + 90 port_stats->rx_frame_too_long + 91 port_stats->rx_ip_checksum_errs + 92 port_stats->rx_tcp_checksum_errs + 93 port_stats->rx_udp_checksum_errs; 94 95 stats->rx_drops.value.ul = port_stats->rx_dropped_too_small + 96 port_stats->rx_dropped_too_short + 97 port_stats->rx_dropped_header_too_small + 98 port_stats->rx_dropped_tcp_length + 99 port_stats->rx_dropped_runt; 100 101 stats->tx_bytes_lo.value.ul = port_stats->tx_bytes_lsd; 102 stats->tx_bytes_hi.value.ul = port_stats->tx_bytes_msd; 103 104 stats->tx_frames.value.ul = port_stats->tx_unicast_frames + 105 port_stats->tx_multicast_frames + 106 port_stats->tx_broadcast_frames + 107 port_stats->tx_pause_frames + 108 port_stats->tx_control_frames; 109 stats->tx_errors.value.ul = dev->tx_errors; 110 111 stats->rx_unicast_frames.value.ul = 112 port_stats->rx_unicast_frames; 113 stats->rx_multicast_frames.value.ul = 114 port_stats->rx_multicast_frames; 115 stats->rx_broadcast_frames.value.ul = 116 port_stats->rx_broadcast_frames; 117 stats->rx_crc_errors.value.ul = 118 port_stats->rx_crc_errors; 119 120 stats->rx_alignment_symbol_errors.value.ul = 121 port_stats->rx_alignment_symbol_errors; 122 stats->rx_in_range_errors.value.ul = 123 port_stats->rx_in_range_errors; 124 stats->rx_out_range_errors.value.ul = 125 port_stats->rx_out_range_errors; 126 stats->rx_frame_too_long.value.ul = 127 port_stats->rx_frame_too_long; 128 stats->rx_address_match_errors.value.ul = 129 port_stats->rx_address_match_errors; 130 131 stats->rx_pause_frames.value.ul = 132 port_stats->rx_pause_frames; 133 stats->rx_control_frames.value.ul = 134 port_stats->rx_control_frames; 135 stats->rx_ip_checksum_errs.value.ul = 136 port_stats->rx_ip_checksum_errs; 137 stats->rx_tcp_checksum_errs.value.ul = 138 port_stats->rx_tcp_checksum_errs; 139 stats->rx_udp_checksum_errs.value.ul = 140 port_stats->rx_udp_checksum_errs; 141 stats->rx_fifo_overflow.value.ul = port_stats->rx_fifo_overflow; 142 stats->rx_input_fifo_overflow.value.ul = 143 port_stats->rx_input_fifo_overflow; 144 145 stats->tx_unicast_frames.value.ul = 146 port_stats->tx_unicast_frames; 147 stats->tx_multicast_frames.value.ul = 148 port_stats->tx_multicast_frames; 149 stats->tx_broadcast_frames.value.ul = 150 port_stats->tx_broadcast_frames; 151 stats->tx_pause_frames.value.ul = 152 port_stats->tx_pause_frames; 153 stats->tx_control_frames.value.ul = 154 port_stats->tx_control_frames; 155 mutex_exit(&dev->dev_lock); 156 return (DDI_SUCCESS); 157 } /* oce_update_stats */ 158 159 /* 160 * function to setup the kstat_t structure for the device and install it 161 * 162 * dev - software handle to the device 163 * 164 * return DDI_SUCCESS => success, failure otherwise 165 */ 166 int 167 oce_stat_init(struct oce_dev *dev) 168 { 169 struct oce_stat *stats; 170 uint32_t num_stats = sizeof (struct oce_stat) / 171 sizeof (kstat_named_t); 172 173 /* allocate the kstat */ 174 dev->oce_kstats = kstat_create(OCE_MOD_NAME, dev->dev_id, "stats", 175 "net", KSTAT_TYPE_NAMED, 176 num_stats, 0); 177 if (dev->oce_kstats == NULL) { 178 oce_log(dev, CE_NOTE, MOD_CONFIG, 179 "kstat creation failed: 0x%p", 180 (void *)dev->oce_kstats); 181 return (DDI_FAILURE); 182 } 183 184 /* allocate the device copy of the stats */ 185 dev->stats_dbuf = oce_alloc_dma_buffer(dev, 186 sizeof (struct mbx_get_nic_stats), 187 NULL, DDI_DMA_CONSISTENT); 188 if (dev->stats_dbuf == NULL) { 189 oce_log(dev, CE_NOTE, MOD_CONFIG, 190 "Could not allocate stats_dbuf: %p", 191 (void *)dev->stats_dbuf); 192 kstat_delete(dev->oce_kstats); 193 return (DDI_FAILURE); 194 } 195 dev->hw_stats = (struct mbx_get_nic_stats *)DBUF_VA(dev->stats_dbuf); 196 197 /* initialize the counters */ 198 stats = (struct oce_stat *)dev->oce_kstats->ks_data; 199 kstat_named_init(&stats->rx_bytes_hi, "rx bytes msd", KSTAT_DATA_ULONG); 200 kstat_named_init(&stats->rx_bytes_lo, "rx bytes lsd", KSTAT_DATA_ULONG); 201 202 kstat_named_init(&stats->rx_frames, "rx frames", KSTAT_DATA_ULONG); 203 kstat_named_init(&stats->rx_errors, "rx errors", KSTAT_DATA_ULONG); 204 kstat_named_init(&stats->rx_drops, "rx drops", KSTAT_DATA_ULONG); 205 206 kstat_named_init(&stats->tx_bytes_hi, "tx bytes msd", KSTAT_DATA_ULONG); 207 kstat_named_init(&stats->tx_bytes_lo, "tx bytes lsd", KSTAT_DATA_ULONG); 208 209 kstat_named_init(&stats->tx_frames, "tx frames", KSTAT_DATA_ULONG); 210 kstat_named_init(&stats->tx_errors, "tx errors", KSTAT_DATA_ULONG); 211 212 kstat_named_init(&stats->rx_unicast_frames, 213 "rx unicast frames", KSTAT_DATA_ULONG); 214 kstat_named_init(&stats->rx_multicast_frames, 215 "rx multicast frames", KSTAT_DATA_ULONG); 216 kstat_named_init(&stats->rx_broadcast_frames, 217 "rx broadcast frames", KSTAT_DATA_ULONG); 218 kstat_named_init(&stats->rx_crc_errors, 219 "rx crc errors", KSTAT_DATA_ULONG); 220 221 kstat_named_init(&stats->rx_alignment_symbol_errors, 222 "rx alignment symbol errors", KSTAT_DATA_ULONG); 223 kstat_named_init(&stats->rx_in_range_errors, 224 "rx in range errors", KSTAT_DATA_ULONG); 225 kstat_named_init(&stats->rx_out_range_errors, 226 "rx out range errors", KSTAT_DATA_ULONG); 227 kstat_named_init(&stats->rx_frame_too_long, 228 "rx frame too long", KSTAT_DATA_ULONG); 229 kstat_named_init(&stats->rx_address_match_errors, 230 "rx address match errors", KSTAT_DATA_ULONG); 231 232 kstat_named_init(&stats->rx_pause_frames, 233 "rx pause frames", KSTAT_DATA_ULONG); 234 kstat_named_init(&stats->rx_control_frames, 235 "rx control frames", KSTAT_DATA_ULONG); 236 kstat_named_init(&stats->rx_ip_checksum_errs, 237 "rx ip checksum errors", KSTAT_DATA_ULONG); 238 kstat_named_init(&stats->rx_tcp_checksum_errs, 239 "rx tcp checksum errors", KSTAT_DATA_ULONG); 240 kstat_named_init(&stats->rx_udp_checksum_errs, 241 "rx udp checksum errors", KSTAT_DATA_ULONG); 242 kstat_named_init(&stats->rx_fifo_overflow, 243 "rx fifo overflow", KSTAT_DATA_ULONG); 244 kstat_named_init(&stats->rx_input_fifo_overflow, 245 "rx input fifo overflow", KSTAT_DATA_ULONG); 246 247 kstat_named_init(&stats->tx_unicast_frames, 248 "tx unicast frames", KSTAT_DATA_ULONG); 249 kstat_named_init(&stats->tx_multicast_frames, 250 "tx multicast frames", KSTAT_DATA_ULONG); 251 kstat_named_init(&stats->tx_broadcast_frames, 252 "tx broadcast frames", KSTAT_DATA_ULONG); 253 kstat_named_init(&stats->tx_pause_frames, 254 "tx pause frames", KSTAT_DATA_ULONG); 255 kstat_named_init(&stats->tx_control_frames, 256 "tx control frames", KSTAT_DATA_ULONG); 257 258 dev->oce_kstats->ks_update = oce_update_stats; 259 dev->oce_kstats->ks_private = (void *)dev; 260 kstat_install(dev->oce_kstats); 261 262 return (DDI_SUCCESS); 263 } /* oce_stat_init */ 264 265 /* 266 * function to undo initialization done in oce_stat_init 267 * 268 * dev - software handle to the device 269 * 270 * return none 271 */ 272 void 273 oce_stat_fini(struct oce_dev *dev) 274 { 275 oce_free_dma_buffer(dev, dev->stats_dbuf); 276 dev->hw_stats = NULL; 277 dev->stats_dbuf = NULL; 278 kstat_delete(dev->oce_kstats); 279 dev->oce_kstats = NULL; 280 } /* oce_stat_fini */ 281 282 /* 283 * GLDv3 entry for statistic query 284 */ 285 int 286 oce_m_stat(void *arg, uint_t stat, uint64_t *val) 287 { 288 struct oce_dev *dev = arg; 289 struct oce_stat *stats; 290 struct rx_port_stats *port_stats; 291 292 stats = (struct oce_stat *)dev->oce_kstats->ks_data; 293 port_stats = &dev->hw_stats->params.rsp.rx.port[dev->port_id]; 294 295 mutex_enter(&dev->dev_lock); 296 297 if (dev->suspended || 298 (dev->state & STATE_MAC_STOPPING) || 299 !(dev->state & STATE_MAC_STARTED)) { 300 mutex_exit(&dev->dev_lock); 301 return (EIO); 302 } 303 304 switch (stat) { 305 case MAC_STAT_IFSPEED: { 306 struct link_status link = {0}; 307 if (dev->link_speed < 0) { 308 (void) oce_get_link_status(dev, &link); 309 dev->link_speed = link.qos_link_speed ? 310 link.qos_link_speed * 10 : 311 pow10[link.mac_speed]; 312 } 313 *val = dev->link_speed * 1000000ull; 314 } 315 break; 316 317 case MAC_STAT_RBYTES: 318 stats->rx_bytes_lo.value.ul = port_stats->rx_bytes_lsd; 319 stats->rx_bytes_hi.value.ul = port_stats->rx_bytes_msd; 320 *val = (uint64_t)stats->rx_bytes_hi.value.ul << 32 | 321 (uint64_t)stats->rx_bytes_lo.value.ul; 322 break; 323 324 case MAC_STAT_IPACKETS: 325 stats->rx_frames.value.ul = port_stats->rx_total_frames; 326 *val = stats->rx_frames.value.ul; 327 break; 328 329 case MAC_STAT_OBYTES: 330 stats->tx_bytes_lo.value.ul = port_stats->tx_bytes_lsd; 331 stats->tx_bytes_hi.value.ul = port_stats->tx_bytes_msd; 332 *val = (uint64_t)stats->tx_bytes_hi.value.ul << 32 | 333 (uint64_t)stats->tx_bytes_lo.value.ul; 334 break; 335 336 case MAC_STAT_OPACKETS: 337 stats->tx_frames.value.ul = port_stats->tx_unicast_frames + 338 port_stats->tx_multicast_frames + 339 port_stats->tx_broadcast_frames + 340 port_stats->tx_pause_frames + 341 port_stats->tx_control_frames; 342 *val = stats->tx_frames.value.ul; 343 break; 344 345 case MAC_STAT_BRDCSTRCV: 346 stats->rx_broadcast_frames.value.ul = 347 port_stats->rx_broadcast_frames; 348 *val = stats->rx_broadcast_frames.value.ul; 349 break; 350 351 case MAC_STAT_MULTIRCV: 352 stats->rx_multicast_frames.value.ul = 353 port_stats->rx_multicast_frames; 354 *val = stats->rx_multicast_frames.value.ul; 355 break; 356 357 case MAC_STAT_MULTIXMT: 358 stats->tx_multicast_frames.value.ul = 359 port_stats->tx_multicast_frames; 360 *val = stats->tx_multicast_frames.value.ul; 361 break; 362 363 case MAC_STAT_BRDCSTXMT: 364 stats->tx_broadcast_frames.value.ul = 365 port_stats->tx_broadcast_frames; 366 *val = stats->tx_broadcast_frames.value.ul; 367 break; 368 369 case MAC_STAT_NORCVBUF: 370 stats->rx_fifo_overflow.value.ul = 371 port_stats->rx_fifo_overflow; 372 *val = stats->rx_fifo_overflow.value.ul; 373 break; 374 375 case MAC_STAT_IERRORS: 376 stats->rx_errors.value.ul = port_stats->rx_crc_errors + 377 port_stats->rx_alignment_symbol_errors + 378 port_stats->rx_in_range_errors + 379 port_stats->rx_out_range_errors + 380 port_stats->rx_frame_too_long + 381 port_stats->rx_ip_checksum_errs + 382 port_stats->rx_tcp_checksum_errs + 383 port_stats->rx_udp_checksum_errs; 384 *val = stats->rx_errors.value.ul; 385 break; 386 387 case MAC_STAT_NOXMTBUF: 388 *val = dev->tx_noxmtbuf; 389 break; 390 391 case MAC_STAT_OERRORS: 392 *val = stats->tx_errors.value.ul; 393 break; 394 395 case ETHER_STAT_LINK_DUPLEX: 396 if (dev->state & STATE_MAC_STARTED) 397 *val = LINK_DUPLEX_FULL; 398 else 399 *val = LINK_DUPLEX_UNKNOWN; 400 break; 401 402 case ETHER_STAT_ALIGN_ERRORS: 403 stats->rx_alignment_symbol_errors.value.ul = 404 port_stats->rx_alignment_symbol_errors; 405 *val = port_stats->rx_alignment_symbol_errors; 406 break; 407 408 case ETHER_STAT_FCS_ERRORS: 409 stats->rx_crc_errors.value.ul = 410 port_stats->rx_crc_errors; 411 *val = port_stats->rx_crc_errors; 412 break; 413 414 case ETHER_STAT_MACRCV_ERRORS: 415 stats->rx_errors.value.ul = port_stats->rx_crc_errors + 416 port_stats->rx_alignment_symbol_errors + 417 port_stats->rx_in_range_errors + 418 port_stats->rx_out_range_errors + 419 port_stats->rx_frame_too_long + 420 port_stats->rx_ip_checksum_errs + 421 port_stats->rx_tcp_checksum_errs + 422 port_stats->rx_udp_checksum_errs; 423 424 *val = stats->rx_errors.value.ul; 425 break; 426 427 case ETHER_STAT_MACXMT_ERRORS: 428 *val = stats->tx_errors.value.ul; 429 break; 430 431 case ETHER_STAT_TOOLONG_ERRORS: 432 stats->rx_frame_too_long.value.ul = 433 port_stats->rx_frame_too_long; 434 *val = port_stats->rx_frame_too_long; 435 break; 436 437 case ETHER_STAT_CAP_PAUSE: 438 case ETHER_STAT_LINK_PAUSE: 439 if (dev->flow_control & OCE_FC_TX && 440 dev->flow_control & OCE_FC_RX) 441 *val = LINK_FLOWCTRL_BI; 442 else if (dev->flow_control == OCE_FC_TX) 443 *val = LINK_FLOWCTRL_TX; 444 else if (dev->flow_control == OCE_FC_RX) 445 *val = LINK_FLOWCTRL_RX; 446 else if (dev->flow_control == 0) 447 *val = LINK_FLOWCTRL_NONE; 448 break; 449 450 default: 451 mutex_exit(&dev->dev_lock); 452 return (ENOTSUP); 453 } 454 mutex_exit(&dev->dev_lock); 455 return (0); 456 } /* oce_m_stat */ 457