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