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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <hxge_impl.h>
27 #include <inet/mi.h>
28 #include <sys/cmn_err.h>
29 
30 #define	RDC_NAME_FORMAT1 "RDC_"
31 #define	TDC_NAME_FORMAT1 "TDC_"
32 #define	CH_NAME_FORMAT "%d"
33 
34 void
35 hxge_init_statsp(p_hxge_t hxgep)
36 {
37 	size_t stats_size;
38 
39 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "==> hxge_init_statsp"));
40 
41 	stats_size = sizeof (hxge_stats_t);
42 	hxgep->statsp = KMEM_ZALLOC(stats_size, KM_SLEEP);
43 	hxgep->statsp->stats_size = stats_size;
44 
45 	HXGE_DEBUG_MSG((hxgep, KST_CTL, " <== hxge_init_statsp"));
46 }
47 
48 typedef struct {
49 	uint8_t index;
50 	uint8_t type;
51 	char *name;
52 } hxge_kstat_index_t;
53 
54 typedef enum {
55 	RDC_STAT_PACKETS = 0,
56 	RDC_STAT_BYTES,
57 	RDC_STAT_ERRORS,
58 	RDC_STAT_JUMBO_PKTS,
59 	RDC_STAT_RCR_UNKNOWN_ERR,
60 	RDC_STAT_RCR_SHA_PAR_ERR,
61 	RDC_STAT_RBR_PRE_PAR_ERR,
62 	RDC_STAT_RBR_PRE_EMTY,
63 	RDC_STAT_RCR_SHADOW_FULL,
64 	RDC_STAT_RBR_TMOUT,
65 	RDC_STAT_PEU_RESP_ERR,
66 	RDC_STAT_CTRL_FIFO_ECC_ERR,
67 	RDC_STAT_DATA_FIFO_ECC_ERR,
68 	RDC_STAT_RCRFULL,
69 	RDC_STAT_RBR_EMPTY,
70 	RDC_STAT_RBR_EMPTY_FAIL,
71 	RDC_STAT_RBR_EMPTY_RESTORE,
72 	RDC_STAT_RBR_FULL,
73 	RDC_STAT_RCR_INVALIDS,
74 	RDC_STAT_RCRTO,
75 	RDC_STAT_RCRTHRES,
76 	RDC_STAT_PKT_DROP,
77 	RDC_STAT_END
78 } hxge_rdc_stat_index_t;
79 
80 hxge_kstat_index_t hxge_rdc_stats[] = {
81 	{RDC_STAT_PACKETS, KSTAT_DATA_UINT64, "rdc_packets"},
82 	{RDC_STAT_BYTES, KSTAT_DATA_UINT64, "rdc_bytes"},
83 	{RDC_STAT_ERRORS, KSTAT_DATA_ULONG, "rdc_errors"},
84 	{RDC_STAT_JUMBO_PKTS, KSTAT_DATA_ULONG, "rdc_jumbo_pkts"},
85 	{RDC_STAT_RCR_UNKNOWN_ERR, KSTAT_DATA_ULONG, "rdc_rcr_unknown_err"},
86 	{RDC_STAT_RCR_SHA_PAR_ERR, KSTAT_DATA_ULONG, "rdc_rcr_sha_par_err"},
87 	{RDC_STAT_RBR_PRE_PAR_ERR, KSTAT_DATA_ULONG, "rdc_rbr_pre_par_err"},
88 	{RDC_STAT_RBR_PRE_EMTY, KSTAT_DATA_ULONG, "rdc_rbr_pre_empty"},
89 	{RDC_STAT_RCR_SHADOW_FULL, KSTAT_DATA_ULONG, "rdc_rcr_shadow_full"},
90 	{RDC_STAT_RBR_TMOUT, KSTAT_DATA_ULONG, "rdc_rbr_tmout"},
91 	{RDC_STAT_PEU_RESP_ERR, KSTAT_DATA_ULONG, "peu_resp_err"},
92 	{RDC_STAT_CTRL_FIFO_ECC_ERR, KSTAT_DATA_ULONG, "ctrl_fifo_ecc_err"},
93 	{RDC_STAT_DATA_FIFO_ECC_ERR, KSTAT_DATA_ULONG, "data_fifo_ecc_err"},
94 	{RDC_STAT_RCRFULL, KSTAT_DATA_ULONG, "rdc_rcrfull"},
95 	{RDC_STAT_RBR_EMPTY, KSTAT_DATA_ULONG, "rdc_rbr_empty"},
96 	{RDC_STAT_RBR_EMPTY_FAIL, KSTAT_DATA_ULONG, "rdc_rbr_empty_fail"},
97 	{RDC_STAT_RBR_EMPTY_FAIL, KSTAT_DATA_ULONG, "rdc_rbr_empty_restore"},
98 	{RDC_STAT_RBR_FULL, KSTAT_DATA_ULONG, "rdc_rbrfull"},
99 	{RDC_STAT_RCR_INVALIDS, KSTAT_DATA_ULONG, "rdc_rcr_invalids"},
100 	{RDC_STAT_RCRTO, KSTAT_DATA_ULONG, "rdc_rcrto"},
101 	{RDC_STAT_RCRTHRES, KSTAT_DATA_ULONG, "rdc_rcrthres"},
102 	{RDC_STAT_PKT_DROP, KSTAT_DATA_ULONG, "rdc_pkt_drop"},
103 	{RDC_STAT_END, NULL, NULL}
104 };
105 
106 typedef enum {
107 	RDC_SYS_STAT_CTRL_FIFO_SEC = 0,
108 	RDC_SYS_STAT_CTRL_FIFO_DED,
109 	RDC_SYS_STAT_DATA_FIFO_SEC,
110 	RDC_SYS_STAT_DATA_FIFO_DED,
111 	RDC_SYS_STAT_END
112 } hxge_rdc_sys_stat_idx_t;
113 
114 hxge_kstat_index_t hxge_rdc_sys_stats[] = {
115 	{RDC_SYS_STAT_CTRL_FIFO_SEC, KSTAT_DATA_UINT64, "rdc_ctrl_fifo_sec"},
116 	{RDC_SYS_STAT_CTRL_FIFO_DED, KSTAT_DATA_UINT64, "rdc_ctrl_fifo_ded"},
117 	{RDC_SYS_STAT_DATA_FIFO_SEC, KSTAT_DATA_UINT64, "rdc_data_fifo_sec"},
118 	{RDC_SYS_STAT_DATA_FIFO_DED, KSTAT_DATA_UINT64, "tdc_data_fifo_ded"},
119 	{RDC_SYS_STAT_END, NULL, NULL}
120 };
121 
122 typedef enum {
123 	TDC_STAT_PACKETS = 0,
124 	TDC_STAT_BYTES,
125 	TDC_STAT_BYTES_WITH_PAD,
126 	TDC_STAT_ERRORS,
127 	TDC_STAT_TX_INITS,
128 	TDC_STAT_TX_NO_BUF,
129 	TDC_STAT_PEU_RESP_ERR,
130 	TDC_STAT_PKT_SIZE_ERR,
131 	TDC_STAT_TX_RNG_OFLOW,
132 	TDC_STAT_PKT_SIZE_HDR_ERR,
133 	TDC_STAT_RUNT_PKT_DROP_ERR,
134 	TDC_STAT_PREF_PAR_ERR,
135 	TDC_STAT_TDR_PREF_CPL_TO,
136 	TDC_STAT_PKT_CPL_TO,
137 	TDC_STAT_INVALID_SOP,
138 	TDC_STAT_UNEXPECTED_SOP,
139 	TDC_STAT_COUNT_HDR_SIZE_ERR,
140 	TDC_STAT_COUNT_RUNT,
141 	TDC_STAT_COUNT_ABORT,
142 	TDC_STAT_TX_STARTS,
143 	TDC_STAT_TX_NO_DESC,
144 	TDC_STAT_TX_DMA_BIND_FAIL,
145 	TDC_STAT_TX_HDR_PKTS,
146 	TDC_STAT_TX_DDI_PKTS,
147 	TDC_STAT_TX_JUMBO_PKTS,
148 	TDC_STAT_TX_MAX_PEND,
149 	TDC_STAT_TX_MARKS,
150 	TDC_STAT_END
151 } hxge_tdc_stats_index_t;
152 
153 hxge_kstat_index_t hxge_tdc_stats[] = {
154 	{TDC_STAT_PACKETS, KSTAT_DATA_UINT64, "tdc_packets"},
155 	{TDC_STAT_BYTES, KSTAT_DATA_UINT64, "tdc_bytes"},
156 	{TDC_STAT_BYTES_WITH_PAD, KSTAT_DATA_UINT64, "tdc_bytes_with_pad"},
157 	{TDC_STAT_ERRORS, KSTAT_DATA_UINT64, "tdc_errors"},
158 	{TDC_STAT_TX_INITS, KSTAT_DATA_ULONG, "tdc_tx_inits"},
159 	{TDC_STAT_TX_NO_BUF, KSTAT_DATA_ULONG, "tdc_tx_no_buf"},
160 
161 	{TDC_STAT_PEU_RESP_ERR, KSTAT_DATA_ULONG, "tdc_peu_resp_err"},
162 	{TDC_STAT_PKT_SIZE_ERR, KSTAT_DATA_ULONG, "tdc_pkt_size_err"},
163 	{TDC_STAT_TX_RNG_OFLOW, KSTAT_DATA_ULONG, "tdc_tx_rng_oflow"},
164 	{TDC_STAT_PKT_SIZE_HDR_ERR, KSTAT_DATA_ULONG, "tdc_pkt_size_hdr_err"},
165 	{TDC_STAT_RUNT_PKT_DROP_ERR, KSTAT_DATA_ULONG, "tdc_runt_pkt_drop_err"},
166 	{TDC_STAT_PREF_PAR_ERR, KSTAT_DATA_ULONG, "tdc_pref_par_err"},
167 	{TDC_STAT_TDR_PREF_CPL_TO, KSTAT_DATA_ULONG, "tdc_tdr_pref_cpl_to"},
168 	{TDC_STAT_PKT_CPL_TO, KSTAT_DATA_ULONG, "tdc_pkt_cpl_to"},
169 	{TDC_STAT_INVALID_SOP, KSTAT_DATA_ULONG, "tdc_invalid_sop"},
170 	{TDC_STAT_UNEXPECTED_SOP, KSTAT_DATA_ULONG, "tdc_unexpected_sop"},
171 
172 	{TDC_STAT_COUNT_HDR_SIZE_ERR, KSTAT_DATA_ULONG,
173 	    "tdc_count_hdr_size_err"},
174 	{TDC_STAT_COUNT_RUNT, KSTAT_DATA_ULONG, "tdc_count_runt"},
175 	{TDC_STAT_COUNT_ABORT, KSTAT_DATA_ULONG, "tdc_count_abort"},
176 
177 	{TDC_STAT_TX_STARTS, KSTAT_DATA_ULONG, "tdc_tx_starts"},
178 	{TDC_STAT_TX_NO_DESC, KSTAT_DATA_ULONG, "tdc_tx_no_desc"},
179 	{TDC_STAT_TX_DMA_BIND_FAIL, KSTAT_DATA_ULONG, "tdc_tx_dma_bind_fail"},
180 	{TDC_STAT_TX_HDR_PKTS, KSTAT_DATA_ULONG, "tdc_tx_hdr_pkts"},
181 	{TDC_STAT_TX_DDI_PKTS, KSTAT_DATA_ULONG, "tdc_tx_ddi_pkts"},
182 	{TDC_STAT_TX_JUMBO_PKTS, KSTAT_DATA_ULONG, "tdc_tx_jumbo_pkts"},
183 	{TDC_STAT_TX_MAX_PEND, KSTAT_DATA_ULONG, "tdc_tx_max_pend"},
184 	{TDC_STAT_TX_MARKS, KSTAT_DATA_ULONG, "tdc_tx_marks"},
185 	{TDC_STAT_END, NULL, NULL}
186 };
187 
188 typedef enum {
189 	REORD_TBL_PAR_ERR = 0,
190 	REORD_BUF_DED_ERR,
191 	REORD_BUF_SEC_ERR,
192 	TDC_SYS_STAT_END
193 } hxge_tdc_sys_stat_idx_t;
194 
195 hxge_kstat_index_t hxge_tdc_sys_stats[] = {
196 	{REORD_TBL_PAR_ERR, KSTAT_DATA_UINT64, "reord_tbl_par_err"},
197 	{REORD_BUF_DED_ERR, KSTAT_DATA_UINT64, "reord_buf_ded_err"},
198 	{REORD_BUF_SEC_ERR, KSTAT_DATA_UINT64, "reord_buf_sec_err"},
199 	{TDC_SYS_STAT_END, NULL, NULL}
200 };
201 
202 typedef enum {
203 	VMAC_STAT_TX_FRAME_CNT,		/* vmac_tx_frame_cnt_t */
204 	VMAC_STAT_TX_BYTE_CNT,		/* vmac_tx_byte_cnt_t */
205 
206 	VMAC_STAT_RX_FRAME_CNT,		/* vmac_rx_frame_cnt_t */
207 	VMAC_STAT_RX_BYTE_CNT,		/* vmac_rx_byte_cnt_t */
208 	VMAC_STAT_RX_DROP_FRAME_CNT,	/* vmac_rx_drop_fr_cnt_t */
209 	VMAC_STAT_RX_DROP_BYTE_CNT,	/* vmac_rx_drop_byte_cnt_t */
210 	VMAC_STAT_RX_CRC_CNT,		/* vmac_rx_crc_cnt_t */
211 	VMAC_STAT_RX_PAUSE_CNT,		/* vmac_rx_pause_cnt_t */
212 	VMAC_STAT_RX_BCAST_FR_CNT,	/* vmac_rx_bcast_fr_cnt_t */
213 	VMAC_STAT_RX_MCAST_FR_CNT,	/* vmac_rx_mcast_fr_cnt_t */
214 	VMAC_STAT_END
215 } hxge_vmac_stat_index_t;
216 
217 hxge_kstat_index_t hxge_vmac_stats[] = {
218 	{VMAC_STAT_TX_FRAME_CNT, KSTAT_DATA_UINT64, "vmac_tx_frame_cnt"},
219 	{VMAC_STAT_TX_BYTE_CNT, KSTAT_DATA_UINT64, "vmac_tx_byte_cnt"},
220 
221 	{VMAC_STAT_RX_FRAME_CNT, KSTAT_DATA_UINT64, "vmac_rx_frame_cnt"},
222 	{VMAC_STAT_RX_BYTE_CNT, KSTAT_DATA_UINT64, "vmac_rx_byte_cnt"},
223 	{VMAC_STAT_RX_DROP_FRAME_CNT, KSTAT_DATA_UINT64,
224 		"vmac_rx_drop_frame_cnt"},
225 	{VMAC_STAT_RX_DROP_BYTE_CNT, KSTAT_DATA_UINT64,
226 		"vmac_rx_drop_byte_cnt"},
227 	{VMAC_STAT_RX_CRC_CNT, KSTAT_DATA_UINT64, "vmac_rx_crc_cnt"},
228 	{VMAC_STAT_RX_PAUSE_CNT, KSTAT_DATA_UINT64, "vmac_rx_pause_cnt"},
229 	{VMAC_STAT_RX_BCAST_FR_CNT, KSTAT_DATA_UINT64, "vmac_rx_bcast_fr_cnt"},
230 	{VMAC_STAT_RX_MCAST_FR_CNT, KSTAT_DATA_UINT64, "vmac_rx_mcast_fr_cnt"},
231 	{VMAC_STAT_END, NULL, NULL}
232 };
233 
234 typedef enum {
235 	PFC_STAT_PKT_DROP,
236 	PFC_STAT_TCAM_PARITY_ERR,
237 	PFC_STAT_VLAN_PARITY_ERR,
238 	PFC_STAT_BAD_CS_COUNT,
239 	PFC_STAT_DROP_COUNT,
240 	PFC_STAT_TCP_CTRL_DROP,
241 	PFC_STAT_L2_ADDR_DROP,
242 	PFC_STAT_CLASS_CODE_DROP,
243 	PFC_STAT_TCAM_DROP,
244 	PFC_STAT_VLAN_DROP,
245 	PFC_STAT_END
246 } hxge_pfc_stat_index_t;
247 
248 hxge_kstat_index_t hxge_pfc_stats[] = {
249 	{PFC_STAT_PKT_DROP, KSTAT_DATA_ULONG, "pfc_pkt_drop"},
250 	{PFC_STAT_TCAM_PARITY_ERR, KSTAT_DATA_ULONG, "pfc_tcam_parity_err"},
251 	{PFC_STAT_VLAN_PARITY_ERR, KSTAT_DATA_ULONG, "pfc_vlan_parity_err"},
252 	{PFC_STAT_BAD_CS_COUNT, KSTAT_DATA_ULONG, "pfc_bad_cs_count"},
253 	{PFC_STAT_DROP_COUNT, KSTAT_DATA_ULONG, "pfc_drop_count"},
254 	{PFC_STAT_TCP_CTRL_DROP, KSTAT_DATA_ULONG, "  pfc_pkt_drop_tcp_ctrl"},
255 	{PFC_STAT_L2_ADDR_DROP, KSTAT_DATA_ULONG, "  pfc_pkt_drop_l2_addr"},
256 	{PFC_STAT_CLASS_CODE_DROP, KSTAT_DATA_ULONG,
257 	    "  pfc_pkt_drop_class_code"},
258 	{PFC_STAT_TCAM_DROP, KSTAT_DATA_ULONG, "  pfc_pkt_drop_tcam"},
259 	{PFC_STAT_VLAN_DROP, KSTAT_DATA_ULONG, "  pfc_pkt_drop_vlan"},
260 	{PFC_STAT_END, NULL, NULL}
261 };
262 
263 typedef enum {
264 	SPC_ACC_ERR = 0,
265 	TDC_PIOACC_ERR,
266 	RDC_PIOACC_ERR,
267 	PFC_PIOACC_ERR,
268 	VMAC_PIOACC_ERR,
269 	CPL_HDRQ_PARERR,
270 	CPL_DATAQ_PARERR,
271 	RETRYRAM_XDLH_PARERR,
272 	RETRYSOTRAM_XDLH_PARERR,
273 	P_HDRQ_PARERR,
274 	P_DATAQ_PARERR,
275 	NP_HDRQ_PARERR,
276 	NP_DATAQ_PARERR,
277 	EIC_MSIX_PARERR,
278 	HCR_PARERR,
279 	PEU_SYS_STAT_END
280 } hxge_peu_sys_stat_idx_t;
281 
282 hxge_kstat_index_t hxge_peu_sys_stats[] = {
283 	{SPC_ACC_ERR, KSTAT_DATA_UINT64, "spc_acc_err"},
284 	{TDC_PIOACC_ERR, KSTAT_DATA_UINT64, "tdc_pioacc_err"},
285 	{RDC_PIOACC_ERR, KSTAT_DATA_UINT64, "rdc_pioacc_err"},
286 	{PFC_PIOACC_ERR, KSTAT_DATA_UINT64, "pfc_pioacc_err"},
287 	{VMAC_PIOACC_ERR, KSTAT_DATA_UINT64, "vmac_pioacc_err"},
288 	{CPL_HDRQ_PARERR, KSTAT_DATA_UINT64, "cpl_hdrq_parerr"},
289 	{CPL_DATAQ_PARERR, KSTAT_DATA_UINT64, "cpl_dataq_parerr"},
290 	{RETRYRAM_XDLH_PARERR, KSTAT_DATA_UINT64, "retryram_xdlh_parerr"},
291 	{RETRYSOTRAM_XDLH_PARERR, KSTAT_DATA_UINT64, "retrysotram_xdlh_parerr"},
292 	{P_HDRQ_PARERR, KSTAT_DATA_UINT64, "p_hdrq_parerr"},
293 	{P_DATAQ_PARERR, KSTAT_DATA_UINT64, "p_dataq_parerr"},
294 	{NP_HDRQ_PARERR, KSTAT_DATA_UINT64, "np_hdrq_parerr"},
295 	{NP_DATAQ_PARERR, KSTAT_DATA_UINT64, "np_dataq_parerr"},
296 	{EIC_MSIX_PARERR, KSTAT_DATA_UINT64, "eic_msix_parerr"},
297 	{HCR_PARERR, KSTAT_DATA_UINT64, "hcr_parerr"},
298 	{TDC_SYS_STAT_END, NULL, NULL}
299 };
300 
301 /* ARGSUSED */
302 int
303 hxge_tdc_stat_update(kstat_t *ksp, int rw)
304 {
305 	p_hxge_t		hxgep;
306 	p_hxge_tdc_kstat_t	tdc_kstatsp;
307 	p_hxge_tx_ring_stats_t	statsp;
308 	int			channel;
309 	char			*ch_name, *end;
310 
311 	hxgep = (p_hxge_t)ksp->ks_private;
312 	if (hxgep == NULL)
313 		return (-1);
314 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "==> hxge_rxstat_update"));
315 
316 	ch_name = ksp->ks_name;
317 	ch_name += strlen(TDC_NAME_FORMAT1);
318 	channel = mi_strtol(ch_name, &end, 10);
319 
320 	tdc_kstatsp = (p_hxge_tdc_kstat_t)ksp->ks_data;
321 	statsp = (p_hxge_tx_ring_stats_t)&hxgep->statsp->tdc_stats[channel];
322 
323 	HXGE_DEBUG_MSG((hxgep, KST_CTL,
324 	    "hxge_tdc_stat_update data $%p statsp $%p channel %d",
325 	    ksp->ks_data, statsp, channel));
326 
327 	tdc_kstatsp->opackets.value.ull = statsp->opackets;
328 	tdc_kstatsp->obytes.value.ull = statsp->obytes;
329 	tdc_kstatsp->obytes_with_pad.value.ull = statsp->obytes_with_pad;
330 	tdc_kstatsp->oerrors.value.ull = statsp->oerrors;
331 	tdc_kstatsp->tx_hdr_pkts.value.ull = statsp->tx_hdr_pkts;
332 	tdc_kstatsp->tx_ddi_pkts.value.ull = statsp->tx_ddi_pkts;
333 	tdc_kstatsp->tx_jumbo_pkts.value.ull = statsp->tx_jumbo_pkts;
334 	tdc_kstatsp->tx_max_pend.value.ull = statsp->tx_max_pend;
335 	tdc_kstatsp->peu_resp_err.value.ul = statsp->peu_resp_err;
336 	tdc_kstatsp->pkt_size_err.value.ul = statsp->pkt_size_err;
337 	tdc_kstatsp->tx_rng_oflow.value.ul = statsp->tx_rng_oflow;
338 	tdc_kstatsp->pkt_size_hdr_err.value.ul = statsp->pkt_size_hdr_err;
339 	tdc_kstatsp->runt_pkt_drop_err.value.ul = statsp->runt_pkt_drop_err;
340 	tdc_kstatsp->pref_par_err.value.ul = statsp->pref_par_err;
341 	tdc_kstatsp->tdr_pref_cpl_to.value.ul = statsp->tdr_pref_cpl_to;
342 	tdc_kstatsp->pkt_cpl_to.value.ul = statsp->pkt_cpl_to;
343 	tdc_kstatsp->invalid_sop.value.ul = statsp->invalid_sop;
344 	tdc_kstatsp->unexpected_sop.value.ul = statsp->unexpected_sop;
345 	tdc_kstatsp->tx_starts.value.ul = statsp->tx_starts;
346 	tdc_kstatsp->tx_no_desc.value.ul = statsp->tx_no_desc;
347 	tdc_kstatsp->tx_dma_bind_fail.value.ul = statsp->tx_dma_bind_fail;
348 
349 	tdc_kstatsp->count_hdr_size_err.value.ul =
350 	    statsp->count_hdr_size_err;
351 	tdc_kstatsp->count_runt.value.ul = statsp->count_runt;
352 	tdc_kstatsp->count_abort.value.ul = statsp->count_abort;
353 	tdc_kstatsp->tx_marks.value.ul = statsp->tx_marks;
354 
355 	HXGE_DEBUG_MSG((hxgep, KST_CTL, " <== hxge_tdc_stat_update"));
356 	return (0);
357 }
358 
359 /* ARGSUSED */
360 int
361 hxge_tdc_sys_stat_update(kstat_t *ksp, int rw)
362 {
363 	p_hxge_t		hxgep;
364 	p_hxge_tdc_sys_kstat_t	tdc_sys_kstatsp;
365 	p_hxge_tdc_sys_stats_t	statsp;
366 
367 	hxgep = (p_hxge_t)ksp->ks_private;
368 	if (hxgep == NULL)
369 		return (-1);
370 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "==> hxge_tdc_sys_stat_update"));
371 
372 	tdc_sys_kstatsp = (p_hxge_tdc_sys_kstat_t)ksp->ks_data;
373 	statsp = (p_hxge_tdc_sys_stats_t)&hxgep->statsp->tdc_sys_stats;
374 
375 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "hxge_tdc_sys_stat_update %llx",
376 	    ksp->ks_data));
377 
378 	tdc_sys_kstatsp->reord_tbl_par_err.value.ul =
379 	    statsp->reord_tbl_par_err;
380 	tdc_sys_kstatsp->reord_buf_ded_err.value.ul =
381 	    statsp->reord_buf_ded_err;
382 	tdc_sys_kstatsp->reord_buf_sec_err.value.ul =
383 	    statsp->reord_buf_sec_err;
384 
385 	HXGE_DEBUG_MSG((hxgep, KST_CTL, " <== hxge_tdc_sys_stat_update"));
386 	return (0);
387 }
388 
389 /* ARGSUSED */
390 int
391 hxge_rdc_stat_update(kstat_t *ksp, int rw)
392 {
393 	p_hxge_t		hxgep;
394 	p_hxge_rdc_kstat_t	rdc_kstatsp;
395 	p_hxge_rx_ring_stats_t	statsp;
396 	int			channel;
397 	char			*ch_name, *end;
398 
399 	hxgep = (p_hxge_t)ksp->ks_private;
400 	if (hxgep == NULL)
401 		return (-1);
402 
403 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "==> hxge_rdc_stat_update"));
404 
405 	ch_name = ksp->ks_name;
406 	ch_name += strlen(RDC_NAME_FORMAT1);
407 	channel = mi_strtol(ch_name, &end, 10);
408 
409 	rdc_kstatsp = (p_hxge_rdc_kstat_t)ksp->ks_data;
410 	statsp = (p_hxge_rx_ring_stats_t)&hxgep->statsp->rdc_stats[channel];
411 
412 	HXGE_DEBUG_MSG((hxgep, KST_CTL,
413 	    "hxge_rdc_stat_update $%p statsp $%p channel %d",
414 	    ksp->ks_data, statsp, channel));
415 
416 	rdc_kstatsp->ipackets.value.ull = statsp->ipackets;
417 	rdc_kstatsp->rbytes.value.ull = statsp->ibytes;
418 	rdc_kstatsp->jumbo_pkts.value.ul = statsp->jumbo_pkts;
419 	rdc_kstatsp->rcr_unknown_err.value.ul = statsp->rcr_unknown_err;
420 	rdc_kstatsp->errors.value.ul = statsp->ierrors;
421 	rdc_kstatsp->rcr_sha_par_err.value.ul = statsp->rcr_sha_par;
422 	rdc_kstatsp->rbr_pre_par_err.value.ul = statsp->rbr_pre_par;
423 	rdc_kstatsp->rbr_pre_emty.value.ul = statsp->rbr_pre_empty;
424 	rdc_kstatsp->rcr_shadow_full.value.ul = statsp->rcr_shadow_full;
425 	rdc_kstatsp->rbr_tmout.value.ul = statsp->rbr_tmout;
426 	rdc_kstatsp->peu_resp_err.value.ul = statsp->peu_resp_err;
427 	rdc_kstatsp->ctrl_fifo_ecc_err.value.ul = statsp->ctrl_fifo_ecc_err;
428 	rdc_kstatsp->data_fifo_ecc_err.value.ul = statsp->data_fifo_ecc_err;
429 	rdc_kstatsp->rcrfull.value.ul = statsp->rcrfull;
430 	rdc_kstatsp->rbr_empty.value.ul = statsp->rbr_empty;
431 	rdc_kstatsp->rbr_empty_fail.value.ul = statsp->rbr_empty_fail;
432 	rdc_kstatsp->rbr_empty_restore.value.ul = statsp->rbr_empty_restore;
433 	rdc_kstatsp->rbrfull.value.ul = statsp->rbrfull;
434 	rdc_kstatsp->rcr_invalids.value.ul = statsp->rcr_invalids;
435 	rdc_kstatsp->rcr_to.value.ul = statsp->rcr_to;
436 	rdc_kstatsp->rcr_thresh.value.ul = statsp->rcr_thres;
437 	rdc_kstatsp->pkt_drop.value.ul = statsp->pkt_drop;
438 
439 	HXGE_DEBUG_MSG((hxgep, KST_CTL, " <== hxge_rdc_stat_update"));
440 	return (0);
441 }
442 
443 /* ARGSUSED */
444 int
445 hxge_rdc_sys_stat_update(kstat_t *ksp, int rw)
446 {
447 	p_hxge_t		hxgep;
448 	p_hxge_rdc_sys_kstat_t	rdc_sys_kstatsp;
449 	p_hxge_rdc_sys_stats_t	statsp;
450 
451 	hxgep = (p_hxge_t)ksp->ks_private;
452 	if (hxgep == NULL)
453 		return (-1);
454 
455 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "==> hxge_rdc_sys_stat_update"));
456 
457 	rdc_sys_kstatsp = (p_hxge_rdc_sys_kstat_t)ksp->ks_data;
458 	statsp = (p_hxge_rdc_sys_stats_t)&hxgep->statsp->rdc_sys_stats;
459 
460 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "hxge_rdc_sys_stat_update %llx",
461 	    ksp->ks_data));
462 
463 	rdc_sys_kstatsp->ctrl_fifo_sec.value.ul = statsp->ctrl_fifo_sec;
464 	rdc_sys_kstatsp->ctrl_fifo_ded.value.ul = statsp->ctrl_fifo_ded;
465 	rdc_sys_kstatsp->data_fifo_sec.value.ul = statsp->data_fifo_sec;
466 	rdc_sys_kstatsp->data_fifo_ded.value.ul = statsp->data_fifo_ded;
467 
468 	HXGE_DEBUG_MSG((hxgep, KST_CTL, " <== hxge_rdc_sys_stat_update"));
469 	return (0);
470 }
471 
472 /* ARGSUSED */
473 int
474 hxge_vmac_stat_update(kstat_t *ksp, int rw)
475 {
476 	p_hxge_t		hxgep;
477 	p_hxge_vmac_kstat_t	vmac_kstatsp;
478 	p_hxge_vmac_stats_t	statsp;
479 
480 	hxgep = (p_hxge_t)ksp->ks_private;
481 	if (hxgep == NULL)
482 		return (-1);
483 
484 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "==> hxge_vmac_stat_update"));
485 
486 	hxge_save_cntrs(hxgep);
487 
488 	vmac_kstatsp = (p_hxge_vmac_kstat_t)ksp->ks_data;
489 	statsp = (p_hxge_vmac_stats_t)&hxgep->statsp->vmac_stats;
490 
491 	vmac_kstatsp->tx_frame_cnt.value.ul = statsp->tx_frame_cnt;
492 	vmac_kstatsp->tx_byte_cnt.value.ul = statsp->tx_byte_cnt;
493 
494 	vmac_kstatsp->rx_frame_cnt.value.ul = statsp->rx_frame_cnt;
495 	vmac_kstatsp->rx_byte_cnt.value.ul = statsp->rx_byte_cnt;
496 	vmac_kstatsp->rx_drop_frame_cnt.value.ul = statsp->rx_drop_frame_cnt;
497 	vmac_kstatsp->rx_drop_byte_cnt.value.ul = statsp->rx_drop_byte_cnt;
498 	vmac_kstatsp->rx_crc_cnt.value.ul = statsp->rx_crc_cnt;
499 	vmac_kstatsp->rx_pause_cnt.value.ul = statsp->rx_pause_cnt;
500 	vmac_kstatsp->rx_bcast_fr_cnt.value.ul = statsp->rx_bcast_fr_cnt;
501 	vmac_kstatsp->rx_mcast_fr_cnt.value.ul = statsp->rx_mcast_fr_cnt;
502 
503 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "<== hxge_vmac_stat_update"));
504 	return (0);
505 }
506 
507 /* ARGSUSED */
508 int
509 hxge_pfc_stat_update(kstat_t *ksp, int rw)
510 {
511 	p_hxge_t		hxgep;
512 	p_hxge_pfc_kstat_t	kstatsp;
513 	p_hxge_pfc_stats_t	statsp;
514 
515 	hxgep = (p_hxge_t)ksp->ks_private;
516 	if (hxgep == NULL)
517 		return (-1);
518 
519 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "==> hxge_pfc_stat_update"));
520 
521 	kstatsp = (p_hxge_pfc_kstat_t)ksp->ks_data;
522 	statsp = (p_hxge_pfc_stats_t)&hxgep->statsp->pfc_stats;
523 
524 	kstatsp->pfc_pkt_drop.value.ul = statsp->pkt_drop;
525 	kstatsp->pfc_tcam_parity_err.value.ul = statsp->tcam_parity_err;
526 	kstatsp->pfc_vlan_parity_err.value.ul = statsp->vlan_parity_err;
527 	kstatsp->pfc_bad_cs_count.value.ul = statsp->bad_cs_count;
528 	kstatsp->pfc_drop_count.value.ul = statsp->drop_count;
529 	kstatsp->pfc_tcp_ctrl_drop.value.ul = statsp->errlog.tcp_ctrl_drop;
530 	kstatsp->pfc_l2_addr_drop.value.ul = statsp->errlog.l2_addr_drop;
531 	kstatsp->pfc_class_code_drop.value.ul = statsp->errlog.class_code_drop;
532 	kstatsp->pfc_tcam_drop.value.ul = statsp->errlog.tcam_drop;
533 	kstatsp->pfc_vlan_drop.value.ul = statsp->errlog.vlan_drop;
534 
535 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "<== hxge_pfc_stat_update"));
536 	return (0);
537 }
538 
539 /* ARGSUSED */
540 int
541 hxge_peu_sys_stat_update(kstat_t *ksp, int rw)
542 {
543 	p_hxge_t		hxgep;
544 	p_hxge_peu_sys_kstat_t	peu_kstatsp;
545 	p_hxge_peu_sys_stats_t	statsp;
546 
547 	hxgep = (p_hxge_t)ksp->ks_private;
548 	if (hxgep == NULL)
549 		return (-1);
550 
551 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "==> hxge_peu_sys_stat_update"));
552 
553 	peu_kstatsp = (p_hxge_peu_sys_kstat_t)ksp->ks_data;
554 	statsp = (p_hxge_peu_sys_stats_t)&hxgep->statsp->peu_sys_stats;
555 
556 	peu_kstatsp->spc_acc_err.value.ul = statsp->spc_acc_err;
557 	peu_kstatsp->tdc_pioacc_err.value.ul = statsp->tdc_pioacc_err;
558 	peu_kstatsp->rdc_pioacc_err.value.ul = statsp->rdc_pioacc_err;
559 	peu_kstatsp->pfc_pioacc_err.value.ul = statsp->pfc_pioacc_err;
560 	peu_kstatsp->vmac_pioacc_err.value.ul = statsp->vmac_pioacc_err;
561 	peu_kstatsp->cpl_hdrq_parerr.value.ul = statsp->cpl_hdrq_parerr;
562 	peu_kstatsp->cpl_dataq_parerr.value.ul = statsp->cpl_dataq_parerr;
563 	peu_kstatsp->retryram_xdlh_parerr.value.ul =
564 	    statsp->retryram_xdlh_parerr;
565 	peu_kstatsp->retrysotram_xdlh_parerr.value.ul =
566 	    statsp->retrysotram_xdlh_parerr;
567 	peu_kstatsp->p_hdrq_parerr.value.ul = statsp->p_hdrq_parerr;
568 	peu_kstatsp->p_dataq_parerr.value.ul = statsp->p_dataq_parerr;
569 	peu_kstatsp->np_hdrq_parerr.value.ul = statsp->np_hdrq_parerr;
570 	peu_kstatsp->np_dataq_parerr.value.ul = statsp->np_dataq_parerr;
571 	peu_kstatsp->eic_msix_parerr.value.ul = statsp->eic_msix_parerr;
572 	peu_kstatsp->hcr_parerr.value.ul = statsp->hcr_parerr;
573 
574 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "<== hxge_peu_sys_stat_update"));
575 	return (0);
576 }
577 
578 static kstat_t *
579 hxge_setup_local_kstat(p_hxge_t hxgep, int instance, char *name,
580 	const hxge_kstat_index_t *ksip, size_t count,
581 	int (*update) (kstat_t *, int))
582 {
583 	kstat_t		*ksp;
584 	kstat_named_t	*knp;
585 	int		i;
586 
587 	ksp = kstat_create(HXGE_DRIVER_NAME, instance, name, "net",
588 	    KSTAT_TYPE_NAMED, count, 0);
589 	if (ksp == NULL)
590 		return (NULL);
591 
592 	ksp->ks_private = (void *) hxgep;
593 	ksp->ks_update = update;
594 	knp = ksp->ks_data;
595 
596 	for (i = 0; ksip[i].name != NULL; i++) {
597 		kstat_named_init(&knp[i], ksip[i].name, ksip[i].type);
598 	}
599 
600 	kstat_install(ksp);
601 
602 	return (ksp);
603 }
604 
605 void
606 hxge_setup_kstats(p_hxge_t hxgep)
607 {
608 	struct kstat		*ksp;
609 	p_hxge_port_kstat_t	hxgekp;
610 	size_t			hxge_kstat_sz;
611 	char			stat_name[64];
612 	int			i;
613 
614 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "==> hxge_setup_kstats"));
615 
616 	/* Setup RDC statistics */
617 	for (i = 0; i < hxgep->nrdc; i++) {
618 		(void) sprintf(stat_name, "%s"CH_NAME_FORMAT,
619 		    RDC_NAME_FORMAT1, i);
620 		hxgep->statsp->rdc_ksp[i] = hxge_setup_local_kstat(hxgep,
621 		    hxgep->instance, stat_name, &hxge_rdc_stats[0],
622 		    RDC_STAT_END, hxge_rdc_stat_update);
623 		if (hxgep->statsp->rdc_ksp[i] == NULL)
624 			cmn_err(CE_WARN,
625 			    "kstat_create failed for rdc channel %d", i);
626 	}
627 
628 	/* Setup RDC System statistics */
629 	hxgep->statsp->rdc_sys_ksp = hxge_setup_local_kstat(hxgep,
630 	    hxgep->instance, "RDC_system", &hxge_rdc_sys_stats[0],
631 	    RDC_SYS_STAT_END, hxge_rdc_sys_stat_update);
632 	if (hxgep->statsp->rdc_sys_ksp == NULL)
633 		cmn_err(CE_WARN, "kstat_create failed for rdc_sys_ksp");
634 
635 	/* Setup TDC statistics */
636 	for (i = 0; i < hxgep->ntdc; i++) {
637 		(void) sprintf(stat_name, "%s"CH_NAME_FORMAT,
638 		    TDC_NAME_FORMAT1, i);
639 		hxgep->statsp->tdc_ksp[i] = hxge_setup_local_kstat(hxgep,
640 		    hxgep->instance, stat_name, &hxge_tdc_stats[0],
641 		    TDC_STAT_END, hxge_tdc_stat_update);
642 		if (hxgep->statsp->tdc_ksp[i] == NULL)
643 			cmn_err(CE_WARN,
644 			    "kstat_create failed for tdc channel %d", i);
645 	}
646 
647 	/* Setup TDC System statistics */
648 	hxgep->statsp->tdc_sys_ksp = hxge_setup_local_kstat(hxgep,
649 	    hxgep->instance, "TDC_system", &hxge_tdc_sys_stats[0],
650 	    RDC_SYS_STAT_END, hxge_tdc_sys_stat_update);
651 	if (hxgep->statsp->tdc_sys_ksp == NULL)
652 		cmn_err(CE_WARN, "kstat_create failed for tdc_sys_ksp");
653 
654 	/* Setup PFC statistics */
655 	hxgep->statsp->pfc_ksp = hxge_setup_local_kstat(hxgep,
656 	    hxgep->instance, "PFC", &hxge_pfc_stats[0],
657 	    PFC_STAT_END, hxge_pfc_stat_update);
658 	if (hxgep->statsp->pfc_ksp == NULL)
659 		cmn_err(CE_WARN, "kstat_create failed for pfc");
660 
661 	/* Setup VMAC statistics */
662 	hxgep->statsp->vmac_ksp = hxge_setup_local_kstat(hxgep,
663 	    hxgep->instance, "VMAC", &hxge_vmac_stats[0],
664 	    VMAC_STAT_END, hxge_vmac_stat_update);
665 	if (hxgep->statsp->vmac_ksp == NULL)
666 		cmn_err(CE_WARN, "kstat_create failed for vmac");
667 
668 	/* Setup PEU System statistics */
669 	hxgep->statsp->peu_sys_ksp = hxge_setup_local_kstat(hxgep,
670 	    hxgep->instance, "PEU", &hxge_peu_sys_stats[0],
671 	    PEU_SYS_STAT_END, hxge_peu_sys_stat_update);
672 	if (hxgep->statsp->peu_sys_ksp == NULL)
673 		cmn_err(CE_WARN, "kstat_create failed for peu sys");
674 
675 	/* Port stats */
676 	hxge_kstat_sz = sizeof (hxge_port_kstat_t);
677 
678 	if ((ksp = kstat_create(HXGE_DRIVER_NAME, hxgep->instance,
679 	    "Port", "net", KSTAT_TYPE_NAMED,
680 	    hxge_kstat_sz / sizeof (kstat_named_t), 0)) == NULL) {
681 		cmn_err(CE_WARN, "kstat_create failed for port stat");
682 		return;
683 	}
684 
685 	hxgekp = (p_hxge_port_kstat_t)ksp->ks_data;
686 
687 	kstat_named_init(&hxgekp->cap_10gfdx, "cap_10gfdx", KSTAT_DATA_ULONG);
688 
689 	/*
690 	 * Link partner capabilities.
691 	 */
692 	kstat_named_init(&hxgekp->lp_cap_10gfdx, "lp_cap_10gfdx",
693 	    KSTAT_DATA_ULONG);
694 
695 	/*
696 	 * Shared link setup.
697 	 */
698 	kstat_named_init(&hxgekp->link_speed, "link_speed", KSTAT_DATA_ULONG);
699 	kstat_named_init(&hxgekp->link_duplex, "link_duplex", KSTAT_DATA_CHAR);
700 	kstat_named_init(&hxgekp->link_up, "link_up", KSTAT_DATA_ULONG);
701 
702 	/*
703 	 * Loopback statistics.
704 	 */
705 	kstat_named_init(&hxgekp->lb_mode, "lb_mode", KSTAT_DATA_ULONG);
706 
707 	/* General MAC statistics */
708 
709 	kstat_named_init(&hxgekp->ifspeed, "ifspeed", KSTAT_DATA_UINT64);
710 	kstat_named_init(&hxgekp->promisc, "promisc", KSTAT_DATA_CHAR);
711 
712 	ksp->ks_update = hxge_port_kstat_update;
713 	ksp->ks_private = (void *) hxgep;
714 	kstat_install(ksp);
715 	hxgep->statsp->port_ksp = ksp;
716 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "<== hxge_setup_kstats"));
717 }
718 
719 void
720 hxge_destroy_kstats(p_hxge_t hxgep)
721 {
722 	int			channel;
723 	p_hxge_dma_pt_cfg_t	p_dma_cfgp;
724 	p_hxge_hw_pt_cfg_t	p_cfgp;
725 
726 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "==> hxge_destroy_kstats"));
727 	if (hxgep->statsp == NULL)
728 		return;
729 
730 	if (hxgep->statsp->ksp)
731 		kstat_delete(hxgep->statsp->ksp);
732 
733 	p_dma_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config;
734 	p_cfgp = (p_hxge_hw_pt_cfg_t)&p_dma_cfgp->hw_config;
735 
736 	for (channel = 0; channel < p_cfgp->max_rdcs; channel++) {
737 		if (hxgep->statsp->rdc_ksp[channel]) {
738 			kstat_delete(hxgep->statsp->rdc_ksp[channel]);
739 		}
740 	}
741 
742 	for (channel = 0; channel < p_cfgp->max_tdcs; channel++) {
743 		if (hxgep->statsp->tdc_ksp[channel]) {
744 			kstat_delete(hxgep->statsp->tdc_ksp[channel]);
745 		}
746 	}
747 
748 	if (hxgep->statsp->rdc_sys_ksp)
749 		kstat_delete(hxgep->statsp->rdc_sys_ksp);
750 
751 	if (hxgep->statsp->tdc_sys_ksp)
752 		kstat_delete(hxgep->statsp->tdc_sys_ksp);
753 
754 	if (hxgep->statsp->peu_sys_ksp)
755 		kstat_delete(hxgep->statsp->peu_sys_ksp);
756 
757 	if (hxgep->statsp->mmac_ksp)
758 		kstat_delete(hxgep->statsp->mmac_ksp);
759 
760 	if (hxgep->statsp->pfc_ksp)
761 		kstat_delete(hxgep->statsp->pfc_ksp);
762 
763 	if (hxgep->statsp->vmac_ksp)
764 		kstat_delete(hxgep->statsp->vmac_ksp);
765 
766 	if (hxgep->statsp->port_ksp)
767 		kstat_delete(hxgep->statsp->port_ksp);
768 
769 	if (hxgep->statsp)
770 		KMEM_FREE(hxgep->statsp, hxgep->statsp->stats_size);
771 
772 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "<== hxge_destroy_kstats"));
773 }
774 
775 /* ARGSUSED */
776 int
777 hxge_port_kstat_update(kstat_t *ksp, int rw)
778 {
779 	p_hxge_t		hxgep;
780 	p_hxge_stats_t		statsp;
781 	p_hxge_port_kstat_t	hxgekp;
782 	p_hxge_port_stats_t	psp;
783 
784 	hxgep = (p_hxge_t)ksp->ks_private;
785 	if (hxgep == NULL)
786 		return (-1);
787 
788 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "==> hxge_port_kstat_update"));
789 	statsp = (p_hxge_stats_t)hxgep->statsp;
790 	hxgekp = (p_hxge_port_kstat_t)ksp->ks_data;
791 	psp = &statsp->port_stats;
792 
793 	if (hxgep->filter.all_phys_cnt)
794 		(void) strcpy(hxgekp->promisc.value.c, "phys");
795 	else if (hxgep->filter.all_multicast_cnt)
796 		(void) strcpy(hxgekp->promisc.value.c, "multi");
797 	else
798 		(void) strcpy(hxgekp->promisc.value.c, "off");
799 	hxgekp->ifspeed.value.ul = statsp->mac_stats.link_speed * 1000000ULL;
800 
801 	/*
802 	 * transceiver state informations.
803 	 */
804 	hxgekp->cap_10gfdx.value.ul = statsp->mac_stats.cap_10gfdx;
805 
806 	/*
807 	 * Link partner capabilities.
808 	 */
809 	hxgekp->lp_cap_10gfdx.value.ul = statsp->mac_stats.lp_cap_10gfdx;
810 
811 	/*
812 	 * Physical link statistics.
813 	 */
814 	hxgekp->link_speed.value.ul = statsp->mac_stats.link_speed;
815 	if (statsp->mac_stats.link_duplex == 2)
816 		(void) strcpy(hxgekp->link_duplex.value.c, "full");
817 	else
818 		(void) strcpy(hxgekp->link_duplex.value.c, "unknown");
819 	hxgekp->link_up.value.ul = statsp->mac_stats.link_up;
820 
821 	/*
822 	 * Loopback statistics.
823 	 */
824 	hxgekp->lb_mode.value.ul = psp->lb_mode;
825 
826 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "<== hxge_port_kstat_update"));
827 	return (0);
828 }
829 
830 int
831 hxge_m_stat(void *arg, uint_t stat, uint64_t *value)
832 {
833 	p_hxge_t		hxgep = (p_hxge_t)arg;
834 	p_hxge_stats_t		statsp;
835 	hxge_tx_ring_stats_t	*tx_stats;
836 	uint64_t		val = 0;
837 	int			channel;
838 
839 	HXGE_DEBUG_MSG((hxgep, KST_CTL, "==> hxge_m_stat"));
840 	statsp = (p_hxge_stats_t)hxgep->statsp;
841 
842 	switch (stat) {
843 	case MAC_STAT_IFSPEED:
844 		val = statsp->mac_stats.link_speed * 1000000ull;
845 		break;
846 
847 	case MAC_STAT_MULTIRCV:
848 		val = 0;
849 		break;
850 
851 	case MAC_STAT_BRDCSTRCV:
852 		val = 0;
853 		break;
854 
855 	case MAC_STAT_MULTIXMT:
856 		val = 0;
857 		break;
858 
859 	case MAC_STAT_BRDCSTXMT:
860 		val = 0;
861 		break;
862 
863 	case MAC_STAT_NORCVBUF:
864 		val = 0;
865 		break;
866 
867 	case MAC_STAT_IERRORS:
868 	case ETHER_STAT_MACRCV_ERRORS:
869 		val = 0;
870 		for (channel = 0; channel < hxgep->nrdc; channel++) {
871 			val += statsp->rdc_stats[channel].ierrors;
872 		}
873 		break;
874 
875 	case MAC_STAT_NOXMTBUF:
876 		val = 0;
877 		break;
878 
879 	case MAC_STAT_OERRORS:
880 		for (channel = 0; channel < hxgep->ntdc; channel++) {
881 			val += statsp->tdc_stats[channel].oerrors;
882 		}
883 		break;
884 
885 	case MAC_STAT_COLLISIONS:
886 		val = 0;
887 		break;
888 
889 	case MAC_STAT_RBYTES:
890 		for (channel = 0; channel < hxgep->nrdc; channel++) {
891 			val += statsp->rdc_stats[channel].ibytes;
892 		}
893 		break;
894 
895 	case MAC_STAT_IPACKETS:
896 		for (channel = 0; channel < hxgep->nrdc; channel++) {
897 			val += statsp->rdc_stats[channel].ipackets;
898 		}
899 		break;
900 
901 	case MAC_STAT_OBYTES:
902 		for (channel = 0; channel < hxgep->ntdc; channel++) {
903 			val += statsp->tdc_stats[channel].obytes;
904 		}
905 		break;
906 
907 	case MAC_STAT_OPACKETS:
908 		for (channel = 0; channel < hxgep->ntdc; channel++) {
909 			val += statsp->tdc_stats[channel].opackets;
910 		}
911 		break;
912 
913 	case MAC_STAT_UNKNOWNS:
914 		val = 0;
915 		break;
916 
917 	case MAC_STAT_UNDERFLOWS:
918 		val = 0;
919 		break;
920 
921 	case MAC_STAT_OVERFLOWS:
922 		val = 0;
923 		break;
924 
925 	case MAC_STAT_LINK_STATE:
926 		val = statsp->mac_stats.link_duplex;
927 		break;
928 	case MAC_STAT_LINK_UP:
929 		val = statsp->mac_stats.link_up;
930 		break;
931 	case MAC_STAT_PROMISC:
932 		val = statsp->mac_stats.promisc;
933 		break;
934 	case ETHER_STAT_SQE_ERRORS:
935 		val = 0;
936 		break;
937 
938 	case ETHER_STAT_ALIGN_ERRORS:
939 		/*
940 		 * No similar error in Hydra receive channels
941 		 */
942 		val = 0;
943 		break;
944 
945 	case ETHER_STAT_FCS_ERRORS:
946 		/*
947 		 * No similar error in Hydra receive channels
948 		 */
949 		val = 0;
950 		break;
951 
952 	case ETHER_STAT_FIRST_COLLISIONS:
953 		val = 0;
954 		break;
955 
956 	case ETHER_STAT_MULTI_COLLISIONS:
957 		val = 0;
958 		break;
959 
960 	case ETHER_STAT_TX_LATE_COLLISIONS:
961 		val = 0;
962 		break;
963 
964 	case ETHER_STAT_EX_COLLISIONS:
965 		val = 0;
966 		break;
967 
968 	case ETHER_STAT_DEFER_XMTS:
969 		val = 0;
970 		break;
971 
972 	case ETHER_STAT_MACXMT_ERRORS:
973 		/*
974 		 * A count of frames for which transmission on a
975 		 * particular interface fails due to an internal
976 		 * MAC sublayer transmit error
977 		 */
978 		for (channel = 0; channel < hxgep->ntdc; channel++) {
979 			tx_stats = &statsp->tdc_stats[channel];
980 			val += tx_stats->pkt_size_hdr_err +
981 			    tx_stats->pkt_size_err +
982 			    tx_stats->tx_rng_oflow +
983 			    tx_stats->peu_resp_err +
984 			    tx_stats->runt_pkt_drop_err +
985 			    tx_stats->pref_par_err +
986 			    tx_stats->tdr_pref_cpl_to +
987 			    tx_stats->pkt_cpl_to +
988 			    tx_stats->invalid_sop +
989 			    tx_stats->unexpected_sop;
990 		}
991 		break;
992 
993 	case ETHER_STAT_CARRIER_ERRORS:
994 		/*
995 		 * The number of times that the carrier sense
996 		 * condition was lost or never asserted when
997 		 * attempting to transmit a frame on a particular interface
998 		 */
999 		for (channel = 0; channel < hxgep->ntdc; channel++) {
1000 			tx_stats = &statsp->tdc_stats[channel];
1001 			val += tx_stats->tdr_pref_cpl_to + tx_stats->pkt_cpl_to;
1002 		}
1003 		break;
1004 
1005 	case ETHER_STAT_TOOLONG_ERRORS:
1006 		/*
1007 		 * A count of frames received on a particular
1008 		 * interface that exceed the maximum permitted frame size
1009 		 */
1010 		for (channel = 0; channel < hxgep->ntdc; channel++) {
1011 			tx_stats = &statsp->tdc_stats[channel];
1012 			val += tx_stats->pkt_size_err;
1013 		}
1014 		break;
1015 
1016 	case ETHER_STAT_XCVR_ADDR:
1017 		val = 0;
1018 		break;
1019 	case ETHER_STAT_XCVR_ID:
1020 		val = 0;
1021 		break;
1022 
1023 	case ETHER_STAT_XCVR_INUSE:
1024 		val = 0;
1025 		break;
1026 
1027 	case ETHER_STAT_CAP_1000FDX:
1028 		val = 0;
1029 		break;
1030 
1031 	case ETHER_STAT_CAP_1000HDX:
1032 		val = 0;
1033 		break;
1034 
1035 	case ETHER_STAT_CAP_100FDX:
1036 		val = 0;
1037 		break;
1038 
1039 	case ETHER_STAT_CAP_100HDX:
1040 		val = 0;
1041 		break;
1042 
1043 	case ETHER_STAT_CAP_10FDX:
1044 		val = 0;
1045 		break;
1046 
1047 	case ETHER_STAT_CAP_10HDX:
1048 		val = 0;
1049 		break;
1050 
1051 	case ETHER_STAT_CAP_ASMPAUSE:
1052 		val = 0;
1053 		break;
1054 
1055 	case ETHER_STAT_CAP_PAUSE:
1056 		val = 0;
1057 		break;
1058 
1059 	case ETHER_STAT_CAP_AUTONEG:
1060 		val = 0;
1061 		break;
1062 
1063 	case ETHER_STAT_ADV_CAP_1000FDX:
1064 		val = 0;
1065 		break;
1066 
1067 	case ETHER_STAT_ADV_CAP_1000HDX:
1068 		val = 0;
1069 		break;
1070 
1071 	case ETHER_STAT_ADV_CAP_100FDX:
1072 		val = 0;
1073 		break;
1074 
1075 	case ETHER_STAT_ADV_CAP_100HDX:
1076 		val = 0;
1077 		break;
1078 
1079 	case ETHER_STAT_ADV_CAP_10FDX:
1080 		val = 0;
1081 		break;
1082 
1083 	case ETHER_STAT_ADV_CAP_10HDX:
1084 		val = 0;
1085 		break;
1086 
1087 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
1088 		val = 0;
1089 		break;
1090 
1091 	case ETHER_STAT_ADV_CAP_PAUSE:
1092 		val = 0;
1093 		break;
1094 
1095 	case ETHER_STAT_ADV_CAP_AUTONEG:
1096 		val = 0;
1097 		break;
1098 
1099 	case ETHER_STAT_LP_CAP_1000FDX:
1100 		val = 0;
1101 		break;
1102 
1103 	case ETHER_STAT_LP_CAP_1000HDX:
1104 		val = 0;
1105 		break;
1106 
1107 	case ETHER_STAT_LP_CAP_100FDX:
1108 		val = 0;
1109 		break;
1110 
1111 	case ETHER_STAT_LP_CAP_100HDX:
1112 		val = 0;
1113 		break;
1114 
1115 	case ETHER_STAT_LP_CAP_10FDX:
1116 		val = 0;
1117 		break;
1118 
1119 	case ETHER_STAT_LP_CAP_10HDX:
1120 		val = 0;
1121 		break;
1122 
1123 	case ETHER_STAT_LP_CAP_ASMPAUSE:
1124 		val = 0;
1125 		break;
1126 
1127 	case ETHER_STAT_LP_CAP_PAUSE:
1128 		val = 0;
1129 		break;
1130 
1131 	case ETHER_STAT_LP_CAP_AUTONEG:
1132 		val = 0;
1133 		break;
1134 
1135 	case ETHER_STAT_LINK_ASMPAUSE:
1136 		val = 0;
1137 		break;
1138 
1139 	case ETHER_STAT_LINK_PAUSE:
1140 		val = 0;
1141 		break;
1142 
1143 	case ETHER_STAT_LINK_AUTONEG:
1144 		val = 0;
1145 		break;
1146 
1147 	case ETHER_STAT_LINK_DUPLEX:
1148 		val = statsp->mac_stats.link_duplex;
1149 		break;
1150 
1151 	case ETHER_STAT_TOOSHORT_ERRORS:
1152 		val = 0;
1153 		break;
1154 
1155 	case ETHER_STAT_CAP_REMFAULT:
1156 		val = 0;
1157 		break;
1158 
1159 	case ETHER_STAT_ADV_REMFAULT:
1160 		val = 0;
1161 		break;
1162 
1163 	case ETHER_STAT_LP_REMFAULT:
1164 		val = 0;
1165 		break;
1166 
1167 	case ETHER_STAT_JABBER_ERRORS:
1168 		val = 0;
1169 		break;
1170 
1171 	case ETHER_STAT_CAP_100T4:
1172 		val = 0;
1173 		break;
1174 
1175 	case ETHER_STAT_ADV_CAP_100T4:
1176 		val = 0;
1177 		break;
1178 
1179 	case ETHER_STAT_LP_CAP_100T4:
1180 		val = 0;
1181 		break;
1182 
1183 	default:
1184 		/*
1185 		 * Shouldn't reach here...
1186 		 */
1187 		cmn_err(CE_WARN,
1188 		    "hxge_m_stat: unrecognized parameter value = 0x%x", stat);
1189 
1190 		return (ENOTSUP);
1191 	}
1192 	*value = val;
1193 	return (0);
1194 }
1195