xref: /onnv-gate/usr/src/uts/common/io/xge/hal/xgehal/xgehal-stats.c (revision 6937:a5e2c8b5c817)
11256Syl150051 /*
21256Syl150051  * CDDL HEADER START
31256Syl150051  *
41256Syl150051  * The contents of this file are subject to the terms of the
51256Syl150051  * Common Development and Distribution License (the "License").
61256Syl150051  * You may not use this file except in compliance with the License.
71256Syl150051  *
81256Syl150051  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91256Syl150051  * or http://www.opensolaris.org/os/licensing.
101256Syl150051  * See the License for the specific language governing permissions
111256Syl150051  * and limitations under the License.
121256Syl150051  *
131256Syl150051  * When distributing Covered Code, include this CDDL HEADER in each
141256Syl150051  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151256Syl150051  * If applicable, add the following below this CDDL HEADER, with the
161256Syl150051  * fields enclosed by brackets "[]" replaced with your own identifying
171256Syl150051  * information: Portions Copyright [yyyy] [name of copyright owner]
181256Syl150051  *
191256Syl150051  * CDDL HEADER END
201256Syl150051  *
213115Syl150051  * Copyright (c) 2002-2006 Neterion, Inc.
221256Syl150051  */
231256Syl150051 
241256Syl150051 #include "xgehal-stats.h"
251256Syl150051 #include "xgehal-device.h"
261256Syl150051 
271256Syl150051 /*
281256Syl150051  * __hal_stats_initialize
291256Syl150051  * @stats: xge_hal_stats_t structure that contains, in particular,
301256Syl150051  *         Xframe hw stat counters.
311256Syl150051  * @devh: HAL device handle.
321256Syl150051  *
331256Syl150051  * Initialize per-device statistics object.
341256Syl150051  * See also: xge_hal_stats_getinfo(), xge_hal_status_e{}.
351256Syl150051  */
361256Syl150051 xge_hal_status_e
__hal_stats_initialize(xge_hal_stats_t * stats,xge_hal_device_h devh)371256Syl150051 __hal_stats_initialize (xge_hal_stats_t *stats, xge_hal_device_h devh)
381256Syl150051 {
391256Syl150051 	int dma_flags;
401256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
411256Syl150051 
421256Syl150051 	xge_assert(!stats->is_initialized);
431256Syl150051 
441256Syl150051 	dma_flags = XGE_OS_DMA_CACHELINE_ALIGNED;
451256Syl150051 #ifdef XGE_HAL_DMA_STATS_CONSISTENT
461256Syl150051 	dma_flags |= XGE_OS_DMA_CONSISTENT;
471256Syl150051 #else
481256Syl150051 	dma_flags |= XGE_OS_DMA_STREAMING;
491256Syl150051 #endif
50*6937Sxw161283 	if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) {
51*6937Sxw161283 		stats->hw_info =
52*6937Sxw161283 			(xge_hal_stats_hw_info_t *) xge_os_dma_malloc(
53*6937Sxw161283 					hldev->pdev,
54*6937Sxw161283 					sizeof(xge_hal_stats_hw_info_t),
55*6937Sxw161283 					dma_flags,
56*6937Sxw161283 					&stats->hw_info_dmah,
57*6937Sxw161283 					&stats->hw_info_dma_acch);
583115Syl150051 
59*6937Sxw161283 		if (stats->hw_info == NULL) {
60*6937Sxw161283 			xge_debug_stats(XGE_ERR, "%s", "can not DMA alloc");
61*6937Sxw161283 			return XGE_HAL_ERR_OUT_OF_MEMORY;
62*6937Sxw161283 		}
63*6937Sxw161283 		xge_os_memzero(stats->hw_info,
64*6937Sxw161283 			sizeof(xge_hal_stats_hw_info_t));
65*6937Sxw161283 		xge_os_memzero(&stats->hw_info_saved,
66*6937Sxw161283 			sizeof(xge_hal_stats_hw_info_t));
67*6937Sxw161283 		xge_os_memzero(&stats->hw_info_latest,
68*6937Sxw161283 			sizeof(xge_hal_stats_hw_info_t));
691256Syl150051 
70*6937Sxw161283 
711256Syl150051 
72*6937Sxw161283 		stats->dma_addr = xge_os_dma_map(hldev->pdev,
731256Syl150051 	                               stats->hw_info_dmah,
741256Syl150051 				       stats->hw_info,
751256Syl150051 				       sizeof(xge_hal_stats_hw_info_t),
761256Syl150051 				       XGE_OS_DMA_DIR_FROMDEVICE,
771256Syl150051 				       XGE_OS_DMA_CACHELINE_ALIGNED |
781256Syl150051 #ifdef XGE_HAL_DMA_STATS_CONSISTENT
791256Syl150051 				       XGE_OS_DMA_CONSISTENT
801256Syl150051 #else
811256Syl150051 			               XGE_OS_DMA_STREAMING
821256Syl150051 #endif
831256Syl150051                                        );
84*6937Sxw161283 		if (stats->dma_addr == XGE_OS_INVALID_DMA_ADDR) {
85*6937Sxw161283 			xge_debug_stats(XGE_ERR,
86*6937Sxw161283 				"can not map vaddr 0x"XGE_OS_LLXFMT" to DMA",
87*6937Sxw161283 				(unsigned long long)(ulong_t)stats->hw_info);
88*6937Sxw161283 			xge_os_dma_free(hldev->pdev,
891256Syl150051 			      stats->hw_info,
901256Syl150051 			      sizeof(xge_hal_stats_hw_info_t),
911256Syl150051 			      &stats->hw_info_dma_acch,
921256Syl150051 			      &stats->hw_info_dmah);
93*6937Sxw161283 			return XGE_HAL_ERR_OUT_OF_MAPPING;
94*6937Sxw161283 		}
951256Syl150051 	}
96*6937Sxw161283 	else {
97*6937Sxw161283 		stats->pcim_info_saved =
98*6937Sxw161283 			(xge_hal_stats_pcim_info_t *)xge_os_malloc(
99*6937Sxw161283 			hldev->pdev, sizeof(xge_hal_stats_pcim_info_t));
100*6937Sxw161283 		if (stats->pcim_info_saved == NULL) {
101*6937Sxw161283 			xge_debug_stats(XGE_ERR, "%s", "can not alloc");
102*6937Sxw161283 			return XGE_HAL_ERR_OUT_OF_MEMORY;
103*6937Sxw161283 		}
1041256Syl150051 
105*6937Sxw161283 		stats->pcim_info_latest =
106*6937Sxw161283 			(xge_hal_stats_pcim_info_t *)xge_os_malloc(
107*6937Sxw161283 			hldev->pdev, sizeof(xge_hal_stats_pcim_info_t));
108*6937Sxw161283 		if (stats->pcim_info_latest == NULL) {
109*6937Sxw161283 			xge_os_free(hldev->pdev, stats->pcim_info_saved,
110*6937Sxw161283 				sizeof(xge_hal_stats_pcim_info_t));
111*6937Sxw161283 			xge_debug_stats(XGE_ERR, "%s", "can not alloc");
112*6937Sxw161283 			return XGE_HAL_ERR_OUT_OF_MEMORY;
113*6937Sxw161283 		}
114*6937Sxw161283 
115*6937Sxw161283 		stats->pcim_info =
116*6937Sxw161283 			(xge_hal_stats_pcim_info_t *) xge_os_dma_malloc(
117*6937Sxw161283 					hldev->pdev,
118*6937Sxw161283 					sizeof(xge_hal_stats_pcim_info_t),
119*6937Sxw161283 					dma_flags,
120*6937Sxw161283 					&stats->hw_info_dmah,
121*6937Sxw161283 					&stats->hw_info_dma_acch);
122*6937Sxw161283 
123*6937Sxw161283 		if (stats->pcim_info == NULL) {
124*6937Sxw161283 			xge_os_free(hldev->pdev, stats->pcim_info_saved,
125*6937Sxw161283 				sizeof(xge_hal_stats_pcim_info_t));
126*6937Sxw161283 			xge_os_free(hldev->pdev, stats->pcim_info_latest,
127*6937Sxw161283 				sizeof(xge_hal_stats_pcim_info_t));
128*6937Sxw161283 			xge_debug_stats(XGE_ERR, "%s", "can not DMA alloc");
129*6937Sxw161283 			return XGE_HAL_ERR_OUT_OF_MEMORY;
130*6937Sxw161283 		}
131*6937Sxw161283 
132*6937Sxw161283 
133*6937Sxw161283 		xge_os_memzero(stats->pcim_info,
134*6937Sxw161283 			sizeof(xge_hal_stats_pcim_info_t));
135*6937Sxw161283 		xge_os_memzero(stats->pcim_info_saved,
136*6937Sxw161283 			sizeof(xge_hal_stats_pcim_info_t));
137*6937Sxw161283 		xge_os_memzero(stats->pcim_info_latest,
138*6937Sxw161283 			sizeof(xge_hal_stats_pcim_info_t));
139*6937Sxw161283 
140*6937Sxw161283 
141*6937Sxw161283 
142*6937Sxw161283 		stats->dma_addr = xge_os_dma_map(hldev->pdev,
143*6937Sxw161283 	                               stats->hw_info_dmah,
144*6937Sxw161283 				       stats->pcim_info,
145*6937Sxw161283 				       sizeof(xge_hal_stats_pcim_info_t),
146*6937Sxw161283 				       XGE_OS_DMA_DIR_FROMDEVICE,
147*6937Sxw161283 				       XGE_OS_DMA_CACHELINE_ALIGNED |
148*6937Sxw161283 #ifdef XGE_HAL_DMA_STATS_CONSISTENT
149*6937Sxw161283 				       XGE_OS_DMA_CONSISTENT
150*6937Sxw161283 #else
151*6937Sxw161283 			               XGE_OS_DMA_STREAMING
152*6937Sxw161283 #endif
153*6937Sxw161283                                        );
154*6937Sxw161283 		if (stats->dma_addr == XGE_OS_INVALID_DMA_ADDR) {
155*6937Sxw161283 			xge_debug_stats(XGE_ERR,
156*6937Sxw161283 				"can not map vaddr 0x"XGE_OS_LLXFMT" to DMA",
157*6937Sxw161283 				(unsigned long long)(ulong_t)stats->hw_info);
158*6937Sxw161283 
159*6937Sxw161283 			xge_os_dma_free(hldev->pdev,
160*6937Sxw161283 			      stats->pcim_info,
161*6937Sxw161283 			      sizeof(xge_hal_stats_pcim_info_t),
162*6937Sxw161283 			      &stats->hw_info_dma_acch,
163*6937Sxw161283 			      &stats->hw_info_dmah);
164*6937Sxw161283 
165*6937Sxw161283 			xge_os_free(hldev->pdev, stats->pcim_info_saved,
166*6937Sxw161283 				sizeof(xge_hal_stats_pcim_info_t));
167*6937Sxw161283 
168*6937Sxw161283 			xge_os_free(hldev->pdev, stats->pcim_info_latest,
169*6937Sxw161283 				sizeof(xge_hal_stats_pcim_info_t));
170*6937Sxw161283 
171*6937Sxw161283 			return XGE_HAL_ERR_OUT_OF_MAPPING;
172*6937Sxw161283 		}
173*6937Sxw161283 	}
174*6937Sxw161283 	stats->devh = devh;
1751256Syl150051 	xge_os_memzero(&stats->sw_dev_info_stats,
1761256Syl150051 		     sizeof(xge_hal_stats_device_info_t));
1771256Syl150051 
1781256Syl150051 	stats->is_initialized = 1;
1791256Syl150051 
1801256Syl150051 	return XGE_HAL_OK;
1811256Syl150051 }
1821256Syl150051 
1831256Syl150051 static void
__hal_stats_save(xge_hal_stats_t * stats)1841256Syl150051 __hal_stats_save (xge_hal_stats_t *stats)
1851256Syl150051 {
186*6937Sxw161283 	xge_hal_device_t *hldev = (xge_hal_device_t*)stats->devh;
187*6937Sxw161283 
188*6937Sxw161283 	if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) {
189*6937Sxw161283 		xge_hal_stats_hw_info_t	*latest;
190*6937Sxw161283 
191*6937Sxw161283 		(void) xge_hal_stats_hw(stats->devh, &latest);
1921256Syl150051 
193*6937Sxw161283 		xge_os_memcpy(&stats->hw_info_saved, stats->hw_info,
194*6937Sxw161283 		      sizeof(xge_hal_stats_hw_info_t));
195*6937Sxw161283 	} else {
196*6937Sxw161283 		xge_hal_stats_pcim_info_t	*latest;
1971256Syl150051 
198*6937Sxw161283 		(void) xge_hal_stats_pcim(stats->devh, &latest);
199*6937Sxw161283 
200*6937Sxw161283 		xge_os_memcpy(stats->pcim_info_saved, stats->pcim_info,
201*6937Sxw161283 		      sizeof(xge_hal_stats_pcim_info_t));
202*6937Sxw161283 	}
2031256Syl150051 }
2041256Syl150051 
2051256Syl150051 /*
2061256Syl150051  * __hal_stats_disable
2071256Syl150051  * @stats: xge_hal_stats_t structure that contains, in particular,
2081256Syl150051  *         Xframe hw stat counters.
2091256Syl150051  *
2101256Syl150051  * Ask device to stop collecting stats.
2111256Syl150051  * See also: xge_hal_stats_getinfo().
2121256Syl150051  */
2131256Syl150051 void
__hal_stats_disable(xge_hal_stats_t * stats)2141256Syl150051 __hal_stats_disable (xge_hal_stats_t *stats)
2151256Syl150051 {
2161256Syl150051 	xge_hal_device_t *hldev;
2171256Syl150051 	xge_hal_pci_bar0_t *bar0;
2181256Syl150051 	u64 val64;
2191256Syl150051 
2201256Syl150051 	xge_assert(stats->hw_info);
2211256Syl150051 
2221256Syl150051 	hldev = (xge_hal_device_t*)stats->devh;
2231256Syl150051 	xge_assert(hldev);
2241256Syl150051 	bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
2251256Syl150051 
2261256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
227*6937Sxw161283 		&bar0->stat_cfg);
2281256Syl150051 	val64 &= ~XGE_HAL_STAT_CFG_STAT_EN;
2291256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
230*6937Sxw161283 		&bar0->stat_cfg);
2311256Syl150051 	/* flush the write */
2321256Syl150051 	(void)xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
233*6937Sxw161283 		&bar0->stat_cfg);
2341256Syl150051 
2353115Syl150051 	xge_debug_stats(XGE_TRACE, "stats disabled at 0x"XGE_OS_LLXFMT,
236*6937Sxw161283 		 (unsigned long long)stats->dma_addr);
2371256Syl150051 
2381256Syl150051 	stats->is_enabled = 0;
2391256Syl150051 }
2401256Syl150051 
2411256Syl150051 /*
2421256Syl150051  * __hal_stats_terminate
2431256Syl150051  * @stats: xge_hal_stats_t structure that contains, in particular,
2441256Syl150051  *         Xframe hw stat counters.
2451256Syl150051  * Terminate per-device statistics object.
2461256Syl150051  */
2471256Syl150051 void
__hal_stats_terminate(xge_hal_stats_t * stats)2481256Syl150051 __hal_stats_terminate (xge_hal_stats_t *stats)
2491256Syl150051 {
2501256Syl150051 	xge_hal_device_t *hldev;
2511256Syl150051 
2521256Syl150051 	xge_assert(stats->hw_info);
2531256Syl150051 
2541256Syl150051 	hldev = (xge_hal_device_t*)stats->devh;
2551256Syl150051 	xge_assert(hldev);
256*6937Sxw161283 	xge_assert(stats->is_initialized);
257*6937Sxw161283 	if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) {
258*6937Sxw161283 		xge_os_dma_unmap(hldev->pdev,
2591256Syl150051 	               stats->hw_info_dmah,
2601256Syl150051 		       stats->dma_addr,
2611256Syl150051 		       sizeof(xge_hal_stats_hw_info_t),
2621256Syl150051 		       XGE_OS_DMA_DIR_FROMDEVICE);
2631256Syl150051 
264*6937Sxw161283 		xge_os_dma_free(hldev->pdev,
2651256Syl150051 		      stats->hw_info,
2661256Syl150051 		      sizeof(xge_hal_stats_hw_info_t),
2671256Syl150051 		      &stats->hw_info_dma_acch,
2681256Syl150051 		      &stats->hw_info_dmah);
269*6937Sxw161283 	} else {
270*6937Sxw161283 		xge_os_dma_unmap(hldev->pdev,
271*6937Sxw161283 	               stats->hw_info_dmah,
272*6937Sxw161283 		       stats->dma_addr,
273*6937Sxw161283 		       sizeof(xge_hal_stats_pcim_info_t),
274*6937Sxw161283 		       XGE_OS_DMA_DIR_FROMDEVICE);
275*6937Sxw161283 
276*6937Sxw161283 		xge_os_dma_free(hldev->pdev,
277*6937Sxw161283 		      stats->pcim_info,
278*6937Sxw161283 		      sizeof(xge_hal_stats_pcim_info_t),
279*6937Sxw161283 		      &stats->hw_info_dma_acch,
280*6937Sxw161283 		      &stats->hw_info_dmah);
281*6937Sxw161283 
282*6937Sxw161283 		xge_os_free(hldev->pdev, stats->pcim_info_saved,
283*6937Sxw161283 			sizeof(xge_hal_stats_pcim_info_t));
284*6937Sxw161283 
285*6937Sxw161283 		xge_os_free(hldev->pdev, stats->pcim_info_latest,
286*6937Sxw161283 				sizeof(xge_hal_stats_pcim_info_t));
287*6937Sxw161283 
288*6937Sxw161283 	}
2891256Syl150051 
2901256Syl150051 	stats->is_initialized = 0;
2911256Syl150051 	stats->is_enabled = 0;
2921256Syl150051 }
2931256Syl150051 
2941256Syl150051 
2951256Syl150051 
2961256Syl150051 /*
2971256Syl150051  * __hal_stats_enable
2981256Syl150051  * @stats: xge_hal_stats_t structure that contains, in particular,
2991256Syl150051  *         Xframe hw stat counters.
3001256Syl150051  *
3011256Syl150051  * Ask device to start collecting stats.
3021256Syl150051  * See also: xge_hal_stats_getinfo().
3031256Syl150051  */
3041256Syl150051 void
__hal_stats_enable(xge_hal_stats_t * stats)3051256Syl150051 __hal_stats_enable (xge_hal_stats_t *stats)
3061256Syl150051 {
3071256Syl150051 	xge_hal_device_t *hldev;
3081256Syl150051 	xge_hal_pci_bar0_t *bar0;
3091256Syl150051 	u64 val64;
3101256Syl150051 	unsigned int refresh_time_pci_clocks;
3111256Syl150051 
3121256Syl150051 	xge_assert(stats->hw_info);
3131256Syl150051 
3141256Syl150051 	hldev = (xge_hal_device_t*)stats->devh;
3151256Syl150051 	xge_assert(hldev);
3161256Syl150051 
3171256Syl150051 	bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
3181256Syl150051 
319*6937Sxw161283 	/* enable statistics
320*6937Sxw161283 	 * For Titan stat_addr offset == 0x09d8, and stat_cfg offset == 0x09d0
321*6937Sxw161283 	*/
322*6937Sxw161283 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
323*6937Sxw161283 		stats->dma_addr, &bar0->stat_addr);
3241256Syl150051 
325*6937Sxw161283 	refresh_time_pci_clocks = XGE_HAL_XENA_PER_SEC *
326*6937Sxw161283 		hldev->config.stats_refresh_time_sec;
3271256Syl150051 	refresh_time_pci_clocks =
328*6937Sxw161283 		__hal_fix_time_ival_herc(hldev,
329*6937Sxw161283 			refresh_time_pci_clocks);
330*6937Sxw161283 
331*6937Sxw161283 	/* enable enhanced statistics for the HERC */
332*6937Sxw161283 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
333*6937Sxw161283 		val64 = XGE_HAL_STAT_BYTE_CNT(0x320);
334*6937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
335*6937Sxw161283 		    val64, &bar0->stat_byte_cnt);
336*6937Sxw161283 	}
3371256Syl150051 
3381256Syl150051 #ifdef XGE_HAL_HERC_EMULATION
3391256Syl150051 	/*
340*6937Sxw161283 	 *  The clocks in the emulator are running ~1000 times slower
341*6937Sxw161283 	 *  than real world, so the stats transfer will occur ~1000
342*6937Sxw161283 	 *  times less frequent. STAT_CFG.STAT_TRSF_PERIOD should be
343*6937Sxw161283 	 *  set to 0x20C for Hercules emulation (stats transferred
344*6937Sxw161283 	 *  every 0.5 sec).
345*6937Sxw161283 	*/
3463115Syl150051 
347*6937Sxw161283 	val64 = (0x20C | XGE_HAL_STAT_CFG_STAT_RO |
348*6937Sxw161283 		XGE_HAL_STAT_CFG_STAT_EN);
3491256Syl150051 #else
3501256Syl150051 	val64 = XGE_HAL_SET_UPDT_PERIOD(refresh_time_pci_clocks) |
351*6937Sxw161283 		                XGE_HAL_STAT_CFG_STAT_RO |
352*6937Sxw161283 				XGE_HAL_STAT_CFG_STAT_EN;
3531256Syl150051 #endif
3541256Syl150051 
355*6937Sxw161283 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
356*6937Sxw161283 		val64, &bar0->stat_cfg);
3571256Syl150051 
3583115Syl150051 	xge_debug_stats(XGE_TRACE, "stats enabled at 0x"XGE_OS_LLXFMT,
359*6937Sxw161283 		 (unsigned long long)stats->dma_addr);
3601256Syl150051 
3611256Syl150051 	stats->is_enabled = 1;
3621256Syl150051 }
3631256Syl150051 
3641256Syl150051 /*
365*6937Sxw161283  * __hal_stats_pcim_update_latest - Update hw ER stats counters, based on the
366*6937Sxw161283  * real hardware maintained counters and the stored "reset" values.
367*6937Sxw161283  */
368*6937Sxw161283 static void
__hal_stats_pcim_update_latest(xge_hal_device_h devh)369*6937Sxw161283 __hal_stats_pcim_update_latest(xge_hal_device_h devh)
370*6937Sxw161283 {
371*6937Sxw161283 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
372*6937Sxw161283 	int i;
373*6937Sxw161283 
374*6937Sxw161283 #define set_latest_stat_link_cnt(_link, _p)				      \
375*6937Sxw161283         hldev->stats.pcim_info_latest->link_info[_link]._p =		      \
376*6937Sxw161283 	((hldev->stats.pcim_info->link_info[_link]._p >=	              \
377*6937Sxw161283 		hldev->stats.pcim_info_saved->link_info[_link]._p) ?	      \
378*6937Sxw161283 		hldev->stats.pcim_info->link_info[_link]._p -		      \
379*6937Sxw161283 			hldev->stats.pcim_info_saved->link_info[_link]._p :   \
380*6937Sxw161283 		((-1) - hldev->stats.pcim_info_saved->link_info[_link]._p) +  \
381*6937Sxw161283 			hldev->stats.pcim_info->link_info[_link]._p)
382*6937Sxw161283 
383*6937Sxw161283 
384*6937Sxw161283 #define set_latest_stat_aggr_cnt(_aggr, _p)				      \
385*6937Sxw161283         hldev->stats.pcim_info_latest->aggr_info[_aggr]._p =		      \
386*6937Sxw161283 	((hldev->stats.pcim_info->aggr_info[_aggr]._p >=		      \
387*6937Sxw161283 		hldev->stats.pcim_info_saved->aggr_info[_aggr]._p) ?	      \
388*6937Sxw161283 		hldev->stats.pcim_info->aggr_info[_aggr]._p -		      \
389*6937Sxw161283 			hldev->stats.pcim_info_saved->aggr_info[_aggr]._p :   \
390*6937Sxw161283 		((-1) - hldev->stats.pcim_info_saved->aggr_info[_aggr]._p) +  \
391*6937Sxw161283 			hldev->stats.pcim_info->aggr_info[_aggr]._p)
392*6937Sxw161283 
393*6937Sxw161283 
394*6937Sxw161283 	for (i = 0; i < XGE_HAL_MAC_LINKS; i++) {
395*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_frms);
396*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_ttl_eth_octets);
397*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_data_octets);
398*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_mcst_frms);
399*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_bcst_frms);
400*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_ucst_frms);
401*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_tagged_frms);
402*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_vld_ip);
403*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_vld_ip_octets);
404*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_icmp);
405*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_tcp);
406*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_rst_tcp);
407*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_udp);
408*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_unknown_protocol);
409*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_parse_error);
410*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_pause_ctrl_frms);
411*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_lacpdu_frms);
412*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_marker_pdu_frms);
413*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_marker_resp_pdu_frms);
414*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_drop_ip);
415*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_xgmii_char1_match);
416*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_xgmii_char2_match);
417*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_xgmii_column1_match);
418*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_xgmii_column2_match);
419*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_drop_frms);
420*6937Sxw161283 		set_latest_stat_link_cnt(i, tx_any_err_frms);
421*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_ttl_frms);
422*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_vld_frms);
423*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_offld_frms);
424*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_ttl_eth_octets);
425*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_data_octets);
426*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_offld_octets);
427*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_vld_mcst_frms);
428*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_vld_bcst_frms);
429*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_accepted_ucst_frms);
430*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_accepted_nucst_frms);
431*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_tagged_frms);
432*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_long_frms);
433*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_usized_frms);
434*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_osized_frms);
435*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_frag_frms);
436*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_jabber_frms);
437*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_ttl_64_frms);
438*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_ttl_65_127_frms);
439*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_ttl_128_255_frms);
440*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_ttl_256_511_frms);
441*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_ttl_512_1023_frms);
442*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_ttl_1024_1518_frms);
443*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_ttl_1519_4095_frms);
444*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_ttl_40956_8191_frms);
445*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_ttl_8192_max_frms);
446*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_ttl_gt_max_frms);
447*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_ip);
448*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_ip_octets);
449*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_hdr_err_ip);
450*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_icmp);
451*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_tcp);
452*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_udp);
453*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_err_tcp);
454*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_pause_cnt);
455*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_pause_ctrl_frms);
456*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_unsup_ctrl_frms);
457*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_in_rng_len_err_frms);
458*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_out_rng_len_err_frms);
459*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_drop_frms);
460*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_discarded_frms);
461*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_drop_ip);
462*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_err_drp_udp);
463*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_lacpdu_frms);
464*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_marker_pdu_frms);
465*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_marker_resp_pdu_frms);
466*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_unknown_pdu_frms);
467*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_illegal_pdu_frms);
468*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_fcs_discard);
469*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_len_discard);
470*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_pf_discard);
471*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_trash_discard);
472*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_rts_discard);
473*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_wol_discard);
474*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_red_discard);
475*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_ingm_full_discard);
476*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_xgmii_data_err_cnt);
477*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_xgmii_ctrl_err_cnt);
478*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_xgmii_err_sym);
479*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_xgmii_char1_match);
480*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_xgmii_char2_match);
481*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_xgmii_column1_match);
482*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_xgmii_column2_match);
483*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_local_fault);
484*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_remote_fault);
485*6937Sxw161283 		set_latest_stat_link_cnt(i, rx_queue_full);
486*6937Sxw161283 	}
487*6937Sxw161283 
488*6937Sxw161283 	for (i = 0; i < XGE_HAL_MAC_AGGREGATORS; i++) {
489*6937Sxw161283 		set_latest_stat_aggr_cnt(i, tx_frms);
490*6937Sxw161283 		set_latest_stat_aggr_cnt(i, tx_mcst_frms);
491*6937Sxw161283 		set_latest_stat_aggr_cnt(i, tx_bcst_frms);
492*6937Sxw161283 		set_latest_stat_aggr_cnt(i, tx_discarded_frms);
493*6937Sxw161283 		set_latest_stat_aggr_cnt(i, tx_errored_frms);
494*6937Sxw161283 		set_latest_stat_aggr_cnt(i, rx_frms);
495*6937Sxw161283 		set_latest_stat_aggr_cnt(i, rx_data_octets);
496*6937Sxw161283 		set_latest_stat_aggr_cnt(i, rx_mcst_frms);
497*6937Sxw161283 		set_latest_stat_aggr_cnt(i, rx_bcst_frms);
498*6937Sxw161283 		set_latest_stat_aggr_cnt(i, rx_discarded_frms);
499*6937Sxw161283 		set_latest_stat_aggr_cnt(i, rx_errored_frms);
500*6937Sxw161283 		set_latest_stat_aggr_cnt(i, rx_unknown_protocol_frms);
501*6937Sxw161283 	}
502*6937Sxw161283 	return;
503*6937Sxw161283 }
504*6937Sxw161283 
505*6937Sxw161283 /*
5061256Syl150051  * __hal_stats_update_latest - Update hw stats counters, based on the real
5071256Syl150051  * hardware maintained counters and the stored "reset" values.
5081256Syl150051  */
5091256Syl150051 static void
__hal_stats_update_latest(xge_hal_device_h devh)5101256Syl150051 __hal_stats_update_latest(xge_hal_device_h devh)
5111256Syl150051 {
5121256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
5131256Syl150051 
5141256Syl150051 #define set_latest_stat_cnt(_dev, _p)                                   \
5151256Syl150051         hldev->stats.hw_info_latest._p =                                \
5161256Syl150051 	((hldev->stats.hw_info->_p >= hldev->stats.hw_info_saved._p) ?  \
5171256Syl150051           hldev->stats.hw_info->_p - hldev->stats.hw_info_saved._p :    \
5181256Syl150051 	  ((-1) - hldev->stats.hw_info_saved._p) + hldev->stats.hw_info->_p)
5191256Syl150051 
520*6937Sxw161283 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_TITAN) {
521*6937Sxw161283 		__hal_stats_pcim_update_latest(devh);
522*6937Sxw161283 		return;
523*6937Sxw161283 	}
524*6937Sxw161283 
5251256Syl150051 	/* Tx MAC statistics counters. */
5261256Syl150051 	set_latest_stat_cnt(hldev, tmac_frms);
5271256Syl150051 	set_latest_stat_cnt(hldev, tmac_data_octets);
5281256Syl150051 	set_latest_stat_cnt(hldev, tmac_drop_frms);
5291256Syl150051 	set_latest_stat_cnt(hldev, tmac_mcst_frms);
5301256Syl150051 	set_latest_stat_cnt(hldev, tmac_bcst_frms);
5311256Syl150051 	set_latest_stat_cnt(hldev, tmac_pause_ctrl_frms);
5321256Syl150051 	set_latest_stat_cnt(hldev, tmac_ttl_octets);
5331256Syl150051 	set_latest_stat_cnt(hldev, tmac_ucst_frms);
5341256Syl150051 	set_latest_stat_cnt(hldev, tmac_nucst_frms);
5351256Syl150051 	set_latest_stat_cnt(hldev, tmac_any_err_frms);
5361256Syl150051 	set_latest_stat_cnt(hldev, tmac_ttl_less_fb_octets);
5371256Syl150051 	set_latest_stat_cnt(hldev, tmac_vld_ip_octets);
5381256Syl150051 	set_latest_stat_cnt(hldev, tmac_vld_ip);
5391256Syl150051 	set_latest_stat_cnt(hldev, tmac_drop_ip);
5401256Syl150051 	set_latest_stat_cnt(hldev, tmac_icmp);
5411256Syl150051 	set_latest_stat_cnt(hldev, tmac_rst_tcp);
5421256Syl150051 	set_latest_stat_cnt(hldev, tmac_tcp);
5431256Syl150051 	set_latest_stat_cnt(hldev, tmac_udp);
5441256Syl150051 	set_latest_stat_cnt(hldev, reserved_0);
5451256Syl150051 
5461256Syl150051 	/* Rx MAC Statistics counters. */
5471256Syl150051 	set_latest_stat_cnt(hldev, rmac_vld_frms);
5481256Syl150051 	set_latest_stat_cnt(hldev, rmac_data_octets);
5491256Syl150051 	set_latest_stat_cnt(hldev, rmac_fcs_err_frms);
5501256Syl150051 	set_latest_stat_cnt(hldev, rmac_drop_frms);
5511256Syl150051 	set_latest_stat_cnt(hldev, rmac_vld_mcst_frms);
5521256Syl150051 	set_latest_stat_cnt(hldev, rmac_vld_bcst_frms);
5531256Syl150051 	set_latest_stat_cnt(hldev, rmac_in_rng_len_err_frms);
5541256Syl150051 	set_latest_stat_cnt(hldev, rmac_out_rng_len_err_frms);
5551256Syl150051 	set_latest_stat_cnt(hldev, rmac_long_frms);
5561256Syl150051 	set_latest_stat_cnt(hldev, rmac_pause_ctrl_frms);
5571256Syl150051 	set_latest_stat_cnt(hldev, rmac_unsup_ctrl_frms);
5581256Syl150051 	set_latest_stat_cnt(hldev, rmac_ttl_octets);
5591256Syl150051 	set_latest_stat_cnt(hldev, rmac_accepted_ucst_frms);
5601256Syl150051 	set_latest_stat_cnt(hldev, rmac_accepted_nucst_frms);
5611256Syl150051 	set_latest_stat_cnt(hldev, rmac_discarded_frms);
5621256Syl150051 	set_latest_stat_cnt(hldev, rmac_drop_events);
5631256Syl150051 	set_latest_stat_cnt(hldev, reserved_1);
5641256Syl150051 	set_latest_stat_cnt(hldev, rmac_ttl_less_fb_octets);
5651256Syl150051 	set_latest_stat_cnt(hldev, rmac_ttl_frms);
5661256Syl150051 	set_latest_stat_cnt(hldev, reserved_2);
5671256Syl150051 	set_latest_stat_cnt(hldev, reserved_3);
5681256Syl150051 	set_latest_stat_cnt(hldev, rmac_usized_frms);
5691256Syl150051 	set_latest_stat_cnt(hldev, rmac_osized_frms);
5701256Syl150051 	set_latest_stat_cnt(hldev, rmac_frag_frms);
5711256Syl150051 	set_latest_stat_cnt(hldev, rmac_jabber_frms);
5721256Syl150051 	set_latest_stat_cnt(hldev, reserved_4);
5731256Syl150051 	set_latest_stat_cnt(hldev, rmac_ttl_64_frms);
5741256Syl150051 	set_latest_stat_cnt(hldev, rmac_ttl_65_127_frms);
5751256Syl150051 	set_latest_stat_cnt(hldev, reserved_5);
5761256Syl150051 	set_latest_stat_cnt(hldev, rmac_ttl_128_255_frms);
5771256Syl150051 	set_latest_stat_cnt(hldev, rmac_ttl_256_511_frms);
5781256Syl150051 	set_latest_stat_cnt(hldev, reserved_6);
5791256Syl150051 	set_latest_stat_cnt(hldev, rmac_ttl_512_1023_frms);
5801256Syl150051 	set_latest_stat_cnt(hldev, rmac_ttl_1024_1518_frms);
5811256Syl150051 	set_latest_stat_cnt(hldev, reserved_7);
5821256Syl150051 	set_latest_stat_cnt(hldev, rmac_ip);
5831256Syl150051 	set_latest_stat_cnt(hldev, rmac_ip_octets);
5841256Syl150051 	set_latest_stat_cnt(hldev, rmac_hdr_err_ip);
5851256Syl150051 	set_latest_stat_cnt(hldev, rmac_drop_ip);
5861256Syl150051 	set_latest_stat_cnt(hldev, rmac_icmp);
5871256Syl150051 	set_latest_stat_cnt(hldev, reserved_8);
5881256Syl150051 	set_latest_stat_cnt(hldev, rmac_tcp);
5891256Syl150051 	set_latest_stat_cnt(hldev, rmac_udp);
5901256Syl150051 	set_latest_stat_cnt(hldev, rmac_err_drp_udp);
5911256Syl150051 	set_latest_stat_cnt(hldev, rmac_xgmii_err_sym);
5921256Syl150051 	set_latest_stat_cnt(hldev, rmac_frms_q0);
5931256Syl150051 	set_latest_stat_cnt(hldev, rmac_frms_q1);
5941256Syl150051 	set_latest_stat_cnt(hldev, rmac_frms_q2);
5951256Syl150051 	set_latest_stat_cnt(hldev, rmac_frms_q3);
5961256Syl150051 	set_latest_stat_cnt(hldev, rmac_frms_q4);
5971256Syl150051 	set_latest_stat_cnt(hldev, rmac_frms_q5);
5981256Syl150051 	set_latest_stat_cnt(hldev, rmac_frms_q6);
5991256Syl150051 	set_latest_stat_cnt(hldev, rmac_frms_q7);
6001256Syl150051 	set_latest_stat_cnt(hldev, rmac_full_q0);
6011256Syl150051 	set_latest_stat_cnt(hldev, rmac_full_q1);
6021256Syl150051 	set_latest_stat_cnt(hldev, rmac_full_q2);
6031256Syl150051 	set_latest_stat_cnt(hldev, rmac_full_q3);
6041256Syl150051 	set_latest_stat_cnt(hldev, rmac_full_q4);
6051256Syl150051 	set_latest_stat_cnt(hldev, rmac_full_q5);
6061256Syl150051 	set_latest_stat_cnt(hldev, rmac_full_q6);
6071256Syl150051 	set_latest_stat_cnt(hldev, rmac_full_q7);
6081256Syl150051 	set_latest_stat_cnt(hldev, rmac_pause_cnt);
6091256Syl150051 	set_latest_stat_cnt(hldev, reserved_9);
6101256Syl150051 	set_latest_stat_cnt(hldev, rmac_xgmii_data_err_cnt);
6111256Syl150051 	set_latest_stat_cnt(hldev, rmac_xgmii_ctrl_err_cnt);
6121256Syl150051 	set_latest_stat_cnt(hldev, rmac_accepted_ip);
6131256Syl150051 	set_latest_stat_cnt(hldev, rmac_err_tcp);
6141256Syl150051 
6151256Syl150051 	/* PCI/PCI-X Read transaction statistics. */
6161256Syl150051 	set_latest_stat_cnt(hldev, rd_req_cnt);
6171256Syl150051 	set_latest_stat_cnt(hldev, new_rd_req_cnt);
6181256Syl150051 	set_latest_stat_cnt(hldev, new_rd_req_rtry_cnt);
6191256Syl150051 	set_latest_stat_cnt(hldev, rd_rtry_cnt);
6201256Syl150051 	set_latest_stat_cnt(hldev, wr_rtry_rd_ack_cnt);
6211256Syl150051 
6221256Syl150051 	/* PCI/PCI-X write transaction statistics. */
6231256Syl150051 	set_latest_stat_cnt(hldev, wr_req_cnt);
6241256Syl150051 	set_latest_stat_cnt(hldev, new_wr_req_cnt);
6251256Syl150051 	set_latest_stat_cnt(hldev, new_wr_req_rtry_cnt);
6261256Syl150051 	set_latest_stat_cnt(hldev, wr_rtry_cnt);
6271256Syl150051 	set_latest_stat_cnt(hldev, wr_disc_cnt);
6281256Syl150051 	set_latest_stat_cnt(hldev, rd_rtry_wr_ack_cnt);
6291256Syl150051 
6301256Syl150051 	/* DMA Transaction statistics. */
6311256Syl150051 	set_latest_stat_cnt(hldev, txp_wr_cnt);
6321256Syl150051 	set_latest_stat_cnt(hldev, txd_rd_cnt);
6331256Syl150051 	set_latest_stat_cnt(hldev, txd_wr_cnt);
6341256Syl150051 	set_latest_stat_cnt(hldev, rxd_rd_cnt);
6351256Syl150051 	set_latest_stat_cnt(hldev, rxd_wr_cnt);
6361256Syl150051 	set_latest_stat_cnt(hldev, txf_rd_cnt);
6371256Syl150051 	set_latest_stat_cnt(hldev, rxf_wr_cnt);
6381256Syl150051 
6391256Syl150051 	/* Enhanced Herc statistics */
6401256Syl150051 	set_latest_stat_cnt(hldev, tmac_frms_oflow);
6411256Syl150051 	set_latest_stat_cnt(hldev, tmac_data_octets_oflow);
6421256Syl150051 	set_latest_stat_cnt(hldev, tmac_mcst_frms_oflow);
6431256Syl150051 	set_latest_stat_cnt(hldev, tmac_bcst_frms_oflow);
6441256Syl150051 	set_latest_stat_cnt(hldev, tmac_ttl_octets_oflow);
6451256Syl150051 	set_latest_stat_cnt(hldev, tmac_ucst_frms_oflow);
6461256Syl150051 	set_latest_stat_cnt(hldev, tmac_nucst_frms_oflow);
6471256Syl150051 	set_latest_stat_cnt(hldev, tmac_any_err_frms_oflow);
6481256Syl150051 	set_latest_stat_cnt(hldev, tmac_vlan_frms);
6491256Syl150051 	set_latest_stat_cnt(hldev, tmac_vld_ip_oflow);
6501256Syl150051 	set_latest_stat_cnt(hldev, tmac_drop_ip_oflow);
6511256Syl150051 	set_latest_stat_cnt(hldev, tmac_icmp_oflow);
6521256Syl150051 	set_latest_stat_cnt(hldev, tmac_rst_tcp_oflow);
6531256Syl150051 	set_latest_stat_cnt(hldev, tmac_udp_oflow);
6541256Syl150051 	set_latest_stat_cnt(hldev, tpa_unknown_protocol);
6551256Syl150051 	set_latest_stat_cnt(hldev, tpa_parse_failure);
6561256Syl150051 	set_latest_stat_cnt(hldev, rmac_vld_frms_oflow);
6571256Syl150051 	set_latest_stat_cnt(hldev, rmac_data_octets_oflow);
6581256Syl150051 	set_latest_stat_cnt(hldev, rmac_vld_mcst_frms_oflow);
6591256Syl150051 	set_latest_stat_cnt(hldev, rmac_vld_bcst_frms_oflow);
6601256Syl150051 	set_latest_stat_cnt(hldev, rmac_ttl_octets_oflow);
6611256Syl150051 	set_latest_stat_cnt(hldev, rmac_accepted_ucst_frms_oflow);
6621256Syl150051 	set_latest_stat_cnt(hldev, rmac_accepted_nucst_frms_oflow);
6631256Syl150051 	set_latest_stat_cnt(hldev, rmac_discarded_frms_oflow);
6641256Syl150051 	set_latest_stat_cnt(hldev, rmac_drop_events_oflow);
6651256Syl150051 	set_latest_stat_cnt(hldev, rmac_usized_frms_oflow);
6661256Syl150051 	set_latest_stat_cnt(hldev, rmac_osized_frms_oflow);
6671256Syl150051 	set_latest_stat_cnt(hldev, rmac_frag_frms_oflow);
6681256Syl150051 	set_latest_stat_cnt(hldev, rmac_jabber_frms_oflow);
6691256Syl150051 	set_latest_stat_cnt(hldev, rmac_ip_oflow);
6701256Syl150051 	set_latest_stat_cnt(hldev, rmac_drop_ip_oflow);
6711256Syl150051 	set_latest_stat_cnt(hldev, rmac_icmp_oflow);
6721256Syl150051 	set_latest_stat_cnt(hldev, rmac_udp_oflow);
6731256Syl150051 	set_latest_stat_cnt(hldev, rmac_err_drp_udp_oflow);
6741256Syl150051 	set_latest_stat_cnt(hldev, rmac_pause_cnt_oflow);
6751256Syl150051 	set_latest_stat_cnt(hldev, rmac_ttl_1519_4095_frms);
6761256Syl150051 	set_latest_stat_cnt(hldev, rmac_ttl_4096_8191_frms);
6771256Syl150051 	set_latest_stat_cnt(hldev, rmac_ttl_8192_max_frms);
6781256Syl150051 	set_latest_stat_cnt(hldev, rmac_ttl_gt_max_frms);
6791256Syl150051 	set_latest_stat_cnt(hldev, rmac_osized_alt_frms);
6801256Syl150051 	set_latest_stat_cnt(hldev, rmac_jabber_alt_frms);
6811256Syl150051 	set_latest_stat_cnt(hldev, rmac_gt_max_alt_frms);
6821256Syl150051 	set_latest_stat_cnt(hldev, rmac_vlan_frms);
6831256Syl150051 	set_latest_stat_cnt(hldev, rmac_fcs_discard);
6841256Syl150051 	set_latest_stat_cnt(hldev, rmac_len_discard);
6851256Syl150051 	set_latest_stat_cnt(hldev, rmac_da_discard);
6861256Syl150051 	set_latest_stat_cnt(hldev, rmac_pf_discard);
6871256Syl150051 	set_latest_stat_cnt(hldev, rmac_rts_discard);
6881256Syl150051 	set_latest_stat_cnt(hldev, rmac_red_discard);
6891256Syl150051 	set_latest_stat_cnt(hldev, rmac_ingm_full_discard);
6901256Syl150051 	set_latest_stat_cnt(hldev, rmac_accepted_ip_oflow);
6911256Syl150051 	set_latest_stat_cnt(hldev, link_fault_cnt);
6921256Syl150051 }
6931256Syl150051 
6941256Syl150051 /**
6951256Syl150051  * xge_hal_stats_hw - Get HW device statistics.
6961256Syl150051  * @devh: HAL device handle.
6971256Syl150051  * @hw_info: Xframe statistic counters. See xge_hal_stats_hw_info_t.
6981256Syl150051  *           Returned by HAL.
6991256Syl150051  *
7001256Syl150051  * Get device and HAL statistics. The latter is part of the in-host statistics
7011256Syl150051  * that HAL maintains for _that_ device.
7021256Syl150051  *
7031256Syl150051  * Returns: XGE_HAL_OK - success.
7041256Syl150051  * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
7051256Syl150051  * currently available.
7061256Syl150051  *
7071256Syl150051  * See also: xge_hal_status_e{}.
7081256Syl150051  */
7091256Syl150051 xge_hal_status_e
xge_hal_stats_hw(xge_hal_device_h devh,xge_hal_stats_hw_info_t ** hw_info)7101256Syl150051 xge_hal_stats_hw(xge_hal_device_h devh, xge_hal_stats_hw_info_t **hw_info)
7111256Syl150051 {
7121256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
7131256Syl150051 
714*6937Sxw161283 	xge_assert(xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN)
715*6937Sxw161283 
7161256Syl150051 	if (!hldev->stats.is_initialized ||
7171256Syl150051 	    !hldev->stats.is_enabled) {
7181256Syl150051 		*hw_info = NULL;
7191256Syl150051 		return XGE_HAL_INF_STATS_IS_NOT_READY;
7201256Syl150051 	}
7211256Syl150051 
7221256Syl150051 #if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_STATS_STREAMING)
7231256Syl150051 	xge_os_dma_sync(hldev->pdev,
7241256Syl150051 	              hldev->stats.hw_info_dmah,
7251256Syl150051 		      hldev->stats.dma_addr,
7261256Syl150051 		      0,
7271256Syl150051 		      sizeof(xge_hal_stats_hw_info_t),
7281256Syl150051 		      XGE_OS_DMA_DIR_FROMDEVICE);
7291256Syl150051 #endif
7301256Syl150051 
7311256Syl150051         /*
7321256Syl150051 	 * update hw counters, taking into account
7331256Syl150051 	 * the "reset" or "saved"
7341256Syl150051 	 * values
7351256Syl150051 	 */
7361256Syl150051 	__hal_stats_update_latest(devh);
7371256Syl150051 
738*6937Sxw161283 	/*
739*6937Sxw161283 	 * statistics HW bug fixups for Xena and Herc
740*6937Sxw161283 	 */
741*6937Sxw161283 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA ||
742*6937Sxw161283 	    xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
743*6937Sxw161283 		u64 mcst, bcst;
744*6937Sxw161283 		xge_hal_stats_hw_info_t *hwsta = &hldev->stats.hw_info_latest;
745*6937Sxw161283 
746*6937Sxw161283 		mcst = ((u64)hwsta->rmac_vld_mcst_frms_oflow << 32) |
747*6937Sxw161283 			hwsta->rmac_vld_mcst_frms;
748*6937Sxw161283 
749*6937Sxw161283 		bcst = ((u64)hwsta->rmac_vld_bcst_frms_oflow << 32) |
750*6937Sxw161283 			hwsta->rmac_vld_bcst_frms;
751*6937Sxw161283 
752*6937Sxw161283 		mcst -= bcst;
753*6937Sxw161283 
754*6937Sxw161283 		hwsta->rmac_vld_mcst_frms_oflow = (u32)(mcst >> 32);
755*6937Sxw161283 		hwsta->rmac_vld_mcst_frms = (u32)mcst;
756*6937Sxw161283 	}
757*6937Sxw161283 
7581256Syl150051 	*hw_info = &hldev->stats.hw_info_latest;
7591256Syl150051 
7601256Syl150051 	return XGE_HAL_OK;
7611256Syl150051 }
7621256Syl150051 
7631256Syl150051 /**
764*6937Sxw161283  * xge_hal_stats_pcim - Get HW device statistics.
765*6937Sxw161283  * @devh: HAL device handle.
766*6937Sxw161283  * @hw_info: Xframe statistic counters. See xge_hal_stats_pcim_info_t.
767*6937Sxw161283  *
768*6937Sxw161283  * Returns: XGE_HAL_OK - success.
769*6937Sxw161283  * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
770*6937Sxw161283  * currently available.
771*6937Sxw161283  *
772*6937Sxw161283  * See also: xge_hal_status_e{}.
773*6937Sxw161283  */
774*6937Sxw161283 xge_hal_status_e
xge_hal_stats_pcim(xge_hal_device_h devh,xge_hal_stats_pcim_info_t ** hw_info)775*6937Sxw161283 xge_hal_stats_pcim(xge_hal_device_h devh, xge_hal_stats_pcim_info_t **hw_info)
776*6937Sxw161283 {
777*6937Sxw161283 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
778*6937Sxw161283 
779*6937Sxw161283 	xge_assert(xge_hal_device_check_id(hldev) == XGE_HAL_CARD_TITAN)
780*6937Sxw161283 
781*6937Sxw161283 	if (!hldev->stats.is_initialized ||
782*6937Sxw161283 	    !hldev->stats.is_enabled) {
783*6937Sxw161283 		*hw_info = NULL;
784*6937Sxw161283 		return XGE_HAL_INF_STATS_IS_NOT_READY;
785*6937Sxw161283 	}
786*6937Sxw161283 
787*6937Sxw161283 #if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_STATS_STREAMING)
788*6937Sxw161283 	xge_os_dma_sync(hldev->pdev,
789*6937Sxw161283 	              hldev->stats.hw_info_dmah,
790*6937Sxw161283 		      hldev->stats.dma_addr,
791*6937Sxw161283 		      0,
792*6937Sxw161283 		      sizeof(xge_hal_stats_pcim_info_t),
793*6937Sxw161283 		      XGE_OS_DMA_DIR_FROMDEVICE);
794*6937Sxw161283 #endif
795*6937Sxw161283 
796*6937Sxw161283         /*
797*6937Sxw161283 	 * update hw counters, taking into account
798*6937Sxw161283 	 * the "reset" or "saved"
799*6937Sxw161283 	 * values
800*6937Sxw161283 	 */
801*6937Sxw161283 	__hal_stats_pcim_update_latest(devh);
802*6937Sxw161283 
803*6937Sxw161283 	*hw_info = hldev->stats.pcim_info_latest;
804*6937Sxw161283 
805*6937Sxw161283 	return XGE_HAL_OK;
806*6937Sxw161283 }
807*6937Sxw161283 
808*6937Sxw161283 /**
8091256Syl150051  * xge_hal_stats_device - Get HAL statistics.
8101256Syl150051  * @devh: HAL device handle.
8111256Syl150051  * @hw_info: Xframe statistic counters. See xge_hal_stats_hw_info_t.
8121256Syl150051  *           Returned by HAL.
8131256Syl150051  * @device_info: HAL statistics. See xge_hal_stats_device_info_t.
8141256Syl150051  *               Returned by HAL.
8151256Syl150051  *
8161256Syl150051  * Get device and HAL statistics. The latter is part of the in-host statistics
8171256Syl150051  * that HAL maintains for _that_ device.
8181256Syl150051  *
8191256Syl150051  * Returns: XGE_HAL_OK - success.
8201256Syl150051  * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
8211256Syl150051  * currently available.
8221256Syl150051  *
8231256Syl150051  * See also: xge_hal_status_e{}.
8241256Syl150051  */
8251256Syl150051 xge_hal_status_e
xge_hal_stats_device(xge_hal_device_h devh,xge_hal_stats_device_info_t ** device_info)8261256Syl150051 xge_hal_stats_device(xge_hal_device_h devh,
8271256Syl150051 		xge_hal_stats_device_info_t **device_info)
8281256Syl150051 {
8291256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
8301256Syl150051 
8311256Syl150051 	if (!hldev->stats.is_initialized ||
8321256Syl150051 	    !hldev->stats.is_enabled) {
8331256Syl150051 		*device_info = NULL;
8341256Syl150051 		return XGE_HAL_INF_STATS_IS_NOT_READY;
8351256Syl150051 	}
8361256Syl150051 
8371256Syl150051 	hldev->stats.sw_dev_info_stats.traffic_intr_cnt =
8381256Syl150051 		hldev->stats.sw_dev_info_stats.total_intr_cnt -
8391256Syl150051 			hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt;
8401256Syl150051 
8411256Syl150051 	*device_info = &hldev->stats.sw_dev_info_stats;
8421256Syl150051 
8431256Syl150051 	return XGE_HAL_OK;
8441256Syl150051 }
8451256Syl150051 
8461256Syl150051 /**
8471256Syl150051  * xge_hal_stats_channel - Get channel statistics.
8481256Syl150051  * @channelh: Channel handle.
8491256Syl150051  * @channel_info: HAL channel statistic counters.
8501256Syl150051  *                See xge_hal_stats_channel_info_t{}. Returned by HAL.
8511256Syl150051  *
8521256Syl150051  * Retrieve statistics of a particular HAL channel. This includes, for instance,
8531256Syl150051  * number of completions per interrupt, number of traffic interrupts, etc.
8541256Syl150051  *
8551256Syl150051  * Returns: XGE_HAL_OK - success.
8561256Syl150051  * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
8571256Syl150051  * currently available.
8581256Syl150051  *
8591256Syl150051  * See also: xge_hal_status_e{}.
8601256Syl150051  */
8611256Syl150051 xge_hal_status_e
xge_hal_stats_channel(xge_hal_channel_h channelh,xge_hal_stats_channel_info_t ** channel_info)8621256Syl150051 xge_hal_stats_channel(xge_hal_channel_h channelh,
8631256Syl150051 		xge_hal_stats_channel_info_t **channel_info)
8641256Syl150051 {
8651256Syl150051 	xge_hal_stats_hw_info_t	*latest;
8661256Syl150051 	xge_hal_channel_t *channel;
8671256Syl150051 	xge_hal_device_t *hldev;
8681256Syl150051 
8691256Syl150051 	channel = (xge_hal_channel_t *)channelh;
870*6937Sxw161283 	if ((channel == NULL) || (channel->magic != XGE_HAL_MAGIC)) {
871*6937Sxw161283 		return XGE_HAL_ERR_INVALID_DEVICE;
872*6937Sxw161283 	}
8731256Syl150051 	hldev = (xge_hal_device_t *)channel->devh;
8741256Syl150051 	if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) {
8751256Syl150051 		return XGE_HAL_ERR_INVALID_DEVICE;
8761256Syl150051 	}
8771256Syl150051 
8781256Syl150051 	if (!hldev->stats.is_initialized ||
8791256Syl150051 	    !hldev->stats.is_enabled ||
8801256Syl150051 	    !channel->is_open) {
8811256Syl150051 		*channel_info = NULL;
8821256Syl150051 		return XGE_HAL_INF_STATS_IS_NOT_READY;
8831256Syl150051 	}
8841256Syl150051 
8851256Syl150051 	hldev->stats.sw_dev_info_stats.traffic_intr_cnt =
8861256Syl150051 		hldev->stats.sw_dev_info_stats.total_intr_cnt -
8871256Syl150051 			hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt;
8881256Syl150051 
8891256Syl150051 	if (hldev->stats.sw_dev_info_stats.traffic_intr_cnt) {
8903115Syl150051 		int rxcnt = hldev->stats.sw_dev_info_stats.rx_traffic_intr_cnt;
8913115Syl150051 		int txcnt = hldev->stats.sw_dev_info_stats.tx_traffic_intr_cnt;
8923115Syl150051 		if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
8933115Syl150051 			if (!txcnt)
8943115Syl150051 				txcnt = 1;
8953115Syl150051 			channel->stats.avg_compl_per_intr_cnt =
8963115Syl150051 				channel->stats.total_compl_cnt / txcnt;
8973115Syl150051 		} else if (channel->type == XGE_HAL_CHANNEL_TYPE_RING &&
8983115Syl150051 			   !hldev->config.bimodal_interrupts) {
8993115Syl150051 			if (!rxcnt)
9003115Syl150051 				rxcnt = 1;
9013115Syl150051 			channel->stats.avg_compl_per_intr_cnt =
9023115Syl150051 				channel->stats.total_compl_cnt / rxcnt;
9033115Syl150051 		}
9041256Syl150051 		if (channel->stats.avg_compl_per_intr_cnt == 0) {
9051256Syl150051 			/* to not confuse user */
9061256Syl150051 			channel->stats.avg_compl_per_intr_cnt = 1;
9071256Syl150051 		}
9081256Syl150051 	}
9091256Syl150051 
9101256Syl150051 	(void) xge_hal_stats_hw(hldev, &latest);
9111256Syl150051 
9121256Syl150051 	if (channel->stats.total_posts) {
9131256Syl150051 		channel->stats.avg_buffers_per_post =
9141256Syl150051 			channel->stats.total_buffers /
9151256Syl150051 				channel->stats.total_posts;
9161256Syl150051 #ifdef XGE_OS_PLATFORM_64BIT
9171256Syl150051 	        if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
9181256Syl150051 		        channel->stats.avg_post_size =
9191256Syl150051 			(u32)(latest->tmac_ttl_less_fb_octets /
9201256Syl150051 				channel->stats.total_posts);
9211256Syl150051 	        }
9221256Syl150051 #endif
9231256Syl150051 	}
9241256Syl150051 
9251256Syl150051 #ifdef XGE_OS_PLATFORM_64BIT
9261256Syl150051 	if (channel->stats.total_buffers &&
9271256Syl150051 	    channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
9281256Syl150051 		channel->stats.avg_buffer_size =
9291256Syl150051 			(u32)(latest->tmac_ttl_less_fb_octets /
9301256Syl150051 				channel->stats.total_buffers);
9311256Syl150051 	}
9321256Syl150051 #endif
9331256Syl150051 
9341256Syl150051 	*channel_info = &channel->stats;
9351256Syl150051 	return XGE_HAL_OK;
9361256Syl150051 }
9371256Syl150051 
9381256Syl150051 /**
9391256Syl150051  * xge_hal_stats_reset - Reset (zero-out) device statistics
9401256Syl150051  * @devh: HAL device handle.
9411256Syl150051  *
9421256Syl150051  * Reset all device statistics.
9431256Syl150051  * Returns: XGE_HAL_OK - success.
9441256Syl150051  * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
9451256Syl150051  * currently available.
9461256Syl150051  *
9471256Syl150051  * See also: xge_hal_status_e{}, xge_hal_stats_channel_info_t{},
9481256Syl150051  * xge_hal_stats_sw_err_t{}, xge_hal_stats_device_info_t{}.
9491256Syl150051  */
9501256Syl150051 xge_hal_status_e
xge_hal_stats_reset(xge_hal_device_h devh)9511256Syl150051 xge_hal_stats_reset(xge_hal_device_h devh)
9521256Syl150051 {
9531256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
9541256Syl150051 
9551256Syl150051 	if (!hldev->stats.is_initialized ||
9561256Syl150051 	    !hldev->stats.is_enabled) {
9571256Syl150051 		return XGE_HAL_INF_STATS_IS_NOT_READY;
9581256Syl150051 	}
9591256Syl150051 
9601256Syl150051 	/* save hw stats to calculate the after-reset values */
9611256Syl150051 	__hal_stats_save(&hldev->stats);
9621256Syl150051 
9631256Syl150051 	/* zero-out driver-maintained stats, don't reset the saved */
9641256Syl150051         __hal_stats_soft_reset(hldev, 0);
9651256Syl150051 
9661256Syl150051 	return XGE_HAL_OK;
9671256Syl150051 }
9681256Syl150051 
9691256Syl150051 /*
9701256Syl150051  * __hal_stats_soft_reset - Reset software-maintained statistics.
9711256Syl150051  */
9721256Syl150051 void
__hal_stats_soft_reset(xge_hal_device_h devh,int reset_all)9731256Syl150051 __hal_stats_soft_reset (xge_hal_device_h devh, int reset_all)
9741256Syl150051 {
9751256Syl150051 	xge_list_t *item;
9761256Syl150051 	xge_hal_channel_t *channel;
9771256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
9781256Syl150051 
9791256Syl150051         if (reset_all)  {
980*6937Sxw161283 		if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) {
981*6937Sxw161283 			xge_os_memzero(&hldev->stats.hw_info_saved,
982*6937Sxw161283 		               sizeof(xge_hal_stats_hw_info_t));
983*6937Sxw161283 			xge_os_memzero(&hldev->stats.hw_info_latest,
9841256Syl150051 		               sizeof(xge_hal_stats_hw_info_t));
985*6937Sxw161283 		} else {
986*6937Sxw161283 			xge_os_memzero(&hldev->stats.pcim_info_saved,
987*6937Sxw161283 		               sizeof(xge_hal_stats_pcim_info_t));
988*6937Sxw161283 			xge_os_memzero(&hldev->stats.pcim_info_latest,
989*6937Sxw161283 		               sizeof(xge_hal_stats_pcim_info_t));
990*6937Sxw161283 		}
9911256Syl150051         }
9921256Syl150051 
9931256Syl150051 	/* Reset the "soft" error and informational statistics */
9941256Syl150051 	xge_os_memzero(&hldev->stats.sw_dev_err_stats,
9951256Syl150051 	             sizeof(xge_hal_stats_sw_err_t));
9961256Syl150051 	xge_os_memzero(&hldev->stats.sw_dev_info_stats,
9971256Syl150051 	             sizeof(xge_hal_stats_device_info_t));
9981256Syl150051 
9991256Syl150051 	/* for each Rx channel */
10001256Syl150051 	xge_list_for_each(item, &hldev->ring_channels) {
10011256Syl150051 		channel = xge_container_of(item, xge_hal_channel_t, item);
10021256Syl150051 		xge_os_memzero(&channel->stats,
10031256Syl150051 		             sizeof(xge_hal_stats_channel_info_t));
10041256Syl150051 	}
10051256Syl150051 
10061256Syl150051 	/* for each Tx channel */
10071256Syl150051 	xge_list_for_each(item, &hldev->fifo_channels) {
10081256Syl150051 		channel = xge_container_of(item, xge_hal_channel_t, item);
10091256Syl150051 		xge_os_memzero(&channel->stats,
10101256Syl150051 		             sizeof(xge_hal_stats_channel_info_t));
10111256Syl150051 	}
10121256Syl150051 }
10131256Syl150051 
1014