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