xref: /illumos-gate/usr/src/uts/common/io/igb/igb_stat.c (revision fa4e188e)
1c869993eSxy /*
2c869993eSxy  * CDDL HEADER START
3c869993eSxy  *
4b8d0a377Schenlu chen - Sun Microsystems - Beijing China  * Copyright(c) 2007-2009 Intel Corporation. All rights reserved.
5c869993eSxy  * The contents of this file are subject to the terms of the
6c869993eSxy  * Common Development and Distribution License (the "License").
7c869993eSxy  * You may not use this file except in compliance with the License.
8c869993eSxy  *
90dc2366fSVenugopal Iyer  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100dc2366fSVenugopal Iyer  * or http://www.opensolaris.org/os/licensing.
11c869993eSxy  * See the License for the specific language governing permissions
12c869993eSxy  * and limitations under the License.
13c869993eSxy  *
140dc2366fSVenugopal Iyer  * When distributing Covered Code, include this CDDL HEADER in each
150dc2366fSVenugopal Iyer  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16c869993eSxy  * If applicable, add the following below this CDDL HEADER, with the
17c869993eSxy  * fields enclosed by brackets "[]" replaced with your own identifying
18c869993eSxy  * information: Portions Copyright [yyyy] [name of copyright owner]
19c869993eSxy  *
20c869993eSxy  * CDDL HEADER END
21c869993eSxy  */
22c869993eSxy 
23c869993eSxy /*
240dc2366fSVenugopal Iyer  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
250dc2366fSVenugopal Iyer  * Use is subject to license terms.
26c869993eSxy  */
2713485e69SGarrett D'Amore /*
2813485e69SGarrett D'Amore  * Copyright 2014 Pluribus Networks Inc.
2913485e69SGarrett D'Amore  */
30c869993eSxy 
31c869993eSxy #include "igb_sw.h"
32c869993eSxy 
33c869993eSxy /*
34c869993eSxy  * Update driver private statistics.
35c869993eSxy  */
36c869993eSxy static int
igb_update_stats(kstat_t * ks,int rw)37c869993eSxy igb_update_stats(kstat_t *ks, int rw)
38c869993eSxy {
39c869993eSxy 	igb_t *igb;
40c869993eSxy 	struct e1000_hw *hw;
41c869993eSxy 	igb_stat_t *igb_ks;
42c869993eSxy 	uint32_t val_low, val_high;
43c869993eSxy #ifdef IGB_DEBUG
44c869993eSxy 	int i;
45c869993eSxy #endif
46c869993eSxy 
47c869993eSxy 	if (rw == KSTAT_WRITE)
48c869993eSxy 		return (EACCES);
49c869993eSxy 
50c869993eSxy 	igb = (igb_t *)ks->ks_private;
51c869993eSxy 	igb_ks = (igb_stat_t *)ks->ks_data;
52c869993eSxy 	hw = &igb->hw;
53c869993eSxy 
54c869993eSxy 	mutex_enter(&igb->gen_lock);
55c869993eSxy 
56c869993eSxy 	/*
57c869993eSxy 	 * Basic information.
58c869993eSxy 	 */
59c869993eSxy 	igb_ks->reset_count.value.ui64 = igb->reset_count;
60b8d0a377Schenlu chen - Sun Microsystems - Beijing China 	igb_ks->dout_sync.value.ui64 = igb->dout_sync;
61c869993eSxy 
62b8d0a377Schenlu chen - Sun Microsystems - Beijing China #ifdef IGB_DEBUG
63c869993eSxy 	igb_ks->rx_frame_error.value.ui64 = 0;
64c869993eSxy 	igb_ks->rx_cksum_error.value.ui64 = 0;
65c869993eSxy 	igb_ks->rx_exceed_pkt.value.ui64 = 0;
66c869993eSxy 	for (i = 0; i < igb->num_rx_rings; i++) {
67c869993eSxy 		igb_ks->rx_frame_error.value.ui64 +=
68c869993eSxy 		    igb->rx_rings[i].stat_frame_error;
69c869993eSxy 		igb_ks->rx_cksum_error.value.ui64 +=
70c869993eSxy 		    igb->rx_rings[i].stat_cksum_error;
71c869993eSxy 		igb_ks->rx_exceed_pkt.value.ui64 +=
72c869993eSxy 		    igb->rx_rings[i].stat_exceed_pkt;
73c869993eSxy 	}
74c869993eSxy 
75c869993eSxy 	igb_ks->tx_overload.value.ui64 = 0;
76c869993eSxy 	igb_ks->tx_fail_no_tbd.value.ui64 = 0;
77c869993eSxy 	igb_ks->tx_fail_no_tcb.value.ui64 = 0;
78c869993eSxy 	igb_ks->tx_fail_dma_bind.value.ui64 = 0;
79c869993eSxy 	igb_ks->tx_reschedule.value.ui64 = 0;
80c869993eSxy 	for (i = 0; i < igb->num_tx_rings; i++) {
81c869993eSxy 		igb_ks->tx_overload.value.ui64 +=
82c869993eSxy 		    igb->tx_rings[i].stat_overload;
83c869993eSxy 		igb_ks->tx_fail_no_tbd.value.ui64 +=
84c869993eSxy 		    igb->tx_rings[i].stat_fail_no_tbd;
85c869993eSxy 		igb_ks->tx_fail_no_tcb.value.ui64 +=
86c869993eSxy 		    igb->tx_rings[i].stat_fail_no_tcb;
87c869993eSxy 		igb_ks->tx_fail_dma_bind.value.ui64 +=
88c869993eSxy 		    igb->tx_rings[i].stat_fail_dma_bind;
89c869993eSxy 		igb_ks->tx_reschedule.value.ui64 +=
90c869993eSxy 		    igb->tx_rings[i].stat_reschedule;
91c869993eSxy 	}
92c869993eSxy 
93c869993eSxy 	/*
94c869993eSxy 	 * Hardware calculated statistics.
95c869993eSxy 	 */
96c869993eSxy 	igb_ks->gprc.value.ul += E1000_READ_REG(hw, E1000_GPRC);
97c869993eSxy 	igb_ks->gptc.value.ul += E1000_READ_REG(hw, E1000_GPTC);
98c869993eSxy 	igb_ks->prc64.value.ul += E1000_READ_REG(hw, E1000_PRC64);
99c869993eSxy 	igb_ks->prc127.value.ul += E1000_READ_REG(hw, E1000_PRC127);
100c869993eSxy 	igb_ks->prc255.value.ul += E1000_READ_REG(hw, E1000_PRC255);
101c869993eSxy 	igb_ks->prc511.value.ul += E1000_READ_REG(hw, E1000_PRC511);
102c869993eSxy 	igb_ks->prc1023.value.ul += E1000_READ_REG(hw, E1000_PRC1023);
103c869993eSxy 	igb_ks->prc1522.value.ul += E1000_READ_REG(hw, E1000_PRC1522);
104c869993eSxy 	igb_ks->ptc64.value.ul += E1000_READ_REG(hw, E1000_PTC64);
105c869993eSxy 	igb_ks->ptc127.value.ul += E1000_READ_REG(hw, E1000_PTC127);
106c869993eSxy 	igb_ks->ptc255.value.ul += E1000_READ_REG(hw, E1000_PTC255);
107c869993eSxy 	igb_ks->ptc511.value.ul += E1000_READ_REG(hw, E1000_PTC511);
108c869993eSxy 	igb_ks->ptc1023.value.ul += E1000_READ_REG(hw, E1000_PTC1023);
109c869993eSxy 	igb_ks->ptc1522.value.ul += E1000_READ_REG(hw, E1000_PTC1522);
110c869993eSxy 
111c869993eSxy 	/*
112c869993eSxy 	 * The 64-bit register will reset whenever the upper
113c869993eSxy 	 * 32 bits are read. So we need to read the lower
114c869993eSxy 	 * 32 bits first, then read the upper 32 bits.
115c869993eSxy 	 */
116c869993eSxy 	val_low = E1000_READ_REG(hw, E1000_GORCL);
117c869993eSxy 	val_high = E1000_READ_REG(hw, E1000_GORCH);
118c869993eSxy 	igb_ks->gor.value.ui64 += (uint64_t)val_high << 32 | (uint64_t)val_low;
119c869993eSxy 
120c869993eSxy 	val_low = E1000_READ_REG(hw, E1000_GOTCL);
121c869993eSxy 	val_high = E1000_READ_REG(hw, E1000_GOTCH);
122c869993eSxy 	igb_ks->got.value.ui64 += (uint64_t)val_high << 32 | (uint64_t)val_low;
123c869993eSxy #endif
124c869993eSxy 	igb_ks->symerrs.value.ui64 += E1000_READ_REG(hw, E1000_SYMERRS);
125c869993eSxy 	igb_ks->mpc.value.ui64 += E1000_READ_REG(hw, E1000_MPC);
126c869993eSxy 	igb_ks->rlec.value.ui64 += E1000_READ_REG(hw, E1000_RLEC);
127c869993eSxy 	igb_ks->fcruc.value.ui64 += E1000_READ_REG(hw, E1000_FCRUC);
128c869993eSxy 	igb_ks->rfc.value.ul += E1000_READ_REG(hw, E1000_RFC);
129c869993eSxy 	igb_ks->tncrs.value.ul += E1000_READ_REG(hw, E1000_TNCRS);
130c869993eSxy 	igb_ks->tsctc.value.ul += E1000_READ_REG(hw, E1000_TSCTC);
131c869993eSxy 	igb_ks->tsctfc.value.ul += E1000_READ_REG(hw, E1000_TSCTFC);
132c869993eSxy 	igb_ks->xonrxc.value.ui64 += E1000_READ_REG(hw, E1000_XONRXC);
133c869993eSxy 	igb_ks->xontxc.value.ui64 += E1000_READ_REG(hw, E1000_XONTXC);
134c869993eSxy 	igb_ks->xoffrxc.value.ui64 += E1000_READ_REG(hw, E1000_XOFFRXC);
135c869993eSxy 	igb_ks->xofftxc.value.ui64 += E1000_READ_REG(hw, E1000_XOFFTXC);
136c869993eSxy 
137c869993eSxy 	mutex_exit(&igb->gen_lock);
138c869993eSxy 
139cf8dcc9bSzhefeng xu - Sun Microsystems - Beijing China 	if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) {
140cf8dcc9bSzhefeng xu - Sun Microsystems - Beijing China 		ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED);
141cf8dcc9bSzhefeng xu - Sun Microsystems - Beijing China 		return (EIO);
142cf8dcc9bSzhefeng xu - Sun Microsystems - Beijing China 	}
1438bb4b220Sgl 
144c869993eSxy 	return (0);
145c869993eSxy }
146c869993eSxy 
147c869993eSxy /*
148c869993eSxy  * Create and initialize the driver private statistics.
149c869993eSxy  */
150c869993eSxy int
igb_init_stats(igb_t * igb)151c869993eSxy igb_init_stats(igb_t *igb)
152c869993eSxy {
153c869993eSxy 	kstat_t *ks;
154c869993eSxy 	igb_stat_t *igb_ks;
155c869993eSxy 
156c869993eSxy 	/*
157c869993eSxy 	 * Create and init kstat
158c869993eSxy 	 */
159c869993eSxy 	ks = kstat_create(MODULE_NAME, ddi_get_instance(igb->dip),
160c869993eSxy 	    "statistics", "net", KSTAT_TYPE_NAMED,
161c869993eSxy 	    sizeof (igb_stat_t) / sizeof (kstat_named_t), 0);
162c869993eSxy 
163c869993eSxy 	if (ks == NULL) {
164*fa4e188eSYuri Pankov 		igb_log(igb, IGB_LOG_ERROR,
165c869993eSxy 		    "Could not create kernel statistics");
166c869993eSxy 		return (IGB_FAILURE);
167c869993eSxy 	}
168c869993eSxy 
169c869993eSxy 	igb->igb_ks = ks;
170c869993eSxy 
171c869993eSxy 	igb_ks = (igb_stat_t *)ks->ks_data;
172c869993eSxy 
173c869993eSxy 	/*
174c869993eSxy 	 * Initialize all the statistics.
175c869993eSxy 	 */
176c869993eSxy 	kstat_named_init(&igb_ks->reset_count, "reset_count",
177c869993eSxy 	    KSTAT_DATA_UINT64);
178b8d0a377Schenlu chen - Sun Microsystems - Beijing China 	kstat_named_init(&igb_ks->dout_sync, "DMA_out_sync",
179b8d0a377Schenlu chen - Sun Microsystems - Beijing China 	    KSTAT_DATA_UINT64);
180b8d0a377Schenlu chen - Sun Microsystems - Beijing China 
181b8d0a377Schenlu chen - Sun Microsystems - Beijing China #ifdef IGB_DEBUG
182c869993eSxy 	kstat_named_init(&igb_ks->rx_frame_error, "rx_frame_error",
183c869993eSxy 	    KSTAT_DATA_UINT64);
184c869993eSxy 	kstat_named_init(&igb_ks->rx_cksum_error, "rx_cksum_error",
185c869993eSxy 	    KSTAT_DATA_UINT64);
186c869993eSxy 	kstat_named_init(&igb_ks->rx_exceed_pkt, "rx_exceed_pkt",
187c869993eSxy 	    KSTAT_DATA_UINT64);
188c869993eSxy 	kstat_named_init(&igb_ks->tx_overload, "tx_overload",
189c869993eSxy 	    KSTAT_DATA_UINT64);
190c869993eSxy 	kstat_named_init(&igb_ks->tx_fail_no_tbd, "tx_fail_no_tbd",
191c869993eSxy 	    KSTAT_DATA_UINT64);
192c869993eSxy 	kstat_named_init(&igb_ks->tx_fail_no_tcb, "tx_fail_no_tcb",
193c869993eSxy 	    KSTAT_DATA_UINT64);
194c869993eSxy 	kstat_named_init(&igb_ks->tx_fail_dma_bind, "tx_fail_dma_bind",
195c869993eSxy 	    KSTAT_DATA_UINT64);
196c869993eSxy 	kstat_named_init(&igb_ks->tx_reschedule, "tx_reschedule",
197c869993eSxy 	    KSTAT_DATA_UINT64);
198c869993eSxy 
199c869993eSxy 	kstat_named_init(&igb_ks->gprc, "good_pkts_recvd",
200c869993eSxy 	    KSTAT_DATA_UINT64);
201c869993eSxy 	kstat_named_init(&igb_ks->gptc, "good_pkts_xmitd",
202c869993eSxy 	    KSTAT_DATA_UINT64);
203c869993eSxy 	kstat_named_init(&igb_ks->gor, "good_octets_recvd",
204c869993eSxy 	    KSTAT_DATA_UINT64);
205c869993eSxy 	kstat_named_init(&igb_ks->got, "good_octets_xmitd",
206c869993eSxy 	    KSTAT_DATA_UINT64);
207c869993eSxy 	kstat_named_init(&igb_ks->prc64, "pkts_recvd_(  64b)",
208c869993eSxy 	    KSTAT_DATA_UINT64);
209c869993eSxy 	kstat_named_init(&igb_ks->prc127, "pkts_recvd_(  65- 127b)",
210c869993eSxy 	    KSTAT_DATA_UINT64);
211c869993eSxy 	kstat_named_init(&igb_ks->prc255, "pkts_recvd_( 127- 255b)",
212c869993eSxy 	    KSTAT_DATA_UINT64);
213c869993eSxy 	kstat_named_init(&igb_ks->prc511, "pkts_recvd_( 256- 511b)",
214c869993eSxy 	    KSTAT_DATA_UINT64);
215c869993eSxy 	kstat_named_init(&igb_ks->prc1023, "pkts_recvd_( 511-1023b)",
216c869993eSxy 	    KSTAT_DATA_UINT64);
217c869993eSxy 	kstat_named_init(&igb_ks->prc1522, "pkts_recvd_(1024-1522b)",
218c869993eSxy 	    KSTAT_DATA_UINT64);
219c869993eSxy 	kstat_named_init(&igb_ks->ptc64, "pkts_xmitd_(  64b)",
220c869993eSxy 	    KSTAT_DATA_UINT64);
221c869993eSxy 	kstat_named_init(&igb_ks->ptc127, "pkts_xmitd_(  65- 127b)",
222c869993eSxy 	    KSTAT_DATA_UINT64);
223c869993eSxy 	kstat_named_init(&igb_ks->ptc255, "pkts_xmitd_( 128- 255b)",
224c869993eSxy 	    KSTAT_DATA_UINT64);
225c869993eSxy 	kstat_named_init(&igb_ks->ptc511, "pkts_xmitd_( 255- 511b)",
226c869993eSxy 	    KSTAT_DATA_UINT64);
227c869993eSxy 	kstat_named_init(&igb_ks->ptc1023, "pkts_xmitd_( 512-1023b)",
228c869993eSxy 	    KSTAT_DATA_UINT64);
229c869993eSxy 	kstat_named_init(&igb_ks->ptc1522, "pkts_xmitd_(1024-1522b)",
230c869993eSxy 	    KSTAT_DATA_UINT64);
231c869993eSxy #endif
232c869993eSxy 
233c869993eSxy 	kstat_named_init(&igb_ks->symerrs, "recv_symbol_errors",
234c869993eSxy 	    KSTAT_DATA_UINT64);
235c869993eSxy 	kstat_named_init(&igb_ks->mpc, "recv_missed_packets",
236c869993eSxy 	    KSTAT_DATA_UINT64);
237c869993eSxy 	kstat_named_init(&igb_ks->rlec, "recv_length_errors",
238c869993eSxy 	    KSTAT_DATA_UINT64);
239c869993eSxy 	kstat_named_init(&igb_ks->fcruc, "recv_unsupport_FC_pkts",
240c869993eSxy 	    KSTAT_DATA_UINT64);
241c869993eSxy 	kstat_named_init(&igb_ks->rfc, "recv_frag",
242c869993eSxy 	    KSTAT_DATA_UINT64);
243c869993eSxy 	kstat_named_init(&igb_ks->tncrs, "xmit_with_no_CRS",
244c869993eSxy 	    KSTAT_DATA_UINT64);
245c869993eSxy 	kstat_named_init(&igb_ks->tsctc, "xmit_TCP_seg_contexts",
246c869993eSxy 	    KSTAT_DATA_UINT64);
247c869993eSxy 	kstat_named_init(&igb_ks->tsctfc, "xmit_TCP_seg_contexts_fail",
248c869993eSxy 	    KSTAT_DATA_UINT64);
249c869993eSxy 	kstat_named_init(&igb_ks->xonrxc, "XONs_recvd",
250c869993eSxy 	    KSTAT_DATA_UINT64);
251c869993eSxy 	kstat_named_init(&igb_ks->xontxc, "XONs_xmitd",
252c869993eSxy 	    KSTAT_DATA_UINT64);
253c869993eSxy 	kstat_named_init(&igb_ks->xoffrxc, "XOFFs_recvd",
254c869993eSxy 	    KSTAT_DATA_UINT64);
255c869993eSxy 	kstat_named_init(&igb_ks->xofftxc, "XOFFs_xmitd",
256c869993eSxy 	    KSTAT_DATA_UINT64);
257c869993eSxy 
258c869993eSxy 	/*
259c869993eSxy 	 * Function to provide kernel stat update on demand
260c869993eSxy 	 */
261c869993eSxy 	ks->ks_update = igb_update_stats;
262c869993eSxy 
263c869993eSxy 	ks->ks_private = (void *)igb;
264c869993eSxy 
265c869993eSxy 	/*
266c869993eSxy 	 * Add kstat to systems kstat chain
267c869993eSxy 	 */
268c869993eSxy 	kstat_install(ks);
269c869993eSxy 
270c869993eSxy 	return (IGB_SUCCESS);
271c869993eSxy }
2720dc2366fSVenugopal Iyer 
2730dc2366fSVenugopal Iyer /*
2740dc2366fSVenugopal Iyer  * Retrieve a value for one of the statistics for a particular rx ring
2750dc2366fSVenugopal Iyer  */
2760dc2366fSVenugopal Iyer int
igb_rx_ring_stat(mac_ring_driver_t rh,uint_t stat,uint64_t * val)2770dc2366fSVenugopal Iyer igb_rx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
2780dc2366fSVenugopal Iyer {
2790dc2366fSVenugopal Iyer 	igb_rx_ring_t *rx_ring = (igb_rx_ring_t *)rh;
2800dc2366fSVenugopal Iyer 
2810dc2366fSVenugopal Iyer 	switch (stat) {
2820dc2366fSVenugopal Iyer 	case MAC_STAT_RBYTES:
2830dc2366fSVenugopal Iyer 		*val = rx_ring->rx_bytes;
2840dc2366fSVenugopal Iyer 		break;
2850dc2366fSVenugopal Iyer 
2860dc2366fSVenugopal Iyer 	case MAC_STAT_IPACKETS:
2870dc2366fSVenugopal Iyer 		*val = rx_ring->rx_pkts;
2880dc2366fSVenugopal Iyer 		break;
2890dc2366fSVenugopal Iyer 
2900dc2366fSVenugopal Iyer 	default:
2910dc2366fSVenugopal Iyer 		*val = 0;
2920dc2366fSVenugopal Iyer 		return (ENOTSUP);
2930dc2366fSVenugopal Iyer 	}
2940dc2366fSVenugopal Iyer 
2950dc2366fSVenugopal Iyer 	return (0);
2960dc2366fSVenugopal Iyer }
2970dc2366fSVenugopal Iyer 
2980dc2366fSVenugopal Iyer /*
2990dc2366fSVenugopal Iyer  * Retrieve a value for one of the statistics for a particular tx ring
3000dc2366fSVenugopal Iyer  */
3010dc2366fSVenugopal Iyer int
igb_tx_ring_stat(mac_ring_driver_t rh,uint_t stat,uint64_t * val)3020dc2366fSVenugopal Iyer igb_tx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
3030dc2366fSVenugopal Iyer {
3040dc2366fSVenugopal Iyer 	igb_tx_ring_t *tx_ring = (igb_tx_ring_t *)rh;
3050dc2366fSVenugopal Iyer 
3060dc2366fSVenugopal Iyer 	switch (stat) {
3070dc2366fSVenugopal Iyer 	case MAC_STAT_OBYTES:
3080dc2366fSVenugopal Iyer 		*val = tx_ring->tx_bytes;
3090dc2366fSVenugopal Iyer 		break;
3100dc2366fSVenugopal Iyer 
3110dc2366fSVenugopal Iyer 	case MAC_STAT_OPACKETS:
3120dc2366fSVenugopal Iyer 		*val = tx_ring->tx_pkts;
3130dc2366fSVenugopal Iyer 		break;
3140dc2366fSVenugopal Iyer 
3150dc2366fSVenugopal Iyer 	default:
3160dc2366fSVenugopal Iyer 		*val = 0;
3170dc2366fSVenugopal Iyer 		return (ENOTSUP);
3180dc2366fSVenugopal Iyer 	}
3190dc2366fSVenugopal Iyer 
3200dc2366fSVenugopal Iyer 	return (0);
3210dc2366fSVenugopal Iyer }
322