xref: /illumos-gate/usr/src/uts/common/io/xge/hal/xgehal/xgehal-stats.c (revision 2983dda76a6d296fdb560c88114fe41caad1b84f)
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  * Copyright (c) 2002-2006 Neterion, Inc.
22  */
23 
24 #include "xgehal-stats.h"
25 #include "xgehal-device.h"
26 
27 /*
28  * __hal_stats_initialize
29  * @stats: xge_hal_stats_t structure that contains, in particular,
30  *         Xframe hw stat counters.
31  * @devh: HAL device handle.
32  *
33  * Initialize per-device statistics object.
34  * See also: xge_hal_stats_getinfo(), xge_hal_status_e{}.
35  */
36 xge_hal_status_e
37 __hal_stats_initialize (xge_hal_stats_t *stats, xge_hal_device_h devh)
38 {
39 	int dma_flags;
40 	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
41 
42 	xge_assert(!stats->is_initialized);
43 
44 	dma_flags = XGE_OS_DMA_CACHELINE_ALIGNED;
45 #ifdef XGE_HAL_DMA_STATS_CONSISTENT
46 	dma_flags |= XGE_OS_DMA_CONSISTENT;
47 #else
48 	dma_flags |= XGE_OS_DMA_STREAMING;
49 #endif
50 	if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) {
51 		stats->hw_info =
52 			(xge_hal_stats_hw_info_t *) xge_os_dma_malloc(
53 					hldev->pdev,
54 					sizeof(xge_hal_stats_hw_info_t),
55 					dma_flags,
56 					&stats->hw_info_dmah,
57 					&stats->hw_info_dma_acch);
58 
59 		if (stats->hw_info == NULL) {
60 			xge_debug_stats(XGE_ERR, "%s", "can not DMA alloc");
61 			return XGE_HAL_ERR_OUT_OF_MEMORY;
62 		}
63 		xge_os_memzero(stats->hw_info,
64 			sizeof(xge_hal_stats_hw_info_t));
65 		xge_os_memzero(&stats->hw_info_saved,
66 			sizeof(xge_hal_stats_hw_info_t));
67 		xge_os_memzero(&stats->hw_info_latest,
68 			sizeof(xge_hal_stats_hw_info_t));
69 
70 
71 
72 		stats->dma_addr = xge_os_dma_map(hldev->pdev,
73 	                               stats->hw_info_dmah,
74 				       stats->hw_info,
75 				       sizeof(xge_hal_stats_hw_info_t),
76 				       XGE_OS_DMA_DIR_FROMDEVICE,
77 				       XGE_OS_DMA_CACHELINE_ALIGNED |
78 #ifdef XGE_HAL_DMA_STATS_CONSISTENT
79 				       XGE_OS_DMA_CONSISTENT
80 #else
81 			               XGE_OS_DMA_STREAMING
82 #endif
83                                        );
84 		if (stats->dma_addr == XGE_OS_INVALID_DMA_ADDR) {
85 			xge_debug_stats(XGE_ERR,
86 				"can not map vaddr 0x"XGE_OS_LLXFMT" to DMA",
87 				(unsigned long long)(ulong_t)stats->hw_info);
88 			xge_os_dma_free(hldev->pdev,
89 			      stats->hw_info,
90 			      sizeof(xge_hal_stats_hw_info_t),
91 			      &stats->hw_info_dma_acch,
92 			      &stats->hw_info_dmah);
93 			return XGE_HAL_ERR_OUT_OF_MAPPING;
94 		}
95 	}
96 	else {
97 		stats->pcim_info_saved =
98 			(xge_hal_stats_pcim_info_t *)xge_os_malloc(
99 			hldev->pdev, sizeof(xge_hal_stats_pcim_info_t));
100 		if (stats->pcim_info_saved == NULL) {
101 			xge_debug_stats(XGE_ERR, "%s", "can not alloc");
102 			return XGE_HAL_ERR_OUT_OF_MEMORY;
103 		}
104 
105 		stats->pcim_info_latest =
106 			(xge_hal_stats_pcim_info_t *)xge_os_malloc(
107 			hldev->pdev, sizeof(xge_hal_stats_pcim_info_t));
108 		if (stats->pcim_info_latest == NULL) {
109 			xge_os_free(hldev->pdev, stats->pcim_info_saved,
110 				sizeof(xge_hal_stats_pcim_info_t));
111 			xge_debug_stats(XGE_ERR, "%s", "can not alloc");
112 			return XGE_HAL_ERR_OUT_OF_MEMORY;
113 		}
114 
115 		stats->pcim_info =
116 			(xge_hal_stats_pcim_info_t *) xge_os_dma_malloc(
117 					hldev->pdev,
118 					sizeof(xge_hal_stats_pcim_info_t),
119 					dma_flags,
120 					&stats->hw_info_dmah,
121 					&stats->hw_info_dma_acch);
122 
123 		if (stats->pcim_info == NULL) {
124 			xge_os_free(hldev->pdev, stats->pcim_info_saved,
125 				sizeof(xge_hal_stats_pcim_info_t));
126 			xge_os_free(hldev->pdev, stats->pcim_info_latest,
127 				sizeof(xge_hal_stats_pcim_info_t));
128 			xge_debug_stats(XGE_ERR, "%s", "can not DMA alloc");
129 			return XGE_HAL_ERR_OUT_OF_MEMORY;
130 		}
131 
132 
133 		xge_os_memzero(stats->pcim_info,
134 			sizeof(xge_hal_stats_pcim_info_t));
135 		xge_os_memzero(stats->pcim_info_saved,
136 			sizeof(xge_hal_stats_pcim_info_t));
137 		xge_os_memzero(stats->pcim_info_latest,
138 			sizeof(xge_hal_stats_pcim_info_t));
139 
140 
141 
142 		stats->dma_addr = xge_os_dma_map(hldev->pdev,
143 	                               stats->hw_info_dmah,
144 				       stats->pcim_info,
145 				       sizeof(xge_hal_stats_pcim_info_t),
146 				       XGE_OS_DMA_DIR_FROMDEVICE,
147 				       XGE_OS_DMA_CACHELINE_ALIGNED |
148 #ifdef XGE_HAL_DMA_STATS_CONSISTENT
149 				       XGE_OS_DMA_CONSISTENT
150 #else
151 			               XGE_OS_DMA_STREAMING
152 #endif
153                                        );
154 		if (stats->dma_addr == XGE_OS_INVALID_DMA_ADDR) {
155 			xge_debug_stats(XGE_ERR,
156 				"can not map vaddr 0x"XGE_OS_LLXFMT" to DMA",
157 				(unsigned long long)(ulong_t)stats->hw_info);
158 
159 			xge_os_dma_free(hldev->pdev,
160 			      stats->pcim_info,
161 			      sizeof(xge_hal_stats_pcim_info_t),
162 			      &stats->hw_info_dma_acch,
163 			      &stats->hw_info_dmah);
164 
165 			xge_os_free(hldev->pdev, stats->pcim_info_saved,
166 				sizeof(xge_hal_stats_pcim_info_t));
167 
168 			xge_os_free(hldev->pdev, stats->pcim_info_latest,
169 				sizeof(xge_hal_stats_pcim_info_t));
170 
171 			return XGE_HAL_ERR_OUT_OF_MAPPING;
172 		}
173 	}
174 	stats->devh = devh;
175 	xge_os_memzero(&stats->sw_dev_info_stats,
176 		     sizeof(xge_hal_stats_device_info_t));
177 
178 	stats->is_initialized = 1;
179 
180 	return XGE_HAL_OK;
181 }
182 
183 static void
184 __hal_stats_save (xge_hal_stats_t *stats)
185 {
186 	xge_hal_device_t *hldev = (xge_hal_device_t*)stats->devh;
187 
188 	if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) {
189 		xge_hal_stats_hw_info_t	*latest;
190 
191 		(void) xge_hal_stats_hw(stats->devh, &latest);
192 
193 		xge_os_memcpy(&stats->hw_info_saved, stats->hw_info,
194 		      sizeof(xge_hal_stats_hw_info_t));
195 	} else {
196 		xge_hal_stats_pcim_info_t	*latest;
197 
198 		(void) xge_hal_stats_pcim(stats->devh, &latest);
199 
200 		xge_os_memcpy(stats->pcim_info_saved, stats->pcim_info,
201 		      sizeof(xge_hal_stats_pcim_info_t));
202 	}
203 }
204 
205 /*
206  * __hal_stats_disable
207  * @stats: xge_hal_stats_t structure that contains, in particular,
208  *         Xframe hw stat counters.
209  *
210  * Ask device to stop collecting stats.
211  * See also: xge_hal_stats_getinfo().
212  */
213 void
214 __hal_stats_disable (xge_hal_stats_t *stats)
215 {
216 	xge_hal_device_t *hldev;
217 	xge_hal_pci_bar0_t *bar0;
218 	u64 val64;
219 
220 	xge_assert(stats->hw_info);
221 
222 	hldev = (xge_hal_device_t*)stats->devh;
223 	xge_assert(hldev);
224 	bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
225 
226 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
227 		&bar0->stat_cfg);
228 	val64 &= ~XGE_HAL_STAT_CFG_STAT_EN;
229 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
230 		&bar0->stat_cfg);
231 	/* flush the write */
232 	(void)xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
233 		&bar0->stat_cfg);
234 
235 	xge_debug_stats(XGE_TRACE, "stats disabled at 0x"XGE_OS_LLXFMT,
236 		 (unsigned long long)stats->dma_addr);
237 
238 	stats->is_enabled = 0;
239 }
240 
241 /*
242  * __hal_stats_terminate
243  * @stats: xge_hal_stats_t structure that contains, in particular,
244  *         Xframe hw stat counters.
245  * Terminate per-device statistics object.
246  */
247 void
248 __hal_stats_terminate (xge_hal_stats_t *stats)
249 {
250 	xge_hal_device_t *hldev;
251 
252 	xge_assert(stats->hw_info);
253 
254 	hldev = (xge_hal_device_t*)stats->devh;
255 	xge_assert(hldev);
256 	xge_assert(stats->is_initialized);
257 	if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) {
258 		xge_os_dma_unmap(hldev->pdev,
259 	               stats->hw_info_dmah,
260 		       stats->dma_addr,
261 		       sizeof(xge_hal_stats_hw_info_t),
262 		       XGE_OS_DMA_DIR_FROMDEVICE);
263 
264 		xge_os_dma_free(hldev->pdev,
265 		      stats->hw_info,
266 		      sizeof(xge_hal_stats_hw_info_t),
267 		      &stats->hw_info_dma_acch,
268 		      &stats->hw_info_dmah);
269 	} else {
270 		xge_os_dma_unmap(hldev->pdev,
271 	               stats->hw_info_dmah,
272 		       stats->dma_addr,
273 		       sizeof(xge_hal_stats_pcim_info_t),
274 		       XGE_OS_DMA_DIR_FROMDEVICE);
275 
276 		xge_os_dma_free(hldev->pdev,
277 		      stats->pcim_info,
278 		      sizeof(xge_hal_stats_pcim_info_t),
279 		      &stats->hw_info_dma_acch,
280 		      &stats->hw_info_dmah);
281 
282 		xge_os_free(hldev->pdev, stats->pcim_info_saved,
283 			sizeof(xge_hal_stats_pcim_info_t));
284 
285 		xge_os_free(hldev->pdev, stats->pcim_info_latest,
286 				sizeof(xge_hal_stats_pcim_info_t));
287 
288 	}
289 
290 	stats->is_initialized = 0;
291 	stats->is_enabled = 0;
292 }
293 
294 
295 
296 /*
297  * __hal_stats_enable
298  * @stats: xge_hal_stats_t structure that contains, in particular,
299  *         Xframe hw stat counters.
300  *
301  * Ask device to start collecting stats.
302  * See also: xge_hal_stats_getinfo().
303  */
304 void
305 __hal_stats_enable (xge_hal_stats_t *stats)
306 {
307 	xge_hal_device_t *hldev;
308 	xge_hal_pci_bar0_t *bar0;
309 	u64 val64;
310 	unsigned int refresh_time_pci_clocks;
311 
312 	xge_assert(stats->hw_info);
313 
314 	hldev = (xge_hal_device_t*)stats->devh;
315 	xge_assert(hldev);
316 
317 	bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
318 
319 	/* enable statistics
320 	 * For Titan stat_addr offset == 0x09d8, and stat_cfg offset == 0x09d0
321 	*/
322 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
323 		stats->dma_addr, &bar0->stat_addr);
324 
325 	refresh_time_pci_clocks = XGE_HAL_XENA_PER_SEC *
326 		hldev->config.stats_refresh_time_sec;
327 	refresh_time_pci_clocks =
328 		__hal_fix_time_ival_herc(hldev,
329 			refresh_time_pci_clocks);
330 
331 	/* enable enhanced statistics for the HERC */
332 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
333 		val64 = XGE_HAL_STAT_BYTE_CNT(0x320);
334 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
335 		    val64, &bar0->stat_byte_cnt);
336 	}
337 
338 #ifdef XGE_HAL_HERC_EMULATION
339 	/*
340 	 *  The clocks in the emulator are running ~1000 times slower
341 	 *  than real world, so the stats transfer will occur ~1000
342 	 *  times less frequent. STAT_CFG.STAT_TRSF_PERIOD should be
343 	 *  set to 0x20C for Hercules emulation (stats transferred
344 	 *  every 0.5 sec).
345 	*/
346 
347 	val64 = (0x20C | XGE_HAL_STAT_CFG_STAT_RO |
348 		XGE_HAL_STAT_CFG_STAT_EN);
349 #else
350 	val64 = XGE_HAL_SET_UPDT_PERIOD(refresh_time_pci_clocks) |
351 		                XGE_HAL_STAT_CFG_STAT_RO |
352 				XGE_HAL_STAT_CFG_STAT_EN;
353 #endif
354 
355 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
356 		val64, &bar0->stat_cfg);
357 
358 	xge_debug_stats(XGE_TRACE, "stats enabled at 0x"XGE_OS_LLXFMT,
359 		 (unsigned long long)stats->dma_addr);
360 
361 	stats->is_enabled = 1;
362 }
363 
364 /*
365  * __hal_stats_pcim_update_latest - Update hw ER stats counters, based on the
366  * real hardware maintained counters and the stored "reset" values.
367  */
368 static void
369 __hal_stats_pcim_update_latest(xge_hal_device_h devh)
370 {
371 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
372 	int i;
373 
374 #define set_latest_stat_link_cnt(_link, _p)				      \
375         hldev->stats.pcim_info_latest->link_info[_link]._p =		      \
376 	((hldev->stats.pcim_info->link_info[_link]._p >=	              \
377 		hldev->stats.pcim_info_saved->link_info[_link]._p) ?	      \
378 		hldev->stats.pcim_info->link_info[_link]._p -		      \
379 			hldev->stats.pcim_info_saved->link_info[_link]._p :   \
380 		((-1) - hldev->stats.pcim_info_saved->link_info[_link]._p) +  \
381 			hldev->stats.pcim_info->link_info[_link]._p)
382 
383 
384 #define set_latest_stat_aggr_cnt(_aggr, _p)				      \
385         hldev->stats.pcim_info_latest->aggr_info[_aggr]._p =		      \
386 	((hldev->stats.pcim_info->aggr_info[_aggr]._p >=		      \
387 		hldev->stats.pcim_info_saved->aggr_info[_aggr]._p) ?	      \
388 		hldev->stats.pcim_info->aggr_info[_aggr]._p -		      \
389 			hldev->stats.pcim_info_saved->aggr_info[_aggr]._p :   \
390 		((-1) - hldev->stats.pcim_info_saved->aggr_info[_aggr]._p) +  \
391 			hldev->stats.pcim_info->aggr_info[_aggr]._p)
392 
393 
394 	for (i = 0; i < XGE_HAL_MAC_LINKS; i++) {
395 		set_latest_stat_link_cnt(i, tx_frms);
396 		set_latest_stat_link_cnt(i, tx_ttl_eth_octets);
397 		set_latest_stat_link_cnt(i, tx_data_octets);
398 		set_latest_stat_link_cnt(i, tx_mcst_frms);
399 		set_latest_stat_link_cnt(i, tx_bcst_frms);
400 		set_latest_stat_link_cnt(i, tx_ucst_frms);
401 		set_latest_stat_link_cnt(i, tx_tagged_frms);
402 		set_latest_stat_link_cnt(i, tx_vld_ip);
403 		set_latest_stat_link_cnt(i, tx_vld_ip_octets);
404 		set_latest_stat_link_cnt(i, tx_icmp);
405 		set_latest_stat_link_cnt(i, tx_tcp);
406 		set_latest_stat_link_cnt(i, tx_rst_tcp);
407 		set_latest_stat_link_cnt(i, tx_udp);
408 		set_latest_stat_link_cnt(i, tx_unknown_protocol);
409 		set_latest_stat_link_cnt(i, tx_parse_error);
410 		set_latest_stat_link_cnt(i, tx_pause_ctrl_frms);
411 		set_latest_stat_link_cnt(i, tx_lacpdu_frms);
412 		set_latest_stat_link_cnt(i, tx_marker_pdu_frms);
413 		set_latest_stat_link_cnt(i, tx_marker_resp_pdu_frms);
414 		set_latest_stat_link_cnt(i, tx_drop_ip);
415 		set_latest_stat_link_cnt(i, tx_xgmii_char1_match);
416 		set_latest_stat_link_cnt(i, tx_xgmii_char2_match);
417 		set_latest_stat_link_cnt(i, tx_xgmii_column1_match);
418 		set_latest_stat_link_cnt(i, tx_xgmii_column2_match);
419 		set_latest_stat_link_cnt(i, tx_drop_frms);
420 		set_latest_stat_link_cnt(i, tx_any_err_frms);
421 		set_latest_stat_link_cnt(i, rx_ttl_frms);
422 		set_latest_stat_link_cnt(i, rx_vld_frms);
423 		set_latest_stat_link_cnt(i, rx_offld_frms);
424 		set_latest_stat_link_cnt(i, rx_ttl_eth_octets);
425 		set_latest_stat_link_cnt(i, rx_data_octets);
426 		set_latest_stat_link_cnt(i, rx_offld_octets);
427 		set_latest_stat_link_cnt(i, rx_vld_mcst_frms);
428 		set_latest_stat_link_cnt(i, rx_vld_bcst_frms);
429 		set_latest_stat_link_cnt(i, rx_accepted_ucst_frms);
430 		set_latest_stat_link_cnt(i, rx_accepted_nucst_frms);
431 		set_latest_stat_link_cnt(i, rx_tagged_frms);
432 		set_latest_stat_link_cnt(i, rx_long_frms);
433 		set_latest_stat_link_cnt(i, rx_usized_frms);
434 		set_latest_stat_link_cnt(i, rx_osized_frms);
435 		set_latest_stat_link_cnt(i, rx_frag_frms);
436 		set_latest_stat_link_cnt(i, rx_jabber_frms);
437 		set_latest_stat_link_cnt(i, rx_ttl_64_frms);
438 		set_latest_stat_link_cnt(i, rx_ttl_65_127_frms);
439 		set_latest_stat_link_cnt(i, rx_ttl_128_255_frms);
440 		set_latest_stat_link_cnt(i, rx_ttl_256_511_frms);
441 		set_latest_stat_link_cnt(i, rx_ttl_512_1023_frms);
442 		set_latest_stat_link_cnt(i, rx_ttl_1024_1518_frms);
443 		set_latest_stat_link_cnt(i, rx_ttl_1519_4095_frms);
444 		set_latest_stat_link_cnt(i, rx_ttl_40956_8191_frms);
445 		set_latest_stat_link_cnt(i, rx_ttl_8192_max_frms);
446 		set_latest_stat_link_cnt(i, rx_ttl_gt_max_frms);
447 		set_latest_stat_link_cnt(i, rx_ip);
448 		set_latest_stat_link_cnt(i, rx_ip_octets);
449 		set_latest_stat_link_cnt(i, rx_hdr_err_ip);
450 		set_latest_stat_link_cnt(i, rx_icmp);
451 		set_latest_stat_link_cnt(i, rx_tcp);
452 		set_latest_stat_link_cnt(i, rx_udp);
453 		set_latest_stat_link_cnt(i, rx_err_tcp);
454 		set_latest_stat_link_cnt(i, rx_pause_cnt);
455 		set_latest_stat_link_cnt(i, rx_pause_ctrl_frms);
456 		set_latest_stat_link_cnt(i, rx_unsup_ctrl_frms);
457 		set_latest_stat_link_cnt(i, rx_in_rng_len_err_frms);
458 		set_latest_stat_link_cnt(i, rx_out_rng_len_err_frms);
459 		set_latest_stat_link_cnt(i, rx_drop_frms);
460 		set_latest_stat_link_cnt(i, rx_discarded_frms);
461 		set_latest_stat_link_cnt(i, rx_drop_ip);
462 		set_latest_stat_link_cnt(i, rx_err_drp_udp);
463 		set_latest_stat_link_cnt(i, rx_lacpdu_frms);
464 		set_latest_stat_link_cnt(i, rx_marker_pdu_frms);
465 		set_latest_stat_link_cnt(i, rx_marker_resp_pdu_frms);
466 		set_latest_stat_link_cnt(i, rx_unknown_pdu_frms);
467 		set_latest_stat_link_cnt(i, rx_illegal_pdu_frms);
468 		set_latest_stat_link_cnt(i, rx_fcs_discard);
469 		set_latest_stat_link_cnt(i, rx_len_discard);
470 		set_latest_stat_link_cnt(i, rx_pf_discard);
471 		set_latest_stat_link_cnt(i, rx_trash_discard);
472 		set_latest_stat_link_cnt(i, rx_rts_discard);
473 		set_latest_stat_link_cnt(i, rx_wol_discard);
474 		set_latest_stat_link_cnt(i, rx_red_discard);
475 		set_latest_stat_link_cnt(i, rx_ingm_full_discard);
476 		set_latest_stat_link_cnt(i, rx_xgmii_data_err_cnt);
477 		set_latest_stat_link_cnt(i, rx_xgmii_ctrl_err_cnt);
478 		set_latest_stat_link_cnt(i, rx_xgmii_err_sym);
479 		set_latest_stat_link_cnt(i, rx_xgmii_char1_match);
480 		set_latest_stat_link_cnt(i, rx_xgmii_char2_match);
481 		set_latest_stat_link_cnt(i, rx_xgmii_column1_match);
482 		set_latest_stat_link_cnt(i, rx_xgmii_column2_match);
483 		set_latest_stat_link_cnt(i, rx_local_fault);
484 		set_latest_stat_link_cnt(i, rx_remote_fault);
485 		set_latest_stat_link_cnt(i, rx_queue_full);
486 	}
487 
488 	for (i = 0; i < XGE_HAL_MAC_AGGREGATORS; i++) {
489 		set_latest_stat_aggr_cnt(i, tx_frms);
490 		set_latest_stat_aggr_cnt(i, tx_mcst_frms);
491 		set_latest_stat_aggr_cnt(i, tx_bcst_frms);
492 		set_latest_stat_aggr_cnt(i, tx_discarded_frms);
493 		set_latest_stat_aggr_cnt(i, tx_errored_frms);
494 		set_latest_stat_aggr_cnt(i, rx_frms);
495 		set_latest_stat_aggr_cnt(i, rx_data_octets);
496 		set_latest_stat_aggr_cnt(i, rx_mcst_frms);
497 		set_latest_stat_aggr_cnt(i, rx_bcst_frms);
498 		set_latest_stat_aggr_cnt(i, rx_discarded_frms);
499 		set_latest_stat_aggr_cnt(i, rx_errored_frms);
500 		set_latest_stat_aggr_cnt(i, rx_unknown_protocol_frms);
501 	}
502 	return;
503 }
504 
505 /*
506  * __hal_stats_update_latest - Update hw stats counters, based on the real
507  * hardware maintained counters and the stored "reset" values.
508  */
509 static void
510 __hal_stats_update_latest(xge_hal_device_h devh)
511 {
512 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
513 
514 #define set_latest_stat_cnt(_dev, _p)                                   \
515         hldev->stats.hw_info_latest._p =                                \
516 	((hldev->stats.hw_info->_p >= hldev->stats.hw_info_saved._p) ?  \
517           hldev->stats.hw_info->_p - hldev->stats.hw_info_saved._p :    \
518 	  ((-1) - hldev->stats.hw_info_saved._p) + hldev->stats.hw_info->_p)
519 
520 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_TITAN) {
521 		__hal_stats_pcim_update_latest(devh);
522 		return;
523 	}
524 
525 	/* Tx MAC statistics counters. */
526 	set_latest_stat_cnt(hldev, tmac_frms);
527 	set_latest_stat_cnt(hldev, tmac_data_octets);
528 	set_latest_stat_cnt(hldev, tmac_drop_frms);
529 	set_latest_stat_cnt(hldev, tmac_mcst_frms);
530 	set_latest_stat_cnt(hldev, tmac_bcst_frms);
531 	set_latest_stat_cnt(hldev, tmac_pause_ctrl_frms);
532 	set_latest_stat_cnt(hldev, tmac_ttl_octets);
533 	set_latest_stat_cnt(hldev, tmac_ucst_frms);
534 	set_latest_stat_cnt(hldev, tmac_nucst_frms);
535 	set_latest_stat_cnt(hldev, tmac_any_err_frms);
536 	set_latest_stat_cnt(hldev, tmac_ttl_less_fb_octets);
537 	set_latest_stat_cnt(hldev, tmac_vld_ip_octets);
538 	set_latest_stat_cnt(hldev, tmac_vld_ip);
539 	set_latest_stat_cnt(hldev, tmac_drop_ip);
540 	set_latest_stat_cnt(hldev, tmac_icmp);
541 	set_latest_stat_cnt(hldev, tmac_rst_tcp);
542 	set_latest_stat_cnt(hldev, tmac_tcp);
543 	set_latest_stat_cnt(hldev, tmac_udp);
544 	set_latest_stat_cnt(hldev, reserved_0);
545 
546 	/* Rx MAC Statistics counters. */
547 	set_latest_stat_cnt(hldev, rmac_vld_frms);
548 	set_latest_stat_cnt(hldev, rmac_data_octets);
549 	set_latest_stat_cnt(hldev, rmac_fcs_err_frms);
550 	set_latest_stat_cnt(hldev, rmac_drop_frms);
551 	set_latest_stat_cnt(hldev, rmac_vld_mcst_frms);
552 	set_latest_stat_cnt(hldev, rmac_vld_bcst_frms);
553 	set_latest_stat_cnt(hldev, rmac_in_rng_len_err_frms);
554 	set_latest_stat_cnt(hldev, rmac_out_rng_len_err_frms);
555 	set_latest_stat_cnt(hldev, rmac_long_frms);
556 	set_latest_stat_cnt(hldev, rmac_pause_ctrl_frms);
557 	set_latest_stat_cnt(hldev, rmac_unsup_ctrl_frms);
558 	set_latest_stat_cnt(hldev, rmac_ttl_octets);
559 	set_latest_stat_cnt(hldev, rmac_accepted_ucst_frms);
560 	set_latest_stat_cnt(hldev, rmac_accepted_nucst_frms);
561 	set_latest_stat_cnt(hldev, rmac_discarded_frms);
562 	set_latest_stat_cnt(hldev, rmac_drop_events);
563 	set_latest_stat_cnt(hldev, reserved_1);
564 	set_latest_stat_cnt(hldev, rmac_ttl_less_fb_octets);
565 	set_latest_stat_cnt(hldev, rmac_ttl_frms);
566 	set_latest_stat_cnt(hldev, reserved_2);
567 	set_latest_stat_cnt(hldev, reserved_3);
568 	set_latest_stat_cnt(hldev, rmac_usized_frms);
569 	set_latest_stat_cnt(hldev, rmac_osized_frms);
570 	set_latest_stat_cnt(hldev, rmac_frag_frms);
571 	set_latest_stat_cnt(hldev, rmac_jabber_frms);
572 	set_latest_stat_cnt(hldev, reserved_4);
573 	set_latest_stat_cnt(hldev, rmac_ttl_64_frms);
574 	set_latest_stat_cnt(hldev, rmac_ttl_65_127_frms);
575 	set_latest_stat_cnt(hldev, reserved_5);
576 	set_latest_stat_cnt(hldev, rmac_ttl_128_255_frms);
577 	set_latest_stat_cnt(hldev, rmac_ttl_256_511_frms);
578 	set_latest_stat_cnt(hldev, reserved_6);
579 	set_latest_stat_cnt(hldev, rmac_ttl_512_1023_frms);
580 	set_latest_stat_cnt(hldev, rmac_ttl_1024_1518_frms);
581 	set_latest_stat_cnt(hldev, reserved_7);
582 	set_latest_stat_cnt(hldev, rmac_ip);
583 	set_latest_stat_cnt(hldev, rmac_ip_octets);
584 	set_latest_stat_cnt(hldev, rmac_hdr_err_ip);
585 	set_latest_stat_cnt(hldev, rmac_drop_ip);
586 	set_latest_stat_cnt(hldev, rmac_icmp);
587 	set_latest_stat_cnt(hldev, reserved_8);
588 	set_latest_stat_cnt(hldev, rmac_tcp);
589 	set_latest_stat_cnt(hldev, rmac_udp);
590 	set_latest_stat_cnt(hldev, rmac_err_drp_udp);
591 	set_latest_stat_cnt(hldev, rmac_xgmii_err_sym);
592 	set_latest_stat_cnt(hldev, rmac_frms_q0);
593 	set_latest_stat_cnt(hldev, rmac_frms_q1);
594 	set_latest_stat_cnt(hldev, rmac_frms_q2);
595 	set_latest_stat_cnt(hldev, rmac_frms_q3);
596 	set_latest_stat_cnt(hldev, rmac_frms_q4);
597 	set_latest_stat_cnt(hldev, rmac_frms_q5);
598 	set_latest_stat_cnt(hldev, rmac_frms_q6);
599 	set_latest_stat_cnt(hldev, rmac_frms_q7);
600 	set_latest_stat_cnt(hldev, rmac_full_q0);
601 	set_latest_stat_cnt(hldev, rmac_full_q1);
602 	set_latest_stat_cnt(hldev, rmac_full_q2);
603 	set_latest_stat_cnt(hldev, rmac_full_q3);
604 	set_latest_stat_cnt(hldev, rmac_full_q4);
605 	set_latest_stat_cnt(hldev, rmac_full_q5);
606 	set_latest_stat_cnt(hldev, rmac_full_q6);
607 	set_latest_stat_cnt(hldev, rmac_full_q7);
608 	set_latest_stat_cnt(hldev, rmac_pause_cnt);
609 	set_latest_stat_cnt(hldev, reserved_9);
610 	set_latest_stat_cnt(hldev, rmac_xgmii_data_err_cnt);
611 	set_latest_stat_cnt(hldev, rmac_xgmii_ctrl_err_cnt);
612 	set_latest_stat_cnt(hldev, rmac_accepted_ip);
613 	set_latest_stat_cnt(hldev, rmac_err_tcp);
614 
615 	/* PCI/PCI-X Read transaction statistics. */
616 	set_latest_stat_cnt(hldev, rd_req_cnt);
617 	set_latest_stat_cnt(hldev, new_rd_req_cnt);
618 	set_latest_stat_cnt(hldev, new_rd_req_rtry_cnt);
619 	set_latest_stat_cnt(hldev, rd_rtry_cnt);
620 	set_latest_stat_cnt(hldev, wr_rtry_rd_ack_cnt);
621 
622 	/* PCI/PCI-X write transaction statistics. */
623 	set_latest_stat_cnt(hldev, wr_req_cnt);
624 	set_latest_stat_cnt(hldev, new_wr_req_cnt);
625 	set_latest_stat_cnt(hldev, new_wr_req_rtry_cnt);
626 	set_latest_stat_cnt(hldev, wr_rtry_cnt);
627 	set_latest_stat_cnt(hldev, wr_disc_cnt);
628 	set_latest_stat_cnt(hldev, rd_rtry_wr_ack_cnt);
629 
630 	/* DMA Transaction statistics. */
631 	set_latest_stat_cnt(hldev, txp_wr_cnt);
632 	set_latest_stat_cnt(hldev, txd_rd_cnt);
633 	set_latest_stat_cnt(hldev, txd_wr_cnt);
634 	set_latest_stat_cnt(hldev, rxd_rd_cnt);
635 	set_latest_stat_cnt(hldev, rxd_wr_cnt);
636 	set_latest_stat_cnt(hldev, txf_rd_cnt);
637 	set_latest_stat_cnt(hldev, rxf_wr_cnt);
638 
639 	/* Enhanced Herc statistics */
640 	set_latest_stat_cnt(hldev, tmac_frms_oflow);
641 	set_latest_stat_cnt(hldev, tmac_data_octets_oflow);
642 	set_latest_stat_cnt(hldev, tmac_mcst_frms_oflow);
643 	set_latest_stat_cnt(hldev, tmac_bcst_frms_oflow);
644 	set_latest_stat_cnt(hldev, tmac_ttl_octets_oflow);
645 	set_latest_stat_cnt(hldev, tmac_ucst_frms_oflow);
646 	set_latest_stat_cnt(hldev, tmac_nucst_frms_oflow);
647 	set_latest_stat_cnt(hldev, tmac_any_err_frms_oflow);
648 	set_latest_stat_cnt(hldev, tmac_vlan_frms);
649 	set_latest_stat_cnt(hldev, tmac_vld_ip_oflow);
650 	set_latest_stat_cnt(hldev, tmac_drop_ip_oflow);
651 	set_latest_stat_cnt(hldev, tmac_icmp_oflow);
652 	set_latest_stat_cnt(hldev, tmac_rst_tcp_oflow);
653 	set_latest_stat_cnt(hldev, tmac_udp_oflow);
654 	set_latest_stat_cnt(hldev, tpa_unknown_protocol);
655 	set_latest_stat_cnt(hldev, tpa_parse_failure);
656 	set_latest_stat_cnt(hldev, rmac_vld_frms_oflow);
657 	set_latest_stat_cnt(hldev, rmac_data_octets_oflow);
658 	set_latest_stat_cnt(hldev, rmac_vld_mcst_frms_oflow);
659 	set_latest_stat_cnt(hldev, rmac_vld_bcst_frms_oflow);
660 	set_latest_stat_cnt(hldev, rmac_ttl_octets_oflow);
661 	set_latest_stat_cnt(hldev, rmac_accepted_ucst_frms_oflow);
662 	set_latest_stat_cnt(hldev, rmac_accepted_nucst_frms_oflow);
663 	set_latest_stat_cnt(hldev, rmac_discarded_frms_oflow);
664 	set_latest_stat_cnt(hldev, rmac_drop_events_oflow);
665 	set_latest_stat_cnt(hldev, rmac_usized_frms_oflow);
666 	set_latest_stat_cnt(hldev, rmac_osized_frms_oflow);
667 	set_latest_stat_cnt(hldev, rmac_frag_frms_oflow);
668 	set_latest_stat_cnt(hldev, rmac_jabber_frms_oflow);
669 	set_latest_stat_cnt(hldev, rmac_ip_oflow);
670 	set_latest_stat_cnt(hldev, rmac_drop_ip_oflow);
671 	set_latest_stat_cnt(hldev, rmac_icmp_oflow);
672 	set_latest_stat_cnt(hldev, rmac_udp_oflow);
673 	set_latest_stat_cnt(hldev, rmac_err_drp_udp_oflow);
674 	set_latest_stat_cnt(hldev, rmac_pause_cnt_oflow);
675 	set_latest_stat_cnt(hldev, rmac_ttl_1519_4095_frms);
676 	set_latest_stat_cnt(hldev, rmac_ttl_4096_8191_frms);
677 	set_latest_stat_cnt(hldev, rmac_ttl_8192_max_frms);
678 	set_latest_stat_cnt(hldev, rmac_ttl_gt_max_frms);
679 	set_latest_stat_cnt(hldev, rmac_osized_alt_frms);
680 	set_latest_stat_cnt(hldev, rmac_jabber_alt_frms);
681 	set_latest_stat_cnt(hldev, rmac_gt_max_alt_frms);
682 	set_latest_stat_cnt(hldev, rmac_vlan_frms);
683 	set_latest_stat_cnt(hldev, rmac_fcs_discard);
684 	set_latest_stat_cnt(hldev, rmac_len_discard);
685 	set_latest_stat_cnt(hldev, rmac_da_discard);
686 	set_latest_stat_cnt(hldev, rmac_pf_discard);
687 	set_latest_stat_cnt(hldev, rmac_rts_discard);
688 	set_latest_stat_cnt(hldev, rmac_red_discard);
689 	set_latest_stat_cnt(hldev, rmac_ingm_full_discard);
690 	set_latest_stat_cnt(hldev, rmac_accepted_ip_oflow);
691 	set_latest_stat_cnt(hldev, link_fault_cnt);
692 }
693 
694 /**
695  * xge_hal_stats_hw - Get HW device statistics.
696  * @devh: HAL device handle.
697  * @hw_info: Xframe statistic counters. See xge_hal_stats_hw_info_t.
698  *           Returned by HAL.
699  *
700  * Get device and HAL statistics. The latter is part of the in-host statistics
701  * that HAL maintains for _that_ device.
702  *
703  * Returns: XGE_HAL_OK - success.
704  * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
705  * currently available.
706  *
707  * See also: xge_hal_status_e{}.
708  */
709 xge_hal_status_e
710 xge_hal_stats_hw(xge_hal_device_h devh, xge_hal_stats_hw_info_t **hw_info)
711 {
712 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
713 
714 	xge_assert(xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN)
715 
716 	if (!hldev->stats.is_initialized ||
717 	    !hldev->stats.is_enabled) {
718 		*hw_info = NULL;
719 		return XGE_HAL_INF_STATS_IS_NOT_READY;
720 	}
721 
722 #if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_STATS_STREAMING)
723 	xge_os_dma_sync(hldev->pdev,
724 	              hldev->stats.hw_info_dmah,
725 		      hldev->stats.dma_addr,
726 		      0,
727 		      sizeof(xge_hal_stats_hw_info_t),
728 		      XGE_OS_DMA_DIR_FROMDEVICE);
729 #endif
730 
731         /*
732 	 * update hw counters, taking into account
733 	 * the "reset" or "saved"
734 	 * values
735 	 */
736 	__hal_stats_update_latest(devh);
737 
738 	/*
739 	 * statistics HW bug fixups for Xena and Herc
740 	 */
741 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA ||
742 	    xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
743 		u64 mcst, bcst;
744 		xge_hal_stats_hw_info_t *hwsta = &hldev->stats.hw_info_latest;
745 
746 		mcst = ((u64)hwsta->rmac_vld_mcst_frms_oflow << 32) |
747 			hwsta->rmac_vld_mcst_frms;
748 
749 		bcst = ((u64)hwsta->rmac_vld_bcst_frms_oflow << 32) |
750 			hwsta->rmac_vld_bcst_frms;
751 
752 		mcst -= bcst;
753 
754 		hwsta->rmac_vld_mcst_frms_oflow = (u32)(mcst >> 32);
755 		hwsta->rmac_vld_mcst_frms = (u32)mcst;
756 	}
757 
758 	*hw_info = &hldev->stats.hw_info_latest;
759 
760 	return XGE_HAL_OK;
761 }
762 
763 /**
764  * xge_hal_stats_pcim - Get HW device statistics.
765  * @devh: HAL device handle.
766  * @hw_info: Xframe statistic counters. See xge_hal_stats_pcim_info_t.
767  *
768  * Returns: XGE_HAL_OK - success.
769  * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
770  * currently available.
771  *
772  * See also: xge_hal_status_e{}.
773  */
774 xge_hal_status_e
775 xge_hal_stats_pcim(xge_hal_device_h devh, xge_hal_stats_pcim_info_t **hw_info)
776 {
777 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
778 
779 	xge_assert(xge_hal_device_check_id(hldev) == XGE_HAL_CARD_TITAN)
780 
781 	if (!hldev->stats.is_initialized ||
782 	    !hldev->stats.is_enabled) {
783 		*hw_info = NULL;
784 		return XGE_HAL_INF_STATS_IS_NOT_READY;
785 	}
786 
787 #if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_STATS_STREAMING)
788 	xge_os_dma_sync(hldev->pdev,
789 	              hldev->stats.hw_info_dmah,
790 		      hldev->stats.dma_addr,
791 		      0,
792 		      sizeof(xge_hal_stats_pcim_info_t),
793 		      XGE_OS_DMA_DIR_FROMDEVICE);
794 #endif
795 
796         /*
797 	 * update hw counters, taking into account
798 	 * the "reset" or "saved"
799 	 * values
800 	 */
801 	__hal_stats_pcim_update_latest(devh);
802 
803 	*hw_info = hldev->stats.pcim_info_latest;
804 
805 	return XGE_HAL_OK;
806 }
807 
808 /**
809  * xge_hal_stats_device - Get HAL statistics.
810  * @devh: HAL device handle.
811  * @hw_info: Xframe statistic counters. See xge_hal_stats_hw_info_t.
812  *           Returned by HAL.
813  * @device_info: HAL statistics. See xge_hal_stats_device_info_t.
814  *               Returned by HAL.
815  *
816  * Get device and HAL statistics. The latter is part of the in-host statistics
817  * that HAL maintains for _that_ device.
818  *
819  * Returns: XGE_HAL_OK - success.
820  * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
821  * currently available.
822  *
823  * See also: xge_hal_status_e{}.
824  */
825 xge_hal_status_e
826 xge_hal_stats_device(xge_hal_device_h devh,
827 		xge_hal_stats_device_info_t **device_info)
828 {
829 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
830 
831 	if (!hldev->stats.is_initialized ||
832 	    !hldev->stats.is_enabled) {
833 		*device_info = NULL;
834 		return XGE_HAL_INF_STATS_IS_NOT_READY;
835 	}
836 
837 	hldev->stats.sw_dev_info_stats.traffic_intr_cnt =
838 		hldev->stats.sw_dev_info_stats.total_intr_cnt -
839 			hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt;
840 
841 	*device_info = &hldev->stats.sw_dev_info_stats;
842 
843 	return XGE_HAL_OK;
844 }
845 
846 /**
847  * xge_hal_stats_channel - Get channel statistics.
848  * @channelh: Channel handle.
849  * @channel_info: HAL channel statistic counters.
850  *                See xge_hal_stats_channel_info_t{}. Returned by HAL.
851  *
852  * Retrieve statistics of a particular HAL channel. This includes, for instance,
853  * number of completions per interrupt, number of traffic interrupts, etc.
854  *
855  * Returns: XGE_HAL_OK - success.
856  * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
857  * currently available.
858  *
859  * See also: xge_hal_status_e{}.
860  */
861 xge_hal_status_e
862 xge_hal_stats_channel(xge_hal_channel_h channelh,
863 		xge_hal_stats_channel_info_t **channel_info)
864 {
865 	xge_hal_stats_hw_info_t	*latest;
866 	xge_hal_channel_t *channel;
867 	xge_hal_device_t *hldev;
868 
869 	channel = (xge_hal_channel_t *)channelh;
870 	if ((channel == NULL) || (channel->magic != XGE_HAL_MAGIC)) {
871 		return XGE_HAL_ERR_INVALID_DEVICE;
872 	}
873 	hldev = (xge_hal_device_t *)channel->devh;
874 	if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) {
875 		return XGE_HAL_ERR_INVALID_DEVICE;
876 	}
877 
878 	if (!hldev->stats.is_initialized ||
879 	    !hldev->stats.is_enabled ||
880 	    !channel->is_open) {
881 		*channel_info = NULL;
882 		return XGE_HAL_INF_STATS_IS_NOT_READY;
883 	}
884 
885 	hldev->stats.sw_dev_info_stats.traffic_intr_cnt =
886 		hldev->stats.sw_dev_info_stats.total_intr_cnt -
887 			hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt;
888 
889 	if (hldev->stats.sw_dev_info_stats.traffic_intr_cnt) {
890 		int rxcnt = hldev->stats.sw_dev_info_stats.rx_traffic_intr_cnt;
891 		int txcnt = hldev->stats.sw_dev_info_stats.tx_traffic_intr_cnt;
892 		if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
893 			if (!txcnt)
894 				txcnt = 1;
895 			channel->stats.avg_compl_per_intr_cnt =
896 				channel->stats.total_compl_cnt / txcnt;
897 		} else if (channel->type == XGE_HAL_CHANNEL_TYPE_RING &&
898 			   !hldev->config.bimodal_interrupts) {
899 			if (!rxcnt)
900 				rxcnt = 1;
901 			channel->stats.avg_compl_per_intr_cnt =
902 				channel->stats.total_compl_cnt / rxcnt;
903 		}
904 		if (channel->stats.avg_compl_per_intr_cnt == 0) {
905 			/* to not confuse user */
906 			channel->stats.avg_compl_per_intr_cnt = 1;
907 		}
908 	}
909 
910 	(void) xge_hal_stats_hw(hldev, &latest);
911 
912 	if (channel->stats.total_posts) {
913 		channel->stats.avg_buffers_per_post =
914 			channel->stats.total_buffers /
915 				channel->stats.total_posts;
916 #ifdef XGE_OS_PLATFORM_64BIT
917 	        if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
918 		        channel->stats.avg_post_size =
919 			(u32)(latest->tmac_ttl_less_fb_octets /
920 				channel->stats.total_posts);
921 	        }
922 #endif
923 	}
924 
925 #ifdef XGE_OS_PLATFORM_64BIT
926 	if (channel->stats.total_buffers &&
927 	    channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
928 		channel->stats.avg_buffer_size =
929 			(u32)(latest->tmac_ttl_less_fb_octets /
930 				channel->stats.total_buffers);
931 	}
932 #endif
933 
934 	*channel_info = &channel->stats;
935 	return XGE_HAL_OK;
936 }
937 
938 /**
939  * xge_hal_stats_reset - Reset (zero-out) device statistics
940  * @devh: HAL device handle.
941  *
942  * Reset all device statistics.
943  * Returns: XGE_HAL_OK - success.
944  * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
945  * currently available.
946  *
947  * See also: xge_hal_status_e{}, xge_hal_stats_channel_info_t{},
948  * xge_hal_stats_sw_err_t{}, xge_hal_stats_device_info_t{}.
949  */
950 xge_hal_status_e
951 xge_hal_stats_reset(xge_hal_device_h devh)
952 {
953 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
954 
955 	if (!hldev->stats.is_initialized ||
956 	    !hldev->stats.is_enabled) {
957 		return XGE_HAL_INF_STATS_IS_NOT_READY;
958 	}
959 
960 	/* save hw stats to calculate the after-reset values */
961 	__hal_stats_save(&hldev->stats);
962 
963 	/* zero-out driver-maintained stats, don't reset the saved */
964         __hal_stats_soft_reset(hldev, 0);
965 
966 	return XGE_HAL_OK;
967 }
968 
969 /*
970  * __hal_stats_soft_reset - Reset software-maintained statistics.
971  */
972 void
973 __hal_stats_soft_reset (xge_hal_device_h devh, int reset_all)
974 {
975 	xge_list_t *item;
976 	xge_hal_channel_t *channel;
977 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
978 
979         if (reset_all)  {
980 		if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) {
981 			xge_os_memzero(&hldev->stats.hw_info_saved,
982 		               sizeof(xge_hal_stats_hw_info_t));
983 			xge_os_memzero(&hldev->stats.hw_info_latest,
984 		               sizeof(xge_hal_stats_hw_info_t));
985 		} else {
986 			xge_os_memzero(&hldev->stats.pcim_info_saved,
987 		               sizeof(xge_hal_stats_pcim_info_t));
988 			xge_os_memzero(&hldev->stats.pcim_info_latest,
989 		               sizeof(xge_hal_stats_pcim_info_t));
990 		}
991         }
992 
993 	/* Reset the "soft" error and informational statistics */
994 	xge_os_memzero(&hldev->stats.sw_dev_err_stats,
995 	             sizeof(xge_hal_stats_sw_err_t));
996 	xge_os_memzero(&hldev->stats.sw_dev_info_stats,
997 	             sizeof(xge_hal_stats_device_info_t));
998 
999 	/* for each Rx channel */
1000 	xge_list_for_each(item, &hldev->ring_channels) {
1001 		channel = xge_container_of(item, xge_hal_channel_t, item);
1002 		xge_os_memzero(&channel->stats,
1003 		             sizeof(xge_hal_stats_channel_info_t));
1004 	}
1005 
1006 	/* for each Tx channel */
1007 	xge_list_for_each(item, &hldev->fifo_channels) {
1008 		channel = xge_container_of(item, xge_hal_channel_t, item);
1009 		xge_os_memzero(&channel->stats,
1010 		             sizeof(xge_hal_stats_channel_info_t));
1011 	}
1012 }
1013 
1014