xref: /illumos-gate/usr/src/uts/common/io/ixgbe/ixgbe_stat.c (revision 45ede40b2394db7967e59f19288fae9b62efd4aa)
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(c) 2007-2010 Intel Corporation. All rights reserved.
24  */
25 
26 /*
27  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
29  * Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved.
30  * Copyright 2019 Joyent, Inc.
31  */
32 
33 #include "ixgbe_sw.h"
34 
35 /*
36  * The 82598 controller lacks a high/low register for the various
37  * octet counters, but the common code also lacks a definition for
38  * these older registers. In these cases, the high register address
39  * maps to the appropriate address in the 82598 controller.
40  */
41 #define	IXGBE_TOR	IXGBE_TORH
42 #define	IXGBE_GOTC	IXGBE_GOTCH
43 #define	IXGBE_GORC	IXGBE_GORCH
44 
45 /*
46  * Read total octets received.
47  */
48 static uint64_t
49 ixgbe_read_tor_value(const struct ixgbe_hw *hw)
50 {
51 	uint64_t tor = 0;
52 	uint64_t hi = 0, lo = 0;
53 
54 	switch (hw->mac.type) {
55 	case ixgbe_mac_82598EB:
56 		tor = IXGBE_READ_REG(hw, IXGBE_TOR);
57 		break;
58 
59 	default:
60 		lo = IXGBE_READ_REG(hw, IXGBE_TORL);
61 		hi = IXGBE_READ_REG(hw, IXGBE_TORH) & 0xF;
62 		tor = (hi << 32) + lo;
63 		break;
64 	}
65 
66 	return (tor);
67 }
68 
69 /*
70  * Read queue octets received.
71  */
72 static uint64_t
73 ixgbe_read_qor_value(const struct ixgbe_hw *hw)
74 {
75 	uint64_t qor = 0;
76 	uint64_t hi = 0, lo = 0;
77 
78 	switch (hw->mac.type) {
79 	case ixgbe_mac_82598EB:
80 		qor = IXGBE_READ_REG(hw, IXGBE_QBRC(0));
81 		break;
82 
83 	default:
84 		lo = IXGBE_READ_REG(hw, IXGBE_QBRC_L(0));
85 		hi = IXGBE_READ_REG(hw, IXGBE_QBRC_H(0)) & 0xF;
86 		qor = (hi << 32) + lo;
87 		break;
88 	}
89 
90 	return (qor);
91 }
92 
93 /*
94  * Read queue octets transmitted.
95  */
96 static uint64_t
97 ixgbe_read_qot_value(const struct ixgbe_hw *hw)
98 {
99 	uint64_t qot = 0;
100 	uint64_t hi = 0, lo = 0;
101 
102 	switch (hw->mac.type) {
103 	case ixgbe_mac_82598EB:
104 		qot = IXGBE_READ_REG(hw, IXGBE_QBTC(0));
105 		break;
106 
107 	default:
108 		lo = IXGBE_READ_REG(hw, IXGBE_QBTC_L(0));
109 		hi = IXGBE_READ_REG(hw, IXGBE_QBTC_H(0)) & 0xF;
110 		qot = (hi << 32) + lo;
111 		break;
112 	}
113 
114 	return (qot);
115 }
116 
117 /*
118  * Read good octets transmitted.
119  */
120 static uint64_t
121 ixgbe_read_got_value(const struct ixgbe_hw *hw)
122 {
123 	uint64_t got = 0;
124 	uint64_t hi = 0, lo = 0;
125 
126 	switch (hw->mac.type) {
127 	case ixgbe_mac_82598EB:
128 		got = IXGBE_READ_REG(hw, IXGBE_GOTC);
129 		break;
130 
131 	default:
132 		lo = IXGBE_READ_REG(hw, IXGBE_GOTCL);
133 		hi = IXGBE_READ_REG(hw, IXGBE_GOTCH) & 0xF;
134 		got = (hi << 32) + lo;
135 		break;
136 	}
137 
138 	return (got);
139 }
140 
141 /*
142  * Read good octets received.
143  */
144 static uint64_t
145 ixgbe_read_gor_value(const struct ixgbe_hw *hw)
146 {
147 	uint64_t gor = 0;
148 	uint64_t hi = 0, lo = 0;
149 
150 	switch (hw->mac.type) {
151 	case ixgbe_mac_82598EB:
152 		gor = IXGBE_READ_REG(hw, IXGBE_GORC);
153 		break;
154 
155 	default:
156 		lo = IXGBE_READ_REG(hw, IXGBE_GORCL);
157 		hi = IXGBE_READ_REG(hw, IXGBE_GORCH) & 0xF;
158 		gor = (hi << 32) + lo;
159 		break;
160 	}
161 
162 	return (gor);
163 }
164 
165 /*
166  * Update driver private statistics.
167  */
168 static int
169 ixgbe_update_stats(kstat_t *ks, int rw)
170 {
171 	ixgbe_t *ixgbe;
172 	struct ixgbe_hw *hw;
173 	ixgbe_stat_t *ixgbe_ks;
174 	int i;
175 
176 	if (rw == KSTAT_WRITE)
177 		return (EACCES);
178 
179 	ixgbe = (ixgbe_t *)ks->ks_private;
180 	ixgbe_ks = (ixgbe_stat_t *)ks->ks_data;
181 	hw = &ixgbe->hw;
182 
183 	mutex_enter(&ixgbe->gen_lock);
184 
185 	/*
186 	 * Basic information
187 	 */
188 	ixgbe_ks->link_speed.value.ui64 = ixgbe->link_speed;
189 	ixgbe_ks->reset_count.value.ui64 = ixgbe->reset_count;
190 	ixgbe_ks->lroc.value.ui64 = ixgbe->lro_pkt_count;
191 
192 	ixgbe_ks->rx_frame_error.value.ui64 = 0;
193 	ixgbe_ks->rx_cksum_error.value.ui64 = 0;
194 	ixgbe_ks->rx_exceed_pkt.value.ui64 = 0;
195 	for (i = 0; i < ixgbe->num_rx_rings; i++) {
196 		ixgbe_ks->rx_frame_error.value.ui64 +=
197 		    ixgbe->rx_rings[i].stat_frame_error;
198 		ixgbe_ks->rx_cksum_error.value.ui64 +=
199 		    ixgbe->rx_rings[i].stat_cksum_error;
200 		ixgbe_ks->rx_exceed_pkt.value.ui64 +=
201 		    ixgbe->rx_rings[i].stat_exceed_pkt;
202 	}
203 
204 	ixgbe_ks->tx_overload.value.ui64 = 0;
205 	ixgbe_ks->tx_fail_no_tbd.value.ui64 = 0;
206 	ixgbe_ks->tx_fail_no_tcb.value.ui64 = 0;
207 	ixgbe_ks->tx_fail_dma_bind.value.ui64 = 0;
208 	ixgbe_ks->tx_reschedule.value.ui64 = 0;
209 	ixgbe_ks->tx_break_tbd_limit.value.ui64 = 0;
210 	ixgbe_ks->tx_lso_header_fail.value.ui64 = 0;
211 	for (i = 0; i < ixgbe->num_tx_rings; i++) {
212 		ixgbe_ks->tx_overload.value.ui64 +=
213 		    ixgbe->tx_rings[i].stat_overload;
214 		ixgbe_ks->tx_fail_no_tbd.value.ui64 +=
215 		    ixgbe->tx_rings[i].stat_fail_no_tbd;
216 		ixgbe_ks->tx_fail_no_tcb.value.ui64 +=
217 		    ixgbe->tx_rings[i].stat_fail_no_tcb;
218 		ixgbe_ks->tx_fail_dma_bind.value.ui64 +=
219 		    ixgbe->tx_rings[i].stat_fail_dma_bind;
220 		ixgbe_ks->tx_reschedule.value.ui64 +=
221 		    ixgbe->tx_rings[i].stat_reschedule;
222 		ixgbe_ks->tx_break_tbd_limit.value.ui64 +=
223 		    ixgbe->tx_rings[i].stat_break_tbd_limit;
224 		ixgbe_ks->tx_lso_header_fail.value.ui64 +=
225 		    ixgbe->tx_rings[i].stat_lso_header_fail;
226 	}
227 
228 	/*
229 	 * Hardware calculated statistics.
230 	 */
231 	ixgbe_ks->gprc.value.ui64 += IXGBE_READ_REG(hw, IXGBE_GPRC);
232 	ixgbe_ks->gptc.value.ui64 += IXGBE_READ_REG(hw, IXGBE_GPTC);
233 	ixgbe_ks->gor.value.ui64 += ixgbe_read_gor_value(hw);
234 	ixgbe_ks->got.value.ui64 += ixgbe_read_got_value(hw);
235 	ixgbe_ks->qpr.value.ui64 += IXGBE_READ_REG(hw, IXGBE_QPRC(0));
236 	ixgbe_ks->qpt.value.ui64 += IXGBE_READ_REG(hw, IXGBE_QPTC(0));
237 	ixgbe_ks->qor.value.ui64 += ixgbe_read_qor_value(hw);
238 	ixgbe_ks->qot.value.ui64 += ixgbe_read_qot_value(hw);
239 	ixgbe_ks->tor.value.ui64 += ixgbe_read_tor_value(hw);
240 	ixgbe_ks->tot.value.ui64 = ixgbe_ks->got.value.ui64;
241 
242 	ixgbe_ks->prc64.value.ul += IXGBE_READ_REG(hw, IXGBE_PRC64);
243 	ixgbe_ks->prc127.value.ul += IXGBE_READ_REG(hw, IXGBE_PRC127);
244 	ixgbe_ks->prc255.value.ul += IXGBE_READ_REG(hw, IXGBE_PRC255);
245 	ixgbe_ks->prc511.value.ul += IXGBE_READ_REG(hw, IXGBE_PRC511);
246 	ixgbe_ks->prc1023.value.ul += IXGBE_READ_REG(hw, IXGBE_PRC1023);
247 	ixgbe_ks->prc1522.value.ul += IXGBE_READ_REG(hw, IXGBE_PRC1522);
248 	ixgbe_ks->ptc64.value.ul += IXGBE_READ_REG(hw, IXGBE_PTC64);
249 	ixgbe_ks->ptc127.value.ul += IXGBE_READ_REG(hw, IXGBE_PTC127);
250 	ixgbe_ks->ptc255.value.ul += IXGBE_READ_REG(hw, IXGBE_PTC255);
251 	ixgbe_ks->ptc511.value.ul += IXGBE_READ_REG(hw, IXGBE_PTC511);
252 	ixgbe_ks->ptc1023.value.ul += IXGBE_READ_REG(hw, IXGBE_PTC1023);
253 	ixgbe_ks->ptc1522.value.ul += IXGBE_READ_REG(hw, IXGBE_PTC1522);
254 
255 	ixgbe_ks->mspdc.value.ui64 += IXGBE_READ_REG(hw, IXGBE_MSPDC);
256 	for (i = 0; i < 8; i++)
257 		ixgbe_ks->mpc.value.ui64 += IXGBE_READ_REG(hw, IXGBE_MPC(i));
258 	ixgbe_ks->mlfc.value.ui64 += IXGBE_READ_REG(hw, IXGBE_MLFC);
259 	ixgbe_ks->mrfc.value.ui64 += IXGBE_READ_REG(hw, IXGBE_MRFC);
260 	ixgbe_ks->rlec.value.ui64 += IXGBE_READ_REG(hw, IXGBE_RLEC);
261 	ixgbe_ks->lxontxc.value.ui64 += IXGBE_READ_REG(hw, IXGBE_LXONTXC);
262 	switch (hw->mac.type) {
263 	case ixgbe_mac_82598EB:
264 		ixgbe_ks->lxonrxc.value.ui64 += IXGBE_READ_REG(hw,
265 		    IXGBE_LXONRXC);
266 		break;
267 
268 	case ixgbe_mac_82599EB:
269 	case ixgbe_mac_X540:
270 	case ixgbe_mac_X550:
271 	case ixgbe_mac_X550EM_x:
272 	case ixgbe_mac_X550EM_a:
273 		ixgbe_ks->lxonrxc.value.ui64 += IXGBE_READ_REG(hw,
274 		    IXGBE_LXONRXCNT);
275 		break;
276 
277 	default:
278 		break;
279 	}
280 	ixgbe_ks->lxofftxc.value.ui64 += IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
281 	switch (hw->mac.type) {
282 	case ixgbe_mac_82598EB:
283 		ixgbe_ks->lxoffrxc.value.ui64 += IXGBE_READ_REG(hw,
284 		    IXGBE_LXOFFRXC);
285 		break;
286 
287 	case ixgbe_mac_82599EB:
288 	case ixgbe_mac_X540:
289 	case ixgbe_mac_X550:
290 	case ixgbe_mac_X550EM_x:
291 	case ixgbe_mac_X550EM_a:
292 		ixgbe_ks->lxoffrxc.value.ui64 += IXGBE_READ_REG(hw,
293 		    IXGBE_LXOFFRXCNT);
294 		break;
295 
296 	default:
297 		break;
298 	}
299 	ixgbe_ks->ruc.value.ui64 += IXGBE_READ_REG(hw, IXGBE_RUC);
300 	ixgbe_ks->rfc.value.ui64 += IXGBE_READ_REG(hw, IXGBE_RFC);
301 	ixgbe_ks->roc.value.ui64 += IXGBE_READ_REG(hw, IXGBE_ROC);
302 	ixgbe_ks->rjc.value.ui64 += IXGBE_READ_REG(hw, IXGBE_RJC);
303 
304 	mutex_exit(&ixgbe->gen_lock);
305 
306 	if (ixgbe_check_acc_handle(ixgbe->osdep.reg_handle) != DDI_FM_OK)
307 		ddi_fm_service_impact(ixgbe->dip, DDI_SERVICE_UNAFFECTED);
308 
309 	return (0);
310 }
311 
312 /*
313  * Create and initialize the driver private statistics.
314  */
315 int
316 ixgbe_init_stats(ixgbe_t *ixgbe)
317 {
318 	kstat_t *ks;
319 	ixgbe_stat_t *ixgbe_ks;
320 
321 	/*
322 	 * Create and init kstat
323 	 */
324 	ks = kstat_create(MODULE_NAME, ddi_get_instance(ixgbe->dip),
325 	    "statistics", "net", KSTAT_TYPE_NAMED,
326 	    sizeof (ixgbe_stat_t) / sizeof (kstat_named_t), 0);
327 
328 	if (ks == NULL) {
329 		ixgbe_error(ixgbe,
330 		    "Could not create kernel statistics");
331 		return (IXGBE_FAILURE);
332 	}
333 
334 	ixgbe->ixgbe_ks = ks;
335 
336 	ixgbe_ks = (ixgbe_stat_t *)ks->ks_data;
337 
338 	/*
339 	 * Initialize all the statistics.
340 	 */
341 	kstat_named_init(&ixgbe_ks->link_speed, "link_speed",
342 	    KSTAT_DATA_UINT64);
343 	kstat_named_init(&ixgbe_ks->reset_count, "reset_count",
344 	    KSTAT_DATA_UINT64);
345 
346 	kstat_named_init(&ixgbe_ks->rx_frame_error, "rx_frame_error",
347 	    KSTAT_DATA_UINT64);
348 	kstat_named_init(&ixgbe_ks->rx_cksum_error, "rx_cksum_error",
349 	    KSTAT_DATA_UINT64);
350 	kstat_named_init(&ixgbe_ks->rx_exceed_pkt, "rx_exceed_pkt",
351 	    KSTAT_DATA_UINT64);
352 	kstat_named_init(&ixgbe_ks->tx_overload, "tx_overload",
353 	    KSTAT_DATA_UINT64);
354 	kstat_named_init(&ixgbe_ks->tx_fail_no_tbd, "tx_fail_no_tbd",
355 	    KSTAT_DATA_UINT64);
356 	kstat_named_init(&ixgbe_ks->tx_fail_no_tcb, "tx_fail_no_tcb",
357 	    KSTAT_DATA_UINT64);
358 	kstat_named_init(&ixgbe_ks->tx_fail_dma_bind, "tx_fail_dma_bind",
359 	    KSTAT_DATA_UINT64);
360 	kstat_named_init(&ixgbe_ks->tx_reschedule, "tx_reschedule",
361 	    KSTAT_DATA_UINT64);
362 	kstat_named_init(&ixgbe_ks->tx_break_tbd_limit, "tx_break_tbd_limit",
363 	    KSTAT_DATA_UINT64);
364 	kstat_named_init(&ixgbe_ks->tx_lso_header_fail, "tx_lso_header_fail",
365 	    KSTAT_DATA_UINT64);
366 
367 	kstat_named_init(&ixgbe_ks->gprc, "good_pkts_recvd",
368 	    KSTAT_DATA_UINT64);
369 	kstat_named_init(&ixgbe_ks->gptc, "good_pkts_xmitd",
370 	    KSTAT_DATA_UINT64);
371 	kstat_named_init(&ixgbe_ks->gor, "good_octets_recvd",
372 	    KSTAT_DATA_UINT64);
373 	kstat_named_init(&ixgbe_ks->got, "good_octets_xmitd",
374 	    KSTAT_DATA_UINT64);
375 	kstat_named_init(&ixgbe_ks->qor, "queue_octets_recvd",
376 	    KSTAT_DATA_UINT64);
377 	kstat_named_init(&ixgbe_ks->qot, "queue_octets_xmitd",
378 	    KSTAT_DATA_UINT64);
379 	kstat_named_init(&ixgbe_ks->qpr, "queue_pkts_recvd",
380 	    KSTAT_DATA_UINT64);
381 	kstat_named_init(&ixgbe_ks->qpt, "queue_pkts_xmitd",
382 	    KSTAT_DATA_UINT64);
383 	kstat_named_init(&ixgbe_ks->prc64, "pkts_recvd_(  64b)",
384 	    KSTAT_DATA_UINT64);
385 	kstat_named_init(&ixgbe_ks->prc127, "pkts_recvd_(  65- 127b)",
386 	    KSTAT_DATA_UINT64);
387 	kstat_named_init(&ixgbe_ks->prc255, "pkts_recvd_( 127- 255b)",
388 	    KSTAT_DATA_UINT64);
389 	kstat_named_init(&ixgbe_ks->prc511, "pkts_recvd_( 256- 511b)",
390 	    KSTAT_DATA_UINT64);
391 	kstat_named_init(&ixgbe_ks->prc1023, "pkts_recvd_( 511-1023b)",
392 	    KSTAT_DATA_UINT64);
393 	kstat_named_init(&ixgbe_ks->prc1522, "pkts_recvd_(1024-1522b)",
394 	    KSTAT_DATA_UINT64);
395 	kstat_named_init(&ixgbe_ks->ptc64, "pkts_xmitd_(  64b)",
396 	    KSTAT_DATA_UINT64);
397 	kstat_named_init(&ixgbe_ks->ptc127, "pkts_xmitd_(  65- 127b)",
398 	    KSTAT_DATA_UINT64);
399 	kstat_named_init(&ixgbe_ks->ptc255, "pkts_xmitd_( 128- 255b)",
400 	    KSTAT_DATA_UINT64);
401 	kstat_named_init(&ixgbe_ks->ptc511, "pkts_xmitd_( 255- 511b)",
402 	    KSTAT_DATA_UINT64);
403 	kstat_named_init(&ixgbe_ks->ptc1023, "pkts_xmitd_( 512-1023b)",
404 	    KSTAT_DATA_UINT64);
405 	kstat_named_init(&ixgbe_ks->ptc1522, "pkts_xmitd_(1024-1522b)",
406 	    KSTAT_DATA_UINT64);
407 
408 	kstat_named_init(&ixgbe_ks->mspdc, "mac_short_packet_discard",
409 	    KSTAT_DATA_UINT64);
410 	kstat_named_init(&ixgbe_ks->mpc, "missed_packets",
411 	    KSTAT_DATA_UINT64);
412 	kstat_named_init(&ixgbe_ks->mlfc, "mac_local_fault",
413 	    KSTAT_DATA_UINT64);
414 	kstat_named_init(&ixgbe_ks->mrfc, "mac_remote_fault",
415 	    KSTAT_DATA_UINT64);
416 	kstat_named_init(&ixgbe_ks->rlec, "recv_length_err",
417 	    KSTAT_DATA_UINT64);
418 	kstat_named_init(&ixgbe_ks->lxontxc, "link_xon_xmitd",
419 	    KSTAT_DATA_UINT64);
420 	kstat_named_init(&ixgbe_ks->lxonrxc, "link_xon_recvd",
421 	    KSTAT_DATA_UINT64);
422 	kstat_named_init(&ixgbe_ks->lxofftxc, "link_xoff_xmitd",
423 	    KSTAT_DATA_UINT64);
424 	kstat_named_init(&ixgbe_ks->lxoffrxc, "link_xoff_recvd",
425 	    KSTAT_DATA_UINT64);
426 	kstat_named_init(&ixgbe_ks->ruc, "recv_undersize",
427 	    KSTAT_DATA_UINT64);
428 	kstat_named_init(&ixgbe_ks->rfc, "recv_fragment",
429 	    KSTAT_DATA_UINT64);
430 	kstat_named_init(&ixgbe_ks->roc, "recv_oversize",
431 	    KSTAT_DATA_UINT64);
432 	kstat_named_init(&ixgbe_ks->rjc, "recv_jabber",
433 	    KSTAT_DATA_UINT64);
434 	kstat_named_init(&ixgbe_ks->rnbc, "recv_no_buffer",
435 	    KSTAT_DATA_UINT64);
436 	kstat_named_init(&ixgbe_ks->lroc, "lro_pkt_count",
437 	    KSTAT_DATA_UINT64);
438 
439 	kstat_named_init(&ixgbe_ks->dev_gone, "device_gone",
440 	    KSTAT_DATA_UINT64);
441 	/*
442 	 * Function to provide kernel stat update on demand
443 	 */
444 	ks->ks_update = ixgbe_update_stats;
445 
446 	ks->ks_private = (void *)ixgbe;
447 
448 	/*
449 	 * Add kstat to systems kstat chain
450 	 */
451 	kstat_install(ks);
452 
453 	return (IXGBE_SUCCESS);
454 }
455 
456 /*
457  * Retrieve a value for one of the statistics.
458  */
459 int
460 ixgbe_m_stat(void *arg, uint_t stat, uint64_t *val)
461 {
462 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
463 	struct ixgbe_hw *hw = &ixgbe->hw;
464 	ixgbe_stat_t *ixgbe_ks;
465 	int i;
466 	ixgbe_link_speed speeds = 0;
467 
468 	ixgbe_ks = (ixgbe_stat_t *)ixgbe->ixgbe_ks->ks_data;
469 
470 	mutex_enter(&ixgbe->gen_lock);
471 
472 	/*
473 	 * We cannot always rely on the common code maintaining
474 	 * hw->phy.speeds_supported, therefore we fall back to use the recorded
475 	 * supported speeds which were obtained during instance init in
476 	 * ixgbe_init_params().
477 	 */
478 	speeds = hw->phy.speeds_supported;
479 	if (speeds == 0)
480 		speeds = ixgbe->speeds_supported;
481 
482 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
483 		mutex_exit(&ixgbe->gen_lock);
484 		return (ECANCELED);
485 	}
486 
487 	switch (stat) {
488 	case MAC_STAT_IFSPEED:
489 		*val = ixgbe->link_speed * 1000000ull;
490 		break;
491 
492 	case MAC_STAT_MULTIRCV:
493 		ixgbe_ks->mprc.value.ui64 +=
494 		    IXGBE_READ_REG(hw, IXGBE_MPRC);
495 		*val = ixgbe_ks->mprc.value.ui64;
496 		break;
497 
498 	case MAC_STAT_BRDCSTRCV:
499 		ixgbe_ks->bprc.value.ui64 +=
500 		    IXGBE_READ_REG(hw, IXGBE_BPRC);
501 		*val = ixgbe_ks->bprc.value.ui64;
502 		break;
503 
504 	case MAC_STAT_MULTIXMT:
505 		ixgbe_ks->mptc.value.ui64 +=
506 		    IXGBE_READ_REG(hw, IXGBE_MPTC);
507 		*val = ixgbe_ks->mptc.value.ui64;
508 		break;
509 
510 	case MAC_STAT_BRDCSTXMT:
511 		ixgbe_ks->bptc.value.ui64 +=
512 		    IXGBE_READ_REG(hw, IXGBE_BPTC);
513 		*val = ixgbe_ks->bptc.value.ui64;
514 		break;
515 
516 	case MAC_STAT_NORCVBUF:
517 		/*
518 		 * The QPRDC[0] register maps to the same kstat as the
519 		 * old RNBC register because they have equivalent
520 		 * semantics.
521 		 */
522 		if (hw->mac.type == ixgbe_mac_82598EB) {
523 			for (i = 0; i < 8; i++) {
524 				ixgbe_ks->rnbc.value.ui64 +=
525 				    IXGBE_READ_REG(hw, IXGBE_RNBC(i));
526 			}
527 		} else {
528 			ixgbe_ks->rnbc.value.ui64 +=
529 			    IXGBE_READ_REG(hw, IXGBE_QPRDC(0));
530 		}
531 
532 		*val = ixgbe_ks->rnbc.value.ui64;
533 		break;
534 
535 	case MAC_STAT_IERRORS:
536 		ixgbe_ks->crcerrs.value.ui64 +=
537 		    IXGBE_READ_REG(hw, IXGBE_CRCERRS);
538 		ixgbe_ks->illerrc.value.ui64 +=
539 		    IXGBE_READ_REG(hw, IXGBE_ILLERRC);
540 		ixgbe_ks->errbc.value.ui64 +=
541 		    IXGBE_READ_REG(hw, IXGBE_ERRBC);
542 		ixgbe_ks->rlec.value.ui64 +=
543 		    IXGBE_READ_REG(hw, IXGBE_RLEC);
544 		*val = ixgbe_ks->crcerrs.value.ui64 +
545 		    ixgbe_ks->illerrc.value.ui64 +
546 		    ixgbe_ks->errbc.value.ui64 +
547 		    ixgbe_ks->rlec.value.ui64;
548 		break;
549 
550 	case MAC_STAT_RBYTES:
551 		ixgbe_ks->tor.value.ui64 += ixgbe_read_tor_value(hw);
552 		*val = ixgbe_ks->tor.value.ui64;
553 		break;
554 
555 	case MAC_STAT_OBYTES:
556 		/*
557 		 * The controller does not provide a Total Octets
558 		 * Transmitted statistic. The closest thing we have is
559 		 * Good Octets Transmitted. This makes sense, as what
560 		 * does it mean to transmit a packet if it didn't
561 		 * actually transmit.
562 		 */
563 		ixgbe_ks->got.value.ui64 += ixgbe_read_got_value(hw);
564 		ixgbe_ks->tot.value.ui64 = ixgbe_ks->got.value.ui64;
565 		*val = ixgbe_ks->tot.value.ui64;
566 		break;
567 
568 	case MAC_STAT_IPACKETS:
569 		ixgbe_ks->tpr.value.ui64 +=
570 		    IXGBE_READ_REG(hw, IXGBE_TPR);
571 		*val = ixgbe_ks->tpr.value.ui64;
572 		break;
573 
574 	case MAC_STAT_OPACKETS:
575 		ixgbe_ks->tpt.value.ui64 +=
576 		    IXGBE_READ_REG(hw, IXGBE_TPT);
577 		*val = ixgbe_ks->tpt.value.ui64;
578 		break;
579 
580 	/* RFC 1643 stats */
581 	case ETHER_STAT_FCS_ERRORS:
582 		ixgbe_ks->crcerrs.value.ui64 +=
583 		    IXGBE_READ_REG(hw, IXGBE_CRCERRS);
584 		*val = ixgbe_ks->crcerrs.value.ui64;
585 		break;
586 
587 	case ETHER_STAT_TOOLONG_ERRORS:
588 		ixgbe_ks->roc.value.ui64 +=
589 		    IXGBE_READ_REG(hw, IXGBE_ROC);
590 		*val = ixgbe_ks->roc.value.ui64;
591 		break;
592 
593 	case ETHER_STAT_MACRCV_ERRORS:
594 		ixgbe_ks->crcerrs.value.ui64 +=
595 		    IXGBE_READ_REG(hw, IXGBE_CRCERRS);
596 		ixgbe_ks->illerrc.value.ui64 +=
597 		    IXGBE_READ_REG(hw, IXGBE_ILLERRC);
598 		ixgbe_ks->errbc.value.ui64 +=
599 		    IXGBE_READ_REG(hw, IXGBE_ERRBC);
600 		ixgbe_ks->rlec.value.ui64 +=
601 		    IXGBE_READ_REG(hw, IXGBE_RLEC);
602 		*val = ixgbe_ks->crcerrs.value.ui64 +
603 		    ixgbe_ks->illerrc.value.ui64 +
604 		    ixgbe_ks->errbc.value.ui64 +
605 		    ixgbe_ks->rlec.value.ui64;
606 		break;
607 
608 	/* MII/GMII stats */
609 	case ETHER_STAT_XCVR_ADDR:
610 		/* The Internal PHY's MDI address for each MAC is 1 */
611 		*val = 1;
612 		break;
613 
614 	case ETHER_STAT_XCVR_ID:
615 		*val = hw->phy.id;
616 		break;
617 
618 	case ETHER_STAT_XCVR_INUSE:
619 		switch (ixgbe->link_speed) {
620 		case IXGBE_LINK_SPEED_1GB_FULL:
621 			*val =
622 			    (hw->phy.media_type == ixgbe_media_type_copper) ?
623 			    XCVR_1000T : XCVR_1000X;
624 			break;
625 		case IXGBE_LINK_SPEED_100_FULL:
626 			*val = (hw->phy.media_type == ixgbe_media_type_copper) ?
627 			    XCVR_100T2 : XCVR_100X;
628 			break;
629 		default:
630 			*val = XCVR_NONE;
631 			break;
632 		}
633 		break;
634 
635 	case ETHER_STAT_CAP_10GFDX:
636 		*val = (speeds & IXGBE_LINK_SPEED_10GB_FULL) ? 1 : 0;
637 		break;
638 
639 	case ETHER_STAT_CAP_5000FDX:
640 		*val = (speeds & IXGBE_LINK_SPEED_5GB_FULL) ? 1 : 0;
641 		break;
642 
643 	case ETHER_STAT_CAP_2500FDX:
644 		*val = (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) ? 1 : 0;
645 		break;
646 
647 	case ETHER_STAT_CAP_1000FDX:
648 		*val = (speeds & IXGBE_LINK_SPEED_1GB_FULL) ? 1 : 0;
649 		break;
650 
651 	case ETHER_STAT_CAP_100FDX:
652 		*val = (speeds & IXGBE_LINK_SPEED_100_FULL) ? 1 : 0;
653 		break;
654 
655 	case ETHER_STAT_CAP_ASMPAUSE:
656 		*val = ixgbe->param_asym_pause_cap;
657 		break;
658 
659 	case ETHER_STAT_CAP_PAUSE:
660 		*val = ixgbe->param_pause_cap;
661 		break;
662 
663 	case ETHER_STAT_CAP_AUTONEG:
664 		*val = 1;
665 		break;
666 
667 	case ETHER_STAT_ADV_CAP_10GFDX:
668 		*val = ixgbe->param_adv_10000fdx_cap;
669 		break;
670 
671 	case ETHER_STAT_ADV_CAP_5000FDX:
672 		*val = ixgbe->param_adv_5000fdx_cap;
673 		break;
674 
675 	case ETHER_STAT_ADV_CAP_2500FDX:
676 		*val = ixgbe->param_adv_2500fdx_cap;
677 		break;
678 
679 	case ETHER_STAT_ADV_CAP_1000FDX:
680 		*val = ixgbe->param_adv_1000fdx_cap;
681 		break;
682 
683 	case ETHER_STAT_ADV_CAP_100FDX:
684 		*val = ixgbe->param_adv_100fdx_cap;
685 		break;
686 
687 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
688 		*val = ixgbe->param_adv_asym_pause_cap;
689 		break;
690 
691 	case ETHER_STAT_ADV_CAP_PAUSE:
692 		*val = ixgbe->param_adv_pause_cap;
693 		break;
694 
695 	case ETHER_STAT_ADV_CAP_AUTONEG:
696 		*val = ixgbe->param_adv_autoneg_cap;
697 		break;
698 
699 	case ETHER_STAT_LP_CAP_10GFDX:
700 		*val = ixgbe->param_lp_10000fdx_cap;
701 		break;
702 
703 	case ETHER_STAT_LP_CAP_5000FDX:
704 		*val = ixgbe->param_lp_5000fdx_cap;
705 		break;
706 
707 	case ETHER_STAT_LP_CAP_2500FDX:
708 		*val = ixgbe->param_lp_2500fdx_cap;
709 		break;
710 
711 	case ETHER_STAT_LP_CAP_1000FDX:
712 		*val = ixgbe->param_lp_1000fdx_cap;
713 		break;
714 
715 	case ETHER_STAT_LP_CAP_100FDX:
716 		*val = ixgbe->param_lp_100fdx_cap;
717 		break;
718 
719 	case ETHER_STAT_LP_CAP_ASMPAUSE:
720 		*val = ixgbe->param_lp_asym_pause_cap;
721 		break;
722 
723 	case ETHER_STAT_LP_CAP_PAUSE:
724 		*val = ixgbe->param_lp_pause_cap;
725 		break;
726 
727 	case ETHER_STAT_LP_CAP_AUTONEG:
728 		*val = ixgbe->param_lp_autoneg_cap;
729 		break;
730 
731 	case ETHER_STAT_LINK_ASMPAUSE:
732 		*val = ixgbe->param_asym_pause_cap;
733 		break;
734 
735 	case ETHER_STAT_LINK_PAUSE:
736 		*val = ixgbe->param_pause_cap;
737 		break;
738 
739 	case ETHER_STAT_LINK_AUTONEG:
740 		*val = ixgbe->param_adv_autoneg_cap;
741 		break;
742 
743 	case ETHER_STAT_LINK_DUPLEX:
744 		*val = ixgbe->link_duplex;
745 		break;
746 
747 	case ETHER_STAT_TOOSHORT_ERRORS:
748 		ixgbe_ks->ruc.value.ui64 +=
749 		    IXGBE_READ_REG(hw, IXGBE_RUC);
750 		*val = ixgbe_ks->ruc.value.ui64;
751 		break;
752 
753 	case ETHER_STAT_CAP_REMFAULT:
754 		*val = ixgbe->param_rem_fault;
755 		break;
756 
757 	case ETHER_STAT_ADV_REMFAULT:
758 		*val = ixgbe->param_adv_rem_fault;
759 		break;
760 
761 	case ETHER_STAT_LP_REMFAULT:
762 		*val = ixgbe->param_lp_rem_fault;
763 		break;
764 
765 	case ETHER_STAT_JABBER_ERRORS:
766 		ixgbe_ks->rjc.value.ui64 +=
767 		    IXGBE_READ_REG(hw, IXGBE_RJC);
768 		*val = ixgbe_ks->rjc.value.ui64;
769 		break;
770 
771 	default:
772 		mutex_exit(&ixgbe->gen_lock);
773 		return (ENOTSUP);
774 	}
775 
776 	mutex_exit(&ixgbe->gen_lock);
777 
778 	if (ixgbe_check_acc_handle(ixgbe->osdep.reg_handle) != DDI_FM_OK) {
779 		ddi_fm_service_impact(ixgbe->dip, DDI_SERVICE_DEGRADED);
780 		return (EIO);
781 	}
782 
783 	return (0);
784 }
785 
786 /*
787  * Retrieve a value for one of the statistics for a particular rx ring
788  */
789 int
790 ixgbe_rx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
791 {
792 	ixgbe_rx_ring_t	*rx_ring = (ixgbe_rx_ring_t *)rh;
793 	ixgbe_t *ixgbe = rx_ring->ixgbe;
794 
795 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
796 		return (ECANCELED);
797 	}
798 
799 	switch (stat) {
800 	case MAC_STAT_RBYTES:
801 		*val = rx_ring->stat_rbytes;
802 		break;
803 
804 	case MAC_STAT_IPACKETS:
805 		*val = rx_ring->stat_ipackets;
806 		break;
807 
808 	default:
809 		*val = 0;
810 		return (ENOTSUP);
811 	}
812 
813 	return (0);
814 }
815 
816 /*
817  * Retrieve a value for one of the statistics for a particular tx ring
818  */
819 int
820 ixgbe_tx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
821 {
822 	ixgbe_tx_ring_t	*tx_ring = (ixgbe_tx_ring_t *)rh;
823 	ixgbe_t *ixgbe = tx_ring->ixgbe;
824 
825 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
826 		return (ECANCELED);
827 	}
828 
829 	switch (stat) {
830 	case MAC_STAT_OBYTES:
831 		*val = tx_ring->stat_obytes;
832 		break;
833 
834 	case MAC_STAT_OPACKETS:
835 		*val = tx_ring->stat_opackets;
836 		break;
837 
838 	default:
839 		*val = 0;
840 		return (ENOTSUP);
841 	}
842 
843 	return (0);
844 }
845