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