1171095Ssam/*-
2171095Ssam * Copyright (c) 2002-2007 Neterion, Inc.
3171095Ssam * All rights reserved.
4171095Ssam *
5171095Ssam * Redistribution and use in source and binary forms, with or without
6171095Ssam * modification, are permitted provided that the following conditions
7171095Ssam * are met:
8171095Ssam * 1. Redistributions of source code must retain the above copyright
9171095Ssam *    notice, this list of conditions and the following disclaimer.
10171095Ssam * 2. Redistributions in binary form must reproduce the above copyright
11171095Ssam *    notice, this list of conditions and the following disclaimer in the
12171095Ssam *    documentation and/or other materials provided with the distribution.
13171095Ssam *
14171095Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15171095Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16171095Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17171095Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18171095Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19171095Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20171095Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21171095Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22171095Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23171095Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24171095Ssam * SUCH DAMAGE.
25171095Ssam *
26171095Ssam * $FreeBSD: releng/11.0/sys/dev/nxge/xgehal/xgehal-stats.c 173139 2007-10-29 14:19:32Z rwatson $
27171095Ssam */
28171095Ssam
29171095Ssam#include <dev/nxge/include/xgehal-stats.h>
30171095Ssam#include <dev/nxge/include/xgehal-device.h>
31171095Ssam
32171095Ssam/*
33171095Ssam * __hal_stats_initialize
34171095Ssam * @stats: xge_hal_stats_t structure that contains, in particular,
35171095Ssam *         Xframe hw stat counters.
36171095Ssam * @devh: HAL device handle.
37171095Ssam *
38171095Ssam * Initialize per-device statistics object.
39171095Ssam * See also: xge_hal_stats_getinfo(), xge_hal_status_e{}.
40171095Ssam */
41171095Ssamxge_hal_status_e
42171095Ssam__hal_stats_initialize (xge_hal_stats_t *stats, xge_hal_device_h devh)
43171095Ssam{
44171095Ssam	int dma_flags;
45171095Ssam	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
46171095Ssam
47171095Ssam	xge_assert(!stats->is_initialized);
48171095Ssam
49171095Ssam	dma_flags = XGE_OS_DMA_CACHELINE_ALIGNED;
50171095Ssam#ifdef XGE_HAL_DMA_STATS_CONSISTENT
51171095Ssam	dma_flags |= XGE_OS_DMA_CONSISTENT;
52171095Ssam#else
53171095Ssam	dma_flags |= XGE_OS_DMA_STREAMING;
54171095Ssam#endif
55171095Ssam	if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) {
56173139Srwatson	    stats->hw_info =
57173139Srwatson	        (xge_hal_stats_hw_info_t *) xge_os_dma_malloc(
58173139Srwatson	                hldev->pdev,
59173139Srwatson	                sizeof(xge_hal_stats_hw_info_t),
60173139Srwatson	                dma_flags,
61173139Srwatson	                &stats->hw_info_dmah,
62173139Srwatson	                &stats->hw_info_dma_acch);
63171095Ssam
64173139Srwatson	    if (stats->hw_info == NULL) {
65173139Srwatson	        xge_debug_stats(XGE_ERR, "%s", "can not DMA alloc");
66173139Srwatson	        return XGE_HAL_ERR_OUT_OF_MEMORY;
67173139Srwatson	    }
68173139Srwatson	    xge_os_memzero(stats->hw_info,
69173139Srwatson	        sizeof(xge_hal_stats_hw_info_t));
70173139Srwatson	    xge_os_memzero(&stats->hw_info_saved,
71173139Srwatson	        sizeof(xge_hal_stats_hw_info_t));
72173139Srwatson	    xge_os_memzero(&stats->hw_info_latest,
73173139Srwatson	        sizeof(xge_hal_stats_hw_info_t));
74171095Ssam
75171095Ssam
76171095Ssam
77173139Srwatson	    stats->dma_addr = xge_os_dma_map(hldev->pdev,
78171095Ssam	                               stats->hw_info_dmah,
79173139Srwatson	                   stats->hw_info,
80173139Srwatson	                   sizeof(xge_hal_stats_hw_info_t),
81173139Srwatson	                   XGE_OS_DMA_DIR_FROMDEVICE,
82173139Srwatson	                   XGE_OS_DMA_CACHELINE_ALIGNED |
83171095Ssam#ifdef XGE_HAL_DMA_STATS_CONSISTENT
84173139Srwatson	                   XGE_OS_DMA_CONSISTENT
85171095Ssam#else
86173139Srwatson	                       XGE_OS_DMA_STREAMING
87171095Ssam#endif
88173139Srwatson	                                   );
89173139Srwatson	    if (stats->dma_addr == XGE_OS_INVALID_DMA_ADDR) {
90173139Srwatson	        xge_debug_stats(XGE_ERR,
91173139Srwatson	            "can not map vaddr 0x"XGE_OS_LLXFMT" to DMA",
92173139Srwatson	            (unsigned long long)(ulong_t)stats->hw_info);
93173139Srwatson	        xge_os_dma_free(hldev->pdev,
94173139Srwatson	              stats->hw_info,
95173139Srwatson	              sizeof(xge_hal_stats_hw_info_t),
96173139Srwatson	              &stats->hw_info_dma_acch,
97173139Srwatson	              &stats->hw_info_dmah);
98173139Srwatson	        return XGE_HAL_ERR_OUT_OF_MAPPING;
99173139Srwatson	    }
100171095Ssam	}
101171095Ssam	else {
102173139Srwatson	    stats->pcim_info_saved =
103173139Srwatson	        (xge_hal_stats_pcim_info_t *)xge_os_malloc(
104173139Srwatson	        hldev->pdev, sizeof(xge_hal_stats_pcim_info_t));
105173139Srwatson	    if (stats->pcim_info_saved == NULL) {
106173139Srwatson	        xge_debug_stats(XGE_ERR, "%s", "can not alloc");
107173139Srwatson	        return XGE_HAL_ERR_OUT_OF_MEMORY;
108173139Srwatson	    }
109171095Ssam
110173139Srwatson	    stats->pcim_info_latest =
111173139Srwatson	        (xge_hal_stats_pcim_info_t *)xge_os_malloc(
112173139Srwatson	        hldev->pdev, sizeof(xge_hal_stats_pcim_info_t));
113173139Srwatson	    if (stats->pcim_info_latest == NULL) {
114173139Srwatson	        xge_os_free(hldev->pdev, stats->pcim_info_saved,
115173139Srwatson	            sizeof(xge_hal_stats_pcim_info_t));
116173139Srwatson	        xge_debug_stats(XGE_ERR, "%s", "can not alloc");
117173139Srwatson	        return XGE_HAL_ERR_OUT_OF_MEMORY;
118173139Srwatson	    }
119171095Ssam
120173139Srwatson	    stats->pcim_info =
121173139Srwatson	        (xge_hal_stats_pcim_info_t *) xge_os_dma_malloc(
122173139Srwatson	                hldev->pdev,
123173139Srwatson	                sizeof(xge_hal_stats_pcim_info_t),
124173139Srwatson	                dma_flags,
125173139Srwatson	                &stats->hw_info_dmah,
126173139Srwatson	                &stats->hw_info_dma_acch);
127171095Ssam
128173139Srwatson	    if (stats->pcim_info == NULL) {
129173139Srwatson	        xge_os_free(hldev->pdev, stats->pcim_info_saved,
130173139Srwatson	            sizeof(xge_hal_stats_pcim_info_t));
131173139Srwatson	        xge_os_free(hldev->pdev, stats->pcim_info_latest,
132173139Srwatson	            sizeof(xge_hal_stats_pcim_info_t));
133173139Srwatson	        xge_debug_stats(XGE_ERR, "%s", "can not DMA alloc");
134173139Srwatson	        return XGE_HAL_ERR_OUT_OF_MEMORY;
135173139Srwatson	    }
136171095Ssam
137171095Ssam
138173139Srwatson	    xge_os_memzero(stats->pcim_info,
139173139Srwatson	        sizeof(xge_hal_stats_pcim_info_t));
140173139Srwatson	    xge_os_memzero(stats->pcim_info_saved,
141173139Srwatson	        sizeof(xge_hal_stats_pcim_info_t));
142173139Srwatson	    xge_os_memzero(stats->pcim_info_latest,
143173139Srwatson	        sizeof(xge_hal_stats_pcim_info_t));
144171095Ssam
145171095Ssam
146171095Ssam
147173139Srwatson	    stats->dma_addr = xge_os_dma_map(hldev->pdev,
148171095Ssam	                               stats->hw_info_dmah,
149173139Srwatson	                   stats->pcim_info,
150173139Srwatson	                   sizeof(xge_hal_stats_pcim_info_t),
151173139Srwatson	                   XGE_OS_DMA_DIR_FROMDEVICE,
152173139Srwatson	                   XGE_OS_DMA_CACHELINE_ALIGNED |
153171095Ssam#ifdef XGE_HAL_DMA_STATS_CONSISTENT
154173139Srwatson	                   XGE_OS_DMA_CONSISTENT
155171095Ssam#else
156173139Srwatson	                       XGE_OS_DMA_STREAMING
157171095Ssam#endif
158173139Srwatson	                                   );
159173139Srwatson	    if (stats->dma_addr == XGE_OS_INVALID_DMA_ADDR) {
160173139Srwatson	        xge_debug_stats(XGE_ERR,
161173139Srwatson	            "can not map vaddr 0x"XGE_OS_LLXFMT" to DMA",
162173139Srwatson	            (unsigned long long)(ulong_t)stats->hw_info);
163171095Ssam
164173139Srwatson	        xge_os_dma_free(hldev->pdev,
165173139Srwatson	              stats->pcim_info,
166173139Srwatson	              sizeof(xge_hal_stats_pcim_info_t),
167173139Srwatson	              &stats->hw_info_dma_acch,
168173139Srwatson	              &stats->hw_info_dmah);
169171095Ssam
170173139Srwatson	        xge_os_free(hldev->pdev, stats->pcim_info_saved,
171173139Srwatson	            sizeof(xge_hal_stats_pcim_info_t));
172171095Ssam
173173139Srwatson	        xge_os_free(hldev->pdev, stats->pcim_info_latest,
174173139Srwatson	            sizeof(xge_hal_stats_pcim_info_t));
175171095Ssam
176173139Srwatson	        return XGE_HAL_ERR_OUT_OF_MAPPING;
177173139Srwatson	    }
178171095Ssam	}
179171095Ssam	stats->devh = devh;
180171095Ssam	xge_os_memzero(&stats->sw_dev_info_stats,
181173139Srwatson	         sizeof(xge_hal_stats_device_info_t));
182171095Ssam
183171095Ssam	stats->is_initialized = 1;
184171095Ssam
185171095Ssam	return XGE_HAL_OK;
186171095Ssam}
187171095Ssam
188171095Ssamstatic void
189171095Ssam__hal_stats_save (xge_hal_stats_t *stats)
190171095Ssam{
191171095Ssam	xge_hal_device_t *hldev = (xge_hal_device_t*)stats->devh;
192171095Ssam
193171095Ssam	if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) {
194173139Srwatson	    xge_hal_stats_hw_info_t *latest;
195171095Ssam
196173139Srwatson	    (void) xge_hal_stats_hw(stats->devh, &latest);
197171095Ssam
198173139Srwatson	    xge_os_memcpy(&stats->hw_info_saved, stats->hw_info,
199173139Srwatson	          sizeof(xge_hal_stats_hw_info_t));
200171095Ssam	} else {
201173139Srwatson	    xge_hal_stats_pcim_info_t   *latest;
202171095Ssam
203173139Srwatson	    (void) xge_hal_stats_pcim(stats->devh, &latest);
204171095Ssam
205173139Srwatson	    xge_os_memcpy(stats->pcim_info_saved, stats->pcim_info,
206173139Srwatson	          sizeof(xge_hal_stats_pcim_info_t));
207171095Ssam	}
208171095Ssam}
209171095Ssam
210171095Ssam/*
211171095Ssam * __hal_stats_disable
212171095Ssam * @stats: xge_hal_stats_t structure that contains, in particular,
213171095Ssam *         Xframe hw stat counters.
214171095Ssam *
215171095Ssam * Ask device to stop collecting stats.
216171095Ssam * See also: xge_hal_stats_getinfo().
217171095Ssam */
218171095Ssamvoid
219171095Ssam__hal_stats_disable (xge_hal_stats_t *stats)
220171095Ssam{
221171095Ssam	xge_hal_device_t *hldev;
222171095Ssam	xge_hal_pci_bar0_t *bar0;
223171095Ssam	u64 val64;
224171095Ssam
225171095Ssam	xge_assert(stats->hw_info);
226171095Ssam
227171095Ssam	hldev = (xge_hal_device_t*)stats->devh;
228171095Ssam	xge_assert(hldev);
229171095Ssam	bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
230171095Ssam
231171095Ssam	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
232173139Srwatson	    &bar0->stat_cfg);
233171095Ssam	val64 &= ~XGE_HAL_STAT_CFG_STAT_EN;
234171095Ssam	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
235173139Srwatson	    &bar0->stat_cfg);
236171095Ssam	/* flush the write */
237171095Ssam	(void)xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
238173139Srwatson	    &bar0->stat_cfg);
239171095Ssam
240171095Ssam	xge_debug_stats(XGE_TRACE, "stats disabled at 0x"XGE_OS_LLXFMT,
241173139Srwatson	     (unsigned long long)stats->dma_addr);
242171095Ssam
243171095Ssam	stats->is_enabled = 0;
244171095Ssam}
245171095Ssam
246171095Ssam/*
247171095Ssam * __hal_stats_terminate
248171095Ssam * @stats: xge_hal_stats_t structure that contains, in particular,
249171095Ssam *         Xframe hw stat counters.
250171095Ssam * Terminate per-device statistics object.
251171095Ssam */
252171095Ssamvoid
253171095Ssam__hal_stats_terminate (xge_hal_stats_t *stats)
254171095Ssam{
255171095Ssam	xge_hal_device_t *hldev;
256171095Ssam
257171095Ssam	xge_assert(stats->hw_info);
258171095Ssam
259171095Ssam	hldev = (xge_hal_device_t*)stats->devh;
260171095Ssam	xge_assert(hldev);
261171095Ssam	xge_assert(stats->is_initialized);
262171095Ssam	if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) {
263173139Srwatson	    xge_os_dma_unmap(hldev->pdev,
264171095Ssam	               stats->hw_info_dmah,
265173139Srwatson	           stats->dma_addr,
266173139Srwatson	           sizeof(xge_hal_stats_hw_info_t),
267173139Srwatson	           XGE_OS_DMA_DIR_FROMDEVICE);
268171095Ssam
269173139Srwatson	    xge_os_dma_free(hldev->pdev,
270173139Srwatson	          stats->hw_info,
271173139Srwatson	          sizeof(xge_hal_stats_hw_info_t),
272173139Srwatson	          &stats->hw_info_dma_acch,
273173139Srwatson	          &stats->hw_info_dmah);
274171095Ssam	} else {
275173139Srwatson	    xge_os_dma_unmap(hldev->pdev,
276171095Ssam	               stats->hw_info_dmah,
277173139Srwatson	           stats->dma_addr,
278173139Srwatson	           sizeof(xge_hal_stats_pcim_info_t),
279173139Srwatson	           XGE_OS_DMA_DIR_FROMDEVICE);
280171095Ssam
281173139Srwatson	    xge_os_dma_free(hldev->pdev,
282173139Srwatson	          stats->pcim_info,
283173139Srwatson	          sizeof(xge_hal_stats_pcim_info_t),
284173139Srwatson	          &stats->hw_info_dma_acch,
285173139Srwatson	          &stats->hw_info_dmah);
286171095Ssam
287173139Srwatson	    xge_os_free(hldev->pdev, stats->pcim_info_saved,
288173139Srwatson	        sizeof(xge_hal_stats_pcim_info_t));
289171095Ssam
290173139Srwatson	    xge_os_free(hldev->pdev, stats->pcim_info_latest,
291173139Srwatson	            sizeof(xge_hal_stats_pcim_info_t));
292171095Ssam
293171095Ssam	}
294171095Ssam
295171095Ssam	stats->is_initialized = 0;
296171095Ssam	stats->is_enabled = 0;
297171095Ssam}
298171095Ssam
299171095Ssam
300171095Ssam
301171095Ssam/*
302171095Ssam * __hal_stats_enable
303171095Ssam * @stats: xge_hal_stats_t structure that contains, in particular,
304171095Ssam *         Xframe hw stat counters.
305171095Ssam *
306171095Ssam * Ask device to start collecting stats.
307171095Ssam * See also: xge_hal_stats_getinfo().
308171095Ssam */
309171095Ssamvoid
310171095Ssam__hal_stats_enable (xge_hal_stats_t *stats)
311171095Ssam{
312171095Ssam	xge_hal_device_t *hldev;
313171095Ssam	xge_hal_pci_bar0_t *bar0;
314171095Ssam	u64 val64;
315171095Ssam	unsigned int refresh_time_pci_clocks;
316171095Ssam
317171095Ssam	xge_assert(stats->hw_info);
318171095Ssam
319171095Ssam	hldev = (xge_hal_device_t*)stats->devh;
320171095Ssam	xge_assert(hldev);
321171095Ssam
322171095Ssam	bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
323171095Ssam
324171095Ssam	/* enable statistics
325171095Ssam	 * For Titan stat_addr offset == 0x09d8, and stat_cfg offset == 0x09d0
326171095Ssam	*/
327171095Ssam	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
328173139Srwatson	    stats->dma_addr, &bar0->stat_addr);
329171095Ssam
330171095Ssam	refresh_time_pci_clocks = XGE_HAL_XENA_PER_SEC *
331173139Srwatson	    hldev->config.stats_refresh_time_sec;
332171095Ssam	refresh_time_pci_clocks =
333173139Srwatson	    __hal_fix_time_ival_herc(hldev,
334173139Srwatson	        refresh_time_pci_clocks);
335171095Ssam
336171095Ssam#ifdef XGE_HAL_HERC_EMULATION
337171095Ssam	/*
338171095Ssam	 *  The clocks in the emulator are running ~1000 times slower
339171095Ssam	 *  than real world, so the stats transfer will occur ~1000
340171095Ssam	 *  times less frequent. STAT_CFG.STAT_TRSF_PERIOD should be
341171095Ssam	 *  set to 0x20C for Hercules emulation (stats transferred
342171095Ssam	 *  every 0.5 sec).
343171095Ssam	*/
344171095Ssam
345171095Ssam	val64 = (0x20C | XGE_HAL_STAT_CFG_STAT_RO |
346173139Srwatson	    XGE_HAL_STAT_CFG_STAT_EN);
347171095Ssam#else
348171095Ssam	val64 = XGE_HAL_SET_UPDT_PERIOD(refresh_time_pci_clocks) |
349173139Srwatson	                    XGE_HAL_STAT_CFG_STAT_RO |
350173139Srwatson	            XGE_HAL_STAT_CFG_STAT_EN;
351171095Ssam#endif
352171095Ssam
353171095Ssam	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
354173139Srwatson	    val64, &bar0->stat_cfg);
355171095Ssam
356171095Ssam	xge_debug_stats(XGE_TRACE, "stats enabled at 0x"XGE_OS_LLXFMT,
357173139Srwatson	     (unsigned long long)stats->dma_addr);
358171095Ssam
359171095Ssam	stats->is_enabled = 1;
360171095Ssam}
361171095Ssam
362171095Ssam/*
363171095Ssam * __hal_stats_pcim_update_latest - Update hw ER stats counters, based on the
364171095Ssam * real hardware maintained counters and the stored "reset" values.
365171095Ssam */
366171095Ssamstatic void
367171095Ssam__hal_stats_pcim_update_latest(xge_hal_device_h devh)
368171095Ssam{
369171095Ssam	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
370171095Ssam	int i;
371171095Ssam
372173139Srwatson#define set_latest_stat_link_cnt(_link, _p)                   \
373173139Srwatson	    hldev->stats.pcim_info_latest->link_info[_link]._p =              \
374173139Srwatson	((hldev->stats.pcim_info->link_info[_link]._p >=                  \
375173139Srwatson	    hldev->stats.pcim_info_saved->link_info[_link]._p) ?          \
376173139Srwatson	    hldev->stats.pcim_info->link_info[_link]._p -             \
377173139Srwatson	        hldev->stats.pcim_info_saved->link_info[_link]._p :   \
378173139Srwatson	    ((-1) - hldev->stats.pcim_info_saved->link_info[_link]._p) +  \
379173139Srwatson	        hldev->stats.pcim_info->link_info[_link]._p)
380171095Ssam
381171095Ssam
382173139Srwatson#define set_latest_stat_aggr_cnt(_aggr, _p)                   \
383173139Srwatson	    hldev->stats.pcim_info_latest->aggr_info[_aggr]._p =              \
384173139Srwatson	((hldev->stats.pcim_info->aggr_info[_aggr]._p >=              \
385173139Srwatson	    hldev->stats.pcim_info_saved->aggr_info[_aggr]._p) ?          \
386173139Srwatson	    hldev->stats.pcim_info->aggr_info[_aggr]._p -             \
387173139Srwatson	        hldev->stats.pcim_info_saved->aggr_info[_aggr]._p :   \
388173139Srwatson	    ((-1) - hldev->stats.pcim_info_saved->aggr_info[_aggr]._p) +  \
389173139Srwatson	        hldev->stats.pcim_info->aggr_info[_aggr]._p)
390171095Ssam
391171095Ssam
392171095Ssam	for (i = 0; i < XGE_HAL_MAC_LINKS; i++) {
393173139Srwatson	    set_latest_stat_link_cnt(i, tx_frms);
394173139Srwatson	    set_latest_stat_link_cnt(i, tx_ttl_eth_octets);
395173139Srwatson	    set_latest_stat_link_cnt(i, tx_data_octets);
396173139Srwatson	    set_latest_stat_link_cnt(i, tx_mcst_frms);
397173139Srwatson	    set_latest_stat_link_cnt(i, tx_bcst_frms);
398173139Srwatson	    set_latest_stat_link_cnt(i, tx_ucst_frms);
399173139Srwatson	    set_latest_stat_link_cnt(i, tx_tagged_frms);
400173139Srwatson	    set_latest_stat_link_cnt(i, tx_vld_ip);
401173139Srwatson	    set_latest_stat_link_cnt(i, tx_vld_ip_octets);
402173139Srwatson	    set_latest_stat_link_cnt(i, tx_icmp);
403173139Srwatson	    set_latest_stat_link_cnt(i, tx_tcp);
404173139Srwatson	    set_latest_stat_link_cnt(i, tx_rst_tcp);
405173139Srwatson	    set_latest_stat_link_cnt(i, tx_udp);
406173139Srwatson	    set_latest_stat_link_cnt(i, tx_unknown_protocol);
407173139Srwatson	    set_latest_stat_link_cnt(i, tx_parse_error);
408173139Srwatson	    set_latest_stat_link_cnt(i, tx_pause_ctrl_frms);
409173139Srwatson	    set_latest_stat_link_cnt(i, tx_lacpdu_frms);
410173139Srwatson	    set_latest_stat_link_cnt(i, tx_marker_pdu_frms);
411173139Srwatson	    set_latest_stat_link_cnt(i, tx_marker_resp_pdu_frms);
412173139Srwatson	    set_latest_stat_link_cnt(i, tx_drop_ip);
413173139Srwatson	    set_latest_stat_link_cnt(i, tx_xgmii_char1_match);
414173139Srwatson	    set_latest_stat_link_cnt(i, tx_xgmii_char2_match);
415173139Srwatson	    set_latest_stat_link_cnt(i, tx_xgmii_column1_match);
416173139Srwatson	    set_latest_stat_link_cnt(i, tx_xgmii_column2_match);
417173139Srwatson	    set_latest_stat_link_cnt(i, tx_drop_frms);
418173139Srwatson	    set_latest_stat_link_cnt(i, tx_any_err_frms);
419173139Srwatson	    set_latest_stat_link_cnt(i, rx_ttl_frms);
420173139Srwatson	    set_latest_stat_link_cnt(i, rx_vld_frms);
421173139Srwatson	    set_latest_stat_link_cnt(i, rx_offld_frms);
422173139Srwatson	    set_latest_stat_link_cnt(i, rx_ttl_eth_octets);
423173139Srwatson	    set_latest_stat_link_cnt(i, rx_data_octets);
424173139Srwatson	    set_latest_stat_link_cnt(i, rx_offld_octets);
425173139Srwatson	    set_latest_stat_link_cnt(i, rx_vld_mcst_frms);
426173139Srwatson	    set_latest_stat_link_cnt(i, rx_vld_bcst_frms);
427173139Srwatson	    set_latest_stat_link_cnt(i, rx_accepted_ucst_frms);
428173139Srwatson	    set_latest_stat_link_cnt(i, rx_accepted_nucst_frms);
429173139Srwatson	    set_latest_stat_link_cnt(i, rx_tagged_frms);
430173139Srwatson	    set_latest_stat_link_cnt(i, rx_long_frms);
431173139Srwatson	    set_latest_stat_link_cnt(i, rx_usized_frms);
432173139Srwatson	    set_latest_stat_link_cnt(i, rx_osized_frms);
433173139Srwatson	    set_latest_stat_link_cnt(i, rx_frag_frms);
434173139Srwatson	    set_latest_stat_link_cnt(i, rx_jabber_frms);
435173139Srwatson	    set_latest_stat_link_cnt(i, rx_ttl_64_frms);
436173139Srwatson	    set_latest_stat_link_cnt(i, rx_ttl_65_127_frms);
437173139Srwatson	    set_latest_stat_link_cnt(i, rx_ttl_128_255_frms);
438173139Srwatson	    set_latest_stat_link_cnt(i, rx_ttl_256_511_frms);
439173139Srwatson	    set_latest_stat_link_cnt(i, rx_ttl_512_1023_frms);
440173139Srwatson	    set_latest_stat_link_cnt(i, rx_ttl_1024_1518_frms);
441173139Srwatson	    set_latest_stat_link_cnt(i, rx_ttl_1519_4095_frms);
442173139Srwatson	    set_latest_stat_link_cnt(i, rx_ttl_40956_8191_frms);
443173139Srwatson	    set_latest_stat_link_cnt(i, rx_ttl_8192_max_frms);
444173139Srwatson	    set_latest_stat_link_cnt(i, rx_ttl_gt_max_frms);
445173139Srwatson	    set_latest_stat_link_cnt(i, rx_ip);
446173139Srwatson	    set_latest_stat_link_cnt(i, rx_ip_octets);
447173139Srwatson	    set_latest_stat_link_cnt(i, rx_hdr_err_ip);
448173139Srwatson	    set_latest_stat_link_cnt(i, rx_icmp);
449173139Srwatson	    set_latest_stat_link_cnt(i, rx_tcp);
450173139Srwatson	    set_latest_stat_link_cnt(i, rx_udp);
451173139Srwatson	    set_latest_stat_link_cnt(i, rx_err_tcp);
452173139Srwatson	    set_latest_stat_link_cnt(i, rx_pause_cnt);
453173139Srwatson	    set_latest_stat_link_cnt(i, rx_pause_ctrl_frms);
454173139Srwatson	    set_latest_stat_link_cnt(i, rx_unsup_ctrl_frms);
455173139Srwatson	    set_latest_stat_link_cnt(i, rx_in_rng_len_err_frms);
456173139Srwatson	    set_latest_stat_link_cnt(i, rx_out_rng_len_err_frms);
457173139Srwatson	    set_latest_stat_link_cnt(i, rx_drop_frms);
458173139Srwatson	    set_latest_stat_link_cnt(i, rx_discarded_frms);
459173139Srwatson	    set_latest_stat_link_cnt(i, rx_drop_ip);
460173139Srwatson	    set_latest_stat_link_cnt(i, rx_err_drp_udp);
461173139Srwatson	    set_latest_stat_link_cnt(i, rx_lacpdu_frms);
462173139Srwatson	    set_latest_stat_link_cnt(i, rx_marker_pdu_frms);
463173139Srwatson	    set_latest_stat_link_cnt(i, rx_marker_resp_pdu_frms);
464173139Srwatson	    set_latest_stat_link_cnt(i, rx_unknown_pdu_frms);
465173139Srwatson	    set_latest_stat_link_cnt(i, rx_illegal_pdu_frms);
466173139Srwatson	    set_latest_stat_link_cnt(i, rx_fcs_discard);
467173139Srwatson	    set_latest_stat_link_cnt(i, rx_len_discard);
468173139Srwatson	    set_latest_stat_link_cnt(i, rx_pf_discard);
469173139Srwatson	    set_latest_stat_link_cnt(i, rx_trash_discard);
470173139Srwatson	    set_latest_stat_link_cnt(i, rx_rts_discard);
471173139Srwatson	    set_latest_stat_link_cnt(i, rx_wol_discard);
472173139Srwatson	    set_latest_stat_link_cnt(i, rx_red_discard);
473173139Srwatson	    set_latest_stat_link_cnt(i, rx_ingm_full_discard);
474173139Srwatson	    set_latest_stat_link_cnt(i, rx_xgmii_data_err_cnt);
475173139Srwatson	    set_latest_stat_link_cnt(i, rx_xgmii_ctrl_err_cnt);
476173139Srwatson	    set_latest_stat_link_cnt(i, rx_xgmii_err_sym);
477173139Srwatson	    set_latest_stat_link_cnt(i, rx_xgmii_char1_match);
478173139Srwatson	    set_latest_stat_link_cnt(i, rx_xgmii_char2_match);
479173139Srwatson	    set_latest_stat_link_cnt(i, rx_xgmii_column1_match);
480173139Srwatson	    set_latest_stat_link_cnt(i, rx_xgmii_column2_match);
481173139Srwatson	    set_latest_stat_link_cnt(i, rx_local_fault);
482173139Srwatson	    set_latest_stat_link_cnt(i, rx_remote_fault);
483173139Srwatson	    set_latest_stat_link_cnt(i, rx_queue_full);
484171095Ssam	}
485171095Ssam
486171095Ssam	for (i = 0; i < XGE_HAL_MAC_AGGREGATORS; i++) {
487173139Srwatson	    set_latest_stat_aggr_cnt(i, tx_frms);
488173139Srwatson	    set_latest_stat_aggr_cnt(i, tx_mcst_frms);
489173139Srwatson	    set_latest_stat_aggr_cnt(i, tx_bcst_frms);
490173139Srwatson	    set_latest_stat_aggr_cnt(i, tx_discarded_frms);
491173139Srwatson	    set_latest_stat_aggr_cnt(i, tx_errored_frms);
492173139Srwatson	    set_latest_stat_aggr_cnt(i, rx_frms);
493173139Srwatson	    set_latest_stat_aggr_cnt(i, rx_data_octets);
494173139Srwatson	    set_latest_stat_aggr_cnt(i, rx_mcst_frms);
495173139Srwatson	    set_latest_stat_aggr_cnt(i, rx_bcst_frms);
496173139Srwatson	    set_latest_stat_aggr_cnt(i, rx_discarded_frms);
497173139Srwatson	    set_latest_stat_aggr_cnt(i, rx_errored_frms);
498173139Srwatson	    set_latest_stat_aggr_cnt(i, rx_unknown_protocol_frms);
499171095Ssam	}
500171095Ssam	return;
501171095Ssam}
502171095Ssam
503171095Ssam/*
504171095Ssam * __hal_stats_update_latest - Update hw stats counters, based on the real
505171095Ssam * hardware maintained counters and the stored "reset" values.
506171095Ssam */
507171095Ssamstatic void
508171095Ssam__hal_stats_update_latest(xge_hal_device_h devh)
509171095Ssam{
510171095Ssam	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
511171095Ssam
512171095Ssam#define set_latest_stat_cnt(_dev, _p)                                   \
513173139Srwatson	    hldev->stats.hw_info_latest._p =                                \
514171095Ssam	((hldev->stats.hw_info->_p >= hldev->stats.hw_info_saved._p) ?  \
515173139Srwatson	      hldev->stats.hw_info->_p - hldev->stats.hw_info_saved._p :    \
516171095Ssam	  ((-1) - hldev->stats.hw_info_saved._p) + hldev->stats.hw_info->_p)
517171095Ssam
518171095Ssam	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_TITAN) {
519173139Srwatson	    __hal_stats_pcim_update_latest(devh);
520173139Srwatson	    return;
521171095Ssam	}
522171095Ssam
523171095Ssam	/* Tx MAC statistics counters. */
524171095Ssam	set_latest_stat_cnt(hldev, tmac_frms);
525171095Ssam	set_latest_stat_cnt(hldev, tmac_data_octets);
526171095Ssam	set_latest_stat_cnt(hldev, tmac_drop_frms);
527171095Ssam	set_latest_stat_cnt(hldev, tmac_mcst_frms);
528171095Ssam	set_latest_stat_cnt(hldev, tmac_bcst_frms);
529171095Ssam	set_latest_stat_cnt(hldev, tmac_pause_ctrl_frms);
530171095Ssam	set_latest_stat_cnt(hldev, tmac_ttl_octets);
531171095Ssam	set_latest_stat_cnt(hldev, tmac_ucst_frms);
532171095Ssam	set_latest_stat_cnt(hldev, tmac_nucst_frms);
533171095Ssam	set_latest_stat_cnt(hldev, tmac_any_err_frms);
534171095Ssam	set_latest_stat_cnt(hldev, tmac_ttl_less_fb_octets);
535171095Ssam	set_latest_stat_cnt(hldev, tmac_vld_ip_octets);
536171095Ssam	set_latest_stat_cnt(hldev, tmac_vld_ip);
537171095Ssam	set_latest_stat_cnt(hldev, tmac_drop_ip);
538171095Ssam	set_latest_stat_cnt(hldev, tmac_icmp);
539171095Ssam	set_latest_stat_cnt(hldev, tmac_rst_tcp);
540171095Ssam	set_latest_stat_cnt(hldev, tmac_tcp);
541171095Ssam	set_latest_stat_cnt(hldev, tmac_udp);
542171095Ssam	set_latest_stat_cnt(hldev, reserved_0);
543171095Ssam
544171095Ssam	/* Rx MAC Statistics counters. */
545171095Ssam	set_latest_stat_cnt(hldev, rmac_vld_frms);
546171095Ssam	set_latest_stat_cnt(hldev, rmac_data_octets);
547171095Ssam	set_latest_stat_cnt(hldev, rmac_fcs_err_frms);
548171095Ssam	set_latest_stat_cnt(hldev, rmac_drop_frms);
549171095Ssam	set_latest_stat_cnt(hldev, rmac_vld_mcst_frms);
550171095Ssam	set_latest_stat_cnt(hldev, rmac_vld_bcst_frms);
551171095Ssam	set_latest_stat_cnt(hldev, rmac_in_rng_len_err_frms);
552171095Ssam	set_latest_stat_cnt(hldev, rmac_out_rng_len_err_frms);
553171095Ssam	set_latest_stat_cnt(hldev, rmac_long_frms);
554171095Ssam	set_latest_stat_cnt(hldev, rmac_pause_ctrl_frms);
555171095Ssam	set_latest_stat_cnt(hldev, rmac_unsup_ctrl_frms);
556171095Ssam	set_latest_stat_cnt(hldev, rmac_ttl_octets);
557171095Ssam	set_latest_stat_cnt(hldev, rmac_accepted_ucst_frms);
558171095Ssam	set_latest_stat_cnt(hldev, rmac_accepted_nucst_frms);
559171095Ssam	set_latest_stat_cnt(hldev, rmac_discarded_frms);
560171095Ssam	set_latest_stat_cnt(hldev, rmac_drop_events);
561171095Ssam	set_latest_stat_cnt(hldev, reserved_1);
562171095Ssam	set_latest_stat_cnt(hldev, rmac_ttl_less_fb_octets);
563171095Ssam	set_latest_stat_cnt(hldev, rmac_ttl_frms);
564171095Ssam	set_latest_stat_cnt(hldev, reserved_2);
565171095Ssam	set_latest_stat_cnt(hldev, reserved_3);
566171095Ssam	set_latest_stat_cnt(hldev, rmac_usized_frms);
567171095Ssam	set_latest_stat_cnt(hldev, rmac_osized_frms);
568171095Ssam	set_latest_stat_cnt(hldev, rmac_frag_frms);
569171095Ssam	set_latest_stat_cnt(hldev, rmac_jabber_frms);
570171095Ssam	set_latest_stat_cnt(hldev, reserved_4);
571171095Ssam	set_latest_stat_cnt(hldev, rmac_ttl_64_frms);
572171095Ssam	set_latest_stat_cnt(hldev, rmac_ttl_65_127_frms);
573171095Ssam	set_latest_stat_cnt(hldev, reserved_5);
574171095Ssam	set_latest_stat_cnt(hldev, rmac_ttl_128_255_frms);
575171095Ssam	set_latest_stat_cnt(hldev, rmac_ttl_256_511_frms);
576171095Ssam	set_latest_stat_cnt(hldev, reserved_6);
577171095Ssam	set_latest_stat_cnt(hldev, rmac_ttl_512_1023_frms);
578171095Ssam	set_latest_stat_cnt(hldev, rmac_ttl_1024_1518_frms);
579171095Ssam	set_latest_stat_cnt(hldev, reserved_7);
580171095Ssam	set_latest_stat_cnt(hldev, rmac_ip);
581171095Ssam	set_latest_stat_cnt(hldev, rmac_ip_octets);
582171095Ssam	set_latest_stat_cnt(hldev, rmac_hdr_err_ip);
583171095Ssam	set_latest_stat_cnt(hldev, rmac_drop_ip);
584171095Ssam	set_latest_stat_cnt(hldev, rmac_icmp);
585171095Ssam	set_latest_stat_cnt(hldev, reserved_8);
586171095Ssam	set_latest_stat_cnt(hldev, rmac_tcp);
587171095Ssam	set_latest_stat_cnt(hldev, rmac_udp);
588171095Ssam	set_latest_stat_cnt(hldev, rmac_err_drp_udp);
589171095Ssam	set_latest_stat_cnt(hldev, rmac_xgmii_err_sym);
590171095Ssam	set_latest_stat_cnt(hldev, rmac_frms_q0);
591171095Ssam	set_latest_stat_cnt(hldev, rmac_frms_q1);
592171095Ssam	set_latest_stat_cnt(hldev, rmac_frms_q2);
593171095Ssam	set_latest_stat_cnt(hldev, rmac_frms_q3);
594171095Ssam	set_latest_stat_cnt(hldev, rmac_frms_q4);
595171095Ssam	set_latest_stat_cnt(hldev, rmac_frms_q5);
596171095Ssam	set_latest_stat_cnt(hldev, rmac_frms_q6);
597171095Ssam	set_latest_stat_cnt(hldev, rmac_frms_q7);
598171095Ssam	set_latest_stat_cnt(hldev, rmac_full_q0);
599171095Ssam	set_latest_stat_cnt(hldev, rmac_full_q1);
600171095Ssam	set_latest_stat_cnt(hldev, rmac_full_q2);
601171095Ssam	set_latest_stat_cnt(hldev, rmac_full_q3);
602171095Ssam	set_latest_stat_cnt(hldev, rmac_full_q4);
603171095Ssam	set_latest_stat_cnt(hldev, rmac_full_q5);
604171095Ssam	set_latest_stat_cnt(hldev, rmac_full_q6);
605171095Ssam	set_latest_stat_cnt(hldev, rmac_full_q7);
606171095Ssam	set_latest_stat_cnt(hldev, rmac_pause_cnt);
607171095Ssam	set_latest_stat_cnt(hldev, reserved_9);
608171095Ssam	set_latest_stat_cnt(hldev, rmac_xgmii_data_err_cnt);
609171095Ssam	set_latest_stat_cnt(hldev, rmac_xgmii_ctrl_err_cnt);
610171095Ssam	set_latest_stat_cnt(hldev, rmac_accepted_ip);
611171095Ssam	set_latest_stat_cnt(hldev, rmac_err_tcp);
612171095Ssam
613171095Ssam	/* PCI/PCI-X Read transaction statistics. */
614171095Ssam	set_latest_stat_cnt(hldev, rd_req_cnt);
615171095Ssam	set_latest_stat_cnt(hldev, new_rd_req_cnt);
616171095Ssam	set_latest_stat_cnt(hldev, new_rd_req_rtry_cnt);
617171095Ssam	set_latest_stat_cnt(hldev, rd_rtry_cnt);
618171095Ssam	set_latest_stat_cnt(hldev, wr_rtry_rd_ack_cnt);
619171095Ssam
620171095Ssam	/* PCI/PCI-X write transaction statistics. */
621171095Ssam	set_latest_stat_cnt(hldev, wr_req_cnt);
622171095Ssam	set_latest_stat_cnt(hldev, new_wr_req_cnt);
623171095Ssam	set_latest_stat_cnt(hldev, new_wr_req_rtry_cnt);
624171095Ssam	set_latest_stat_cnt(hldev, wr_rtry_cnt);
625171095Ssam	set_latest_stat_cnt(hldev, wr_disc_cnt);
626171095Ssam	set_latest_stat_cnt(hldev, rd_rtry_wr_ack_cnt);
627171095Ssam
628171095Ssam	/* DMA Transaction statistics. */
629171095Ssam	set_latest_stat_cnt(hldev, txp_wr_cnt);
630171095Ssam	set_latest_stat_cnt(hldev, txd_rd_cnt);
631171095Ssam	set_latest_stat_cnt(hldev, txd_wr_cnt);
632171095Ssam	set_latest_stat_cnt(hldev, rxd_rd_cnt);
633171095Ssam	set_latest_stat_cnt(hldev, rxd_wr_cnt);
634171095Ssam	set_latest_stat_cnt(hldev, txf_rd_cnt);
635171095Ssam	set_latest_stat_cnt(hldev, rxf_wr_cnt);
636171095Ssam
637171095Ssam	/* Enhanced Herc statistics */
638171095Ssam	set_latest_stat_cnt(hldev, tmac_frms_oflow);
639171095Ssam	set_latest_stat_cnt(hldev, tmac_data_octets_oflow);
640171095Ssam	set_latest_stat_cnt(hldev, tmac_mcst_frms_oflow);
641171095Ssam	set_latest_stat_cnt(hldev, tmac_bcst_frms_oflow);
642171095Ssam	set_latest_stat_cnt(hldev, tmac_ttl_octets_oflow);
643171095Ssam	set_latest_stat_cnt(hldev, tmac_ucst_frms_oflow);
644171095Ssam	set_latest_stat_cnt(hldev, tmac_nucst_frms_oflow);
645171095Ssam	set_latest_stat_cnt(hldev, tmac_any_err_frms_oflow);
646171095Ssam	set_latest_stat_cnt(hldev, tmac_vlan_frms);
647171095Ssam	set_latest_stat_cnt(hldev, tmac_vld_ip_oflow);
648171095Ssam	set_latest_stat_cnt(hldev, tmac_drop_ip_oflow);
649171095Ssam	set_latest_stat_cnt(hldev, tmac_icmp_oflow);
650171095Ssam	set_latest_stat_cnt(hldev, tmac_rst_tcp_oflow);
651171095Ssam	set_latest_stat_cnt(hldev, tmac_udp_oflow);
652171095Ssam	set_latest_stat_cnt(hldev, tpa_unknown_protocol);
653171095Ssam	set_latest_stat_cnt(hldev, tpa_parse_failure);
654171095Ssam	set_latest_stat_cnt(hldev, rmac_vld_frms_oflow);
655171095Ssam	set_latest_stat_cnt(hldev, rmac_data_octets_oflow);
656171095Ssam	set_latest_stat_cnt(hldev, rmac_vld_mcst_frms_oflow);
657171095Ssam	set_latest_stat_cnt(hldev, rmac_vld_bcst_frms_oflow);
658171095Ssam	set_latest_stat_cnt(hldev, rmac_ttl_octets_oflow);
659171095Ssam	set_latest_stat_cnt(hldev, rmac_accepted_ucst_frms_oflow);
660171095Ssam	set_latest_stat_cnt(hldev, rmac_accepted_nucst_frms_oflow);
661171095Ssam	set_latest_stat_cnt(hldev, rmac_discarded_frms_oflow);
662171095Ssam	set_latest_stat_cnt(hldev, rmac_drop_events_oflow);
663171095Ssam	set_latest_stat_cnt(hldev, rmac_usized_frms_oflow);
664171095Ssam	set_latest_stat_cnt(hldev, rmac_osized_frms_oflow);
665171095Ssam	set_latest_stat_cnt(hldev, rmac_frag_frms_oflow);
666171095Ssam	set_latest_stat_cnt(hldev, rmac_jabber_frms_oflow);
667171095Ssam	set_latest_stat_cnt(hldev, rmac_ip_oflow);
668171095Ssam	set_latest_stat_cnt(hldev, rmac_drop_ip_oflow);
669171095Ssam	set_latest_stat_cnt(hldev, rmac_icmp_oflow);
670171095Ssam	set_latest_stat_cnt(hldev, rmac_udp_oflow);
671171095Ssam	set_latest_stat_cnt(hldev, rmac_err_drp_udp_oflow);
672171095Ssam	set_latest_stat_cnt(hldev, rmac_pause_cnt_oflow);
673171095Ssam	set_latest_stat_cnt(hldev, rmac_ttl_1519_4095_frms);
674171095Ssam	set_latest_stat_cnt(hldev, rmac_ttl_4096_8191_frms);
675171095Ssam	set_latest_stat_cnt(hldev, rmac_ttl_8192_max_frms);
676171095Ssam	set_latest_stat_cnt(hldev, rmac_ttl_gt_max_frms);
677171095Ssam	set_latest_stat_cnt(hldev, rmac_osized_alt_frms);
678171095Ssam	set_latest_stat_cnt(hldev, rmac_jabber_alt_frms);
679171095Ssam	set_latest_stat_cnt(hldev, rmac_gt_max_alt_frms);
680171095Ssam	set_latest_stat_cnt(hldev, rmac_vlan_frms);
681171095Ssam	set_latest_stat_cnt(hldev, rmac_fcs_discard);
682171095Ssam	set_latest_stat_cnt(hldev, rmac_len_discard);
683171095Ssam	set_latest_stat_cnt(hldev, rmac_da_discard);
684171095Ssam	set_latest_stat_cnt(hldev, rmac_pf_discard);
685171095Ssam	set_latest_stat_cnt(hldev, rmac_rts_discard);
686171095Ssam	set_latest_stat_cnt(hldev, rmac_red_discard);
687171095Ssam	set_latest_stat_cnt(hldev, rmac_ingm_full_discard);
688171095Ssam	set_latest_stat_cnt(hldev, rmac_accepted_ip_oflow);
689171095Ssam	set_latest_stat_cnt(hldev, link_fault_cnt);
690171095Ssam}
691171095Ssam
692171095Ssam/**
693171095Ssam * xge_hal_stats_hw - Get HW device statistics.
694171095Ssam * @devh: HAL device handle.
695171095Ssam * @hw_info: Xframe statistic counters. See xge_hal_stats_hw_info_t.
696171095Ssam *           Returned by HAL.
697171095Ssam *
698171095Ssam * Get device and HAL statistics. The latter is part of the in-host statistics
699171095Ssam * that HAL maintains for _that_ device.
700171095Ssam *
701171095Ssam * Returns: XGE_HAL_OK - success.
702171095Ssam * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
703171095Ssam * currently available.
704171095Ssam *
705171095Ssam * See also: xge_hal_status_e{}.
706171095Ssam */
707171095Ssamxge_hal_status_e
708171095Ssamxge_hal_stats_hw(xge_hal_device_h devh, xge_hal_stats_hw_info_t **hw_info)
709171095Ssam{
710171095Ssam	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
711171095Ssam
712171095Ssam	xge_assert(xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN)
713171095Ssam
714171095Ssam	if (!hldev->stats.is_initialized ||
715171095Ssam	    !hldev->stats.is_enabled) {
716173139Srwatson	    *hw_info = NULL;
717173139Srwatson	    return XGE_HAL_INF_STATS_IS_NOT_READY;
718171095Ssam	}
719171095Ssam
720171095Ssam#if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_STATS_STREAMING)
721171095Ssam	xge_os_dma_sync(hldev->pdev,
722171095Ssam	              hldev->stats.hw_info_dmah,
723173139Srwatson	          hldev->stats.dma_addr,
724173139Srwatson	          0,
725173139Srwatson	          sizeof(xge_hal_stats_hw_info_t),
726173139Srwatson	          XGE_OS_DMA_DIR_FROMDEVICE);
727171095Ssam#endif
728171095Ssam
729173139Srwatson	    /*
730171095Ssam	 * update hw counters, taking into account
731171095Ssam	 * the "reset" or "saved"
732171095Ssam	 * values
733171095Ssam	 */
734171095Ssam	__hal_stats_update_latest(devh);
735171095Ssam
736171095Ssam	/*
737171095Ssam	 * statistics HW bug fixups for Xena and Herc
738171095Ssam	 */
739171095Ssam	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA ||
740171095Ssam	    xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
741173139Srwatson	    u64 mcst, bcst;
742173139Srwatson	    xge_hal_stats_hw_info_t *hwsta = &hldev->stats.hw_info_latest;
743171095Ssam
744173139Srwatson	    mcst = ((u64)hwsta->rmac_vld_mcst_frms_oflow << 32) |
745173139Srwatson	        hwsta->rmac_vld_mcst_frms;
746171095Ssam
747173139Srwatson	    bcst = ((u64)hwsta->rmac_vld_bcst_frms_oflow << 32) |
748173139Srwatson	        hwsta->rmac_vld_bcst_frms;
749171095Ssam
750173139Srwatson	    mcst -= bcst;
751171095Ssam
752173139Srwatson	    hwsta->rmac_vld_mcst_frms_oflow = (u32)(mcst >> 32);
753173139Srwatson	    hwsta->rmac_vld_mcst_frms = (u32)mcst;
754171095Ssam	}
755171095Ssam
756171095Ssam	*hw_info = &hldev->stats.hw_info_latest;
757171095Ssam
758171095Ssam	return XGE_HAL_OK;
759171095Ssam}
760171095Ssam
761171095Ssam/**
762171095Ssam * xge_hal_stats_pcim - Get HW device statistics.
763171095Ssam * @devh: HAL device handle.
764171095Ssam * @hw_info: Xframe statistic counters. See xge_hal_stats_pcim_info_t.
765171095Ssam *
766171095Ssam * Returns: XGE_HAL_OK - success.
767171095Ssam * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
768171095Ssam * currently available.
769171095Ssam *
770171095Ssam * See also: xge_hal_status_e{}.
771171095Ssam */
772171095Ssamxge_hal_status_e
773171095Ssamxge_hal_stats_pcim(xge_hal_device_h devh, xge_hal_stats_pcim_info_t **hw_info)
774171095Ssam{
775171095Ssam	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
776171095Ssam
777171095Ssam	xge_assert(xge_hal_device_check_id(hldev) == XGE_HAL_CARD_TITAN)
778171095Ssam
779171095Ssam	if (!hldev->stats.is_initialized ||
780171095Ssam	    !hldev->stats.is_enabled) {
781173139Srwatson	    *hw_info = NULL;
782173139Srwatson	    return XGE_HAL_INF_STATS_IS_NOT_READY;
783171095Ssam	}
784171095Ssam
785171095Ssam#if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_STATS_STREAMING)
786171095Ssam	xge_os_dma_sync(hldev->pdev,
787171095Ssam	              hldev->stats.hw_info_dmah,
788173139Srwatson	          hldev->stats.dma_addr,
789173139Srwatson	          0,
790173139Srwatson	          sizeof(xge_hal_stats_pcim_info_t),
791173139Srwatson	          XGE_OS_DMA_DIR_FROMDEVICE);
792171095Ssam#endif
793171095Ssam
794173139Srwatson	    /*
795171095Ssam	 * update hw counters, taking into account
796171095Ssam	 * the "reset" or "saved"
797171095Ssam	 * values
798171095Ssam	 */
799171095Ssam	__hal_stats_pcim_update_latest(devh);
800171095Ssam
801171095Ssam	*hw_info = hldev->stats.pcim_info_latest;
802171095Ssam
803171095Ssam	return XGE_HAL_OK;
804171095Ssam}
805171095Ssam
806171095Ssam/**
807171095Ssam * xge_hal_stats_device - Get HAL statistics.
808171095Ssam * @devh: HAL device handle.
809171095Ssam * @hw_info: Xframe statistic counters. See xge_hal_stats_hw_info_t.
810171095Ssam *           Returned by HAL.
811171095Ssam * @device_info: HAL statistics. See xge_hal_stats_device_info_t.
812171095Ssam *               Returned by HAL.
813171095Ssam *
814171095Ssam * Get device and HAL statistics. The latter is part of the in-host statistics
815171095Ssam * that HAL maintains for _that_ device.
816171095Ssam *
817171095Ssam * Returns: XGE_HAL_OK - success.
818171095Ssam * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
819171095Ssam * currently available.
820171095Ssam *
821171095Ssam * See also: xge_hal_status_e{}.
822171095Ssam */
823171095Ssamxge_hal_status_e
824171095Ssamxge_hal_stats_device(xge_hal_device_h devh,
825173139Srwatson	    xge_hal_stats_device_info_t **device_info)
826171095Ssam{
827171095Ssam	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
828171095Ssam
829171095Ssam	if (!hldev->stats.is_initialized ||
830171095Ssam	    !hldev->stats.is_enabled) {
831173139Srwatson	    *device_info = NULL;
832173139Srwatson	    return XGE_HAL_INF_STATS_IS_NOT_READY;
833171095Ssam	}
834171095Ssam
835171095Ssam	hldev->stats.sw_dev_info_stats.traffic_intr_cnt =
836173139Srwatson	    hldev->stats.sw_dev_info_stats.total_intr_cnt -
837173139Srwatson	        hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt;
838171095Ssam
839171095Ssam	*device_info = &hldev->stats.sw_dev_info_stats;
840171095Ssam
841171095Ssam	return XGE_HAL_OK;
842171095Ssam}
843171095Ssam
844171095Ssam/**
845171095Ssam * xge_hal_stats_channel - Get channel statistics.
846171095Ssam * @channelh: Channel handle.
847171095Ssam * @channel_info: HAL channel statistic counters.
848171095Ssam *                See xge_hal_stats_channel_info_t{}. Returned by HAL.
849171095Ssam *
850171095Ssam * Retrieve statistics of a particular HAL channel. This includes, for instance,
851171095Ssam * number of completions per interrupt, number of traffic interrupts, etc.
852171095Ssam *
853171095Ssam * Returns: XGE_HAL_OK - success.
854171095Ssam * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
855171095Ssam * currently available.
856171095Ssam *
857171095Ssam * See also: xge_hal_status_e{}.
858171095Ssam */
859171095Ssamxge_hal_status_e
860171095Ssamxge_hal_stats_channel(xge_hal_channel_h channelh,
861173139Srwatson	    xge_hal_stats_channel_info_t **channel_info)
862171095Ssam{
863173139Srwatson	xge_hal_stats_hw_info_t *latest;
864171095Ssam	xge_hal_channel_t *channel;
865171095Ssam	xge_hal_device_t *hldev;
866171095Ssam
867171095Ssam	channel = (xge_hal_channel_t *)channelh;
868173139Srwatson	if ((channel == NULL) || (channel->magic != XGE_HAL_MAGIC)) {
869173139Srwatson	    return XGE_HAL_ERR_INVALID_DEVICE;
870173139Srwatson	}
871171095Ssam	hldev = (xge_hal_device_t *)channel->devh;
872171095Ssam	if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) {
873173139Srwatson	    return XGE_HAL_ERR_INVALID_DEVICE;
874171095Ssam	}
875171095Ssam
876171095Ssam	if (!hldev->stats.is_initialized ||
877171095Ssam	    !hldev->stats.is_enabled ||
878171095Ssam	    !channel->is_open) {
879173139Srwatson	    *channel_info = NULL;
880173139Srwatson	    return XGE_HAL_INF_STATS_IS_NOT_READY;
881171095Ssam	}
882171095Ssam
883171095Ssam	hldev->stats.sw_dev_info_stats.traffic_intr_cnt =
884173139Srwatson	    hldev->stats.sw_dev_info_stats.total_intr_cnt -
885173139Srwatson	        hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt;
886171095Ssam
887171095Ssam	if (hldev->stats.sw_dev_info_stats.traffic_intr_cnt) {
888173139Srwatson	    int rxcnt = hldev->stats.sw_dev_info_stats.rx_traffic_intr_cnt;
889173139Srwatson	    int txcnt = hldev->stats.sw_dev_info_stats.tx_traffic_intr_cnt;
890173139Srwatson	    if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
891173139Srwatson	        if (!txcnt)
892173139Srwatson	            txcnt = 1;
893173139Srwatson	        channel->stats.avg_compl_per_intr_cnt =
894173139Srwatson	            channel->stats.total_compl_cnt / txcnt;
895173139Srwatson	    } else if (channel->type == XGE_HAL_CHANNEL_TYPE_RING &&
896173139Srwatson	           !hldev->config.bimodal_interrupts) {
897173139Srwatson	        if (!rxcnt)
898173139Srwatson	            rxcnt = 1;
899173139Srwatson	        channel->stats.avg_compl_per_intr_cnt =
900173139Srwatson	            channel->stats.total_compl_cnt / rxcnt;
901173139Srwatson	    }
902173139Srwatson	    if (channel->stats.avg_compl_per_intr_cnt == 0) {
903173139Srwatson	        /* to not confuse user */
904173139Srwatson	        channel->stats.avg_compl_per_intr_cnt = 1;
905173139Srwatson	    }
906171095Ssam	}
907171095Ssam
908171095Ssam	(void) xge_hal_stats_hw(hldev, &latest);
909171095Ssam
910171095Ssam	if (channel->stats.total_posts) {
911173139Srwatson	    channel->stats.avg_buffers_per_post =
912173139Srwatson	        channel->stats.total_buffers /
913173139Srwatson	            channel->stats.total_posts;
914171095Ssam#ifdef XGE_OS_PLATFORM_64BIT
915171095Ssam	        if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
916173139Srwatson	            channel->stats.avg_post_size =
917173139Srwatson	        (u32)(latest->tmac_ttl_less_fb_octets /
918173139Srwatson	            channel->stats.total_posts);
919171095Ssam	        }
920171095Ssam#endif
921171095Ssam	}
922171095Ssam
923171095Ssam#ifdef XGE_OS_PLATFORM_64BIT
924171095Ssam	if (channel->stats.total_buffers &&
925171095Ssam	    channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
926173139Srwatson	    channel->stats.avg_buffer_size =
927173139Srwatson	        (u32)(latest->tmac_ttl_less_fb_octets /
928173139Srwatson	            channel->stats.total_buffers);
929171095Ssam	}
930171095Ssam#endif
931171095Ssam
932171095Ssam	*channel_info = &channel->stats;
933171095Ssam	return XGE_HAL_OK;
934171095Ssam}
935171095Ssam
936171095Ssam/**
937171095Ssam * xge_hal_stats_reset - Reset (zero-out) device statistics
938171095Ssam * @devh: HAL device handle.
939171095Ssam *
940171095Ssam * Reset all device statistics.
941171095Ssam * Returns: XGE_HAL_OK - success.
942171095Ssam * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
943171095Ssam * currently available.
944171095Ssam *
945171095Ssam * See also: xge_hal_status_e{}, xge_hal_stats_channel_info_t{},
946171095Ssam * xge_hal_stats_sw_err_t{}, xge_hal_stats_device_info_t{}.
947171095Ssam */
948171095Ssamxge_hal_status_e
949171095Ssamxge_hal_stats_reset(xge_hal_device_h devh)
950171095Ssam{
951171095Ssam	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
952171095Ssam
953171095Ssam	if (!hldev->stats.is_initialized ||
954171095Ssam	    !hldev->stats.is_enabled) {
955173139Srwatson	    return XGE_HAL_INF_STATS_IS_NOT_READY;
956171095Ssam	}
957171095Ssam
958171095Ssam	/* save hw stats to calculate the after-reset values */
959171095Ssam	__hal_stats_save(&hldev->stats);
960171095Ssam
961171095Ssam	/* zero-out driver-maintained stats, don't reset the saved */
962173139Srwatson	    __hal_stats_soft_reset(hldev, 0);
963171095Ssam
964171095Ssam	return XGE_HAL_OK;
965171095Ssam}
966171095Ssam
967171095Ssam/*
968171095Ssam * __hal_stats_soft_reset - Reset software-maintained statistics.
969171095Ssam */
970171095Ssamvoid
971171095Ssam__hal_stats_soft_reset (xge_hal_device_h devh, int reset_all)
972171095Ssam{
973171095Ssam	xge_list_t *item;
974171095Ssam	xge_hal_channel_t *channel;
975171095Ssam	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
976171095Ssam
977173139Srwatson	    if (reset_all)  {
978173139Srwatson	    if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN) {
979173139Srwatson	        xge_os_memzero(&hldev->stats.hw_info_saved,
980173139Srwatson	                   sizeof(xge_hal_stats_hw_info_t));
981173139Srwatson	        xge_os_memzero(&hldev->stats.hw_info_latest,
982173139Srwatson	                   sizeof(xge_hal_stats_hw_info_t));
983173139Srwatson	    } else {
984173139Srwatson	        xge_os_memzero(&hldev->stats.pcim_info_saved,
985173139Srwatson	                   sizeof(xge_hal_stats_pcim_info_t));
986173139Srwatson	        xge_os_memzero(&hldev->stats.pcim_info_latest,
987173139Srwatson	                   sizeof(xge_hal_stats_pcim_info_t));
988173139Srwatson	    }
989173139Srwatson	    }
990171095Ssam
991171095Ssam	/* Reset the "soft" error and informational statistics */
992171095Ssam	xge_os_memzero(&hldev->stats.sw_dev_err_stats,
993171095Ssam	             sizeof(xge_hal_stats_sw_err_t));
994171095Ssam	xge_os_memzero(&hldev->stats.sw_dev_info_stats,
995171095Ssam	             sizeof(xge_hal_stats_device_info_t));
996171095Ssam
997171095Ssam	/* for each Rx channel */
998171095Ssam	xge_list_for_each(item, &hldev->ring_channels) {
999173139Srwatson	    channel = xge_container_of(item, xge_hal_channel_t, item);
1000173139Srwatson	    xge_os_memzero(&channel->stats,
1001173139Srwatson	                 sizeof(xge_hal_stats_channel_info_t));
1002171095Ssam	}
1003171095Ssam
1004171095Ssam	/* for each Tx channel */
1005171095Ssam	xge_list_for_each(item, &hldev->fifo_channels) {
1006173139Srwatson	    channel = xge_container_of(item, xge_hal_channel_t, item);
1007173139Srwatson	    xge_os_memzero(&channel->stats,
1008173139Srwatson	                 sizeof(xge_hal_stats_channel_info_t));
1009171095Ssam	}
1010171095Ssam}
1011171095Ssam
1012