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