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