xref: /illumos-gate/usr/src/uts/common/io/xge/hal/xgehal/xgehal-stats.c (revision a23fd118e437af0a7877dd313db8fdaa3537c675)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  *  Copyright (c) 2002-2005 Neterion, Inc.
24  *  All right Reserved.
25  *
26  *  FileName :    xgehal-stats.c
27  *
28  *  Description:  statistics object implementation
29  *
30  *  Created:      2 June 2004
31  */
32 
33 #include "xgehal-stats.h"
34 #include "xgehal-device.h"
35 
36 /*
37  * __hal_stats_initialize
38  * @stats: xge_hal_stats_t structure that contains, in particular,
39  *         Xframe hw stat counters.
40  * @devh: HAL device handle.
41  *
42  * Initialize per-device statistics object.
43  * See also: xge_hal_stats_getinfo(), xge_hal_status_e{}.
44  */
45 xge_hal_status_e
46 __hal_stats_initialize (xge_hal_stats_t *stats, xge_hal_device_h devh)
47 {
48 	int dma_flags;
49 	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
50 
51 	xge_assert(!stats->is_initialized);
52 
53 	dma_flags = XGE_OS_DMA_CACHELINE_ALIGNED;
54 #ifdef XGE_HAL_DMA_STATS_CONSISTENT
55 	dma_flags |= XGE_OS_DMA_CONSISTENT;
56 #else
57 	dma_flags |= XGE_OS_DMA_STREAMING;
58 #endif
59 
60 	stats->hw_info = xge_os_dma_malloc(hldev->pdev,
61 					 sizeof(xge_hal_stats_hw_info_t),
62 					 dma_flags,
63 					 &stats->hw_info_dmah,
64 					 &stats->hw_info_dma_acch);
65 	if (stats->hw_info == NULL) {
66 		xge_debug_stats(XGE_ERR, "%s", "can not DMA alloc");
67 		return XGE_HAL_ERR_OUT_OF_MEMORY;
68 	}
69 	xge_os_memzero(stats->hw_info, sizeof(xge_hal_stats_hw_info_t));
70 	xge_os_memzero(&stats->hw_info_saved, sizeof(xge_hal_stats_hw_info_t));
71 	xge_os_memzero(&stats->hw_info_latest, sizeof(xge_hal_stats_hw_info_t));
72 
73 	stats->devh = devh;
74 
75 	stats->dma_addr = xge_os_dma_map(hldev->pdev,
76 	                               stats->hw_info_dmah,
77 				       stats->hw_info,
78 				       sizeof(xge_hal_stats_hw_info_t),
79 				       XGE_OS_DMA_DIR_FROMDEVICE,
80 				       XGE_OS_DMA_CACHELINE_ALIGNED |
81 #ifdef XGE_HAL_DMA_STATS_CONSISTENT
82 				       XGE_OS_DMA_CONSISTENT
83 #else
84 			               XGE_OS_DMA_STREAMING
85 #endif
86                                        );
87 	if (stats->dma_addr == XGE_OS_INVALID_DMA_ADDR) {
88 		xge_debug_stats(XGE_ERR, "can not map vaddr 0x%llx to DMA",
89 				 (unsigned long long)(ulong_t)stats->hw_info);
90 		xge_os_dma_free(hldev->pdev,
91 			      stats->hw_info,
92 			      sizeof(xge_hal_stats_hw_info_t),
93 			      &stats->hw_info_dma_acch,
94 			      &stats->hw_info_dmah);
95 		return XGE_HAL_ERR_OUT_OF_MAPPING;
96 	}
97 
98 	xge_os_memzero(&stats->sw_dev_info_stats,
99 		     sizeof(xge_hal_stats_device_info_t));
100 
101 	stats->is_initialized = 1;
102 
103 	return XGE_HAL_OK;
104 }
105 
106 static void
107 __hal_stats_save (xge_hal_stats_t *stats)
108 {
109 	xge_hal_stats_hw_info_t	*latest;
110 
111 	(void) xge_hal_stats_hw(stats->devh, &latest);
112 
113 	xge_os_memcpy(&stats->hw_info_saved, stats->hw_info,
114 		      sizeof(xge_hal_stats_hw_info_t));
115 }
116 
117 /*
118  * __hal_stats_disable
119  * @stats: xge_hal_stats_t structure that contains, in particular,
120  *         Xframe hw stat counters.
121  *
122  * Ask device to stop collecting stats.
123  * See also: xge_hal_stats_getinfo().
124  */
125 void
126 __hal_stats_disable (xge_hal_stats_t *stats)
127 {
128 	xge_hal_device_t *hldev;
129 	xge_hal_pci_bar0_t *bar0;
130 	u64 val64;
131 
132 	xge_assert(stats->hw_info);
133 
134 	hldev = (xge_hal_device_t*)stats->devh;
135 	xge_assert(hldev);
136 
137 	bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
138 
139 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
140 			&bar0->stat_cfg);
141 	val64 &= ~XGE_HAL_STAT_CFG_STAT_EN;
142 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
143 			&bar0->stat_cfg);
144 
145 	/* flush the write */
146 	(void)xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
147 			&bar0->stat_cfg);
148 
149 	xge_debug_stats(XGE_TRACE, "stats disabled at 0x%llx",
150 			 (unsigned long long)stats->dma_addr);
151 
152 	stats->is_enabled = 0;
153 }
154 
155 /*
156  * __hal_stats_terminate
157  * @stats: xge_hal_stats_t structure that contains, in particular,
158  *         Xframe hw stat counters.
159  * Terminate per-device statistics object.
160  */
161 void
162 __hal_stats_terminate (xge_hal_stats_t *stats)
163 {
164 	xge_hal_device_t *hldev;
165 
166 	xge_assert(stats->hw_info);
167 
168 	hldev = (xge_hal_device_t*)stats->devh;
169 	xge_assert(hldev);
170 
171 	xge_os_dma_unmap(hldev->pdev,
172 	               stats->hw_info_dmah,
173 		       stats->dma_addr,
174 		       sizeof(xge_hal_stats_hw_info_t),
175 		       XGE_OS_DMA_DIR_FROMDEVICE);
176 
177 	xge_os_dma_free(hldev->pdev,
178 		      stats->hw_info,
179 		      sizeof(xge_hal_stats_hw_info_t),
180 		      &stats->hw_info_dma_acch,
181 		      &stats->hw_info_dmah);
182 
183 	stats->is_initialized = 0;
184 	stats->is_enabled = 0;
185 }
186 
187 
188 
189 /*
190  * __hal_stats_enable
191  * @stats: xge_hal_stats_t structure that contains, in particular,
192  *         Xframe hw stat counters.
193  *
194  * Ask device to start collecting stats.
195  * See also: xge_hal_stats_getinfo().
196  */
197 void
198 __hal_stats_enable (xge_hal_stats_t *stats)
199 {
200 	xge_hal_device_t *hldev;
201 	xge_hal_pci_bar0_t *bar0;
202 	u64 val64;
203 	unsigned int refresh_time_pci_clocks;
204 
205 	xge_assert(stats->hw_info);
206 
207 	hldev = (xge_hal_device_t*)stats->devh;
208 	xge_assert(hldev);
209 
210 	bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
211 
212 	/* enable statistics */
213 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, stats->dma_addr,
214 			       &bar0->stat_addr);
215 
216         refresh_time_pci_clocks = XGE_HAL_XENA_PER_SEC *
217 	                          hldev->config.stats_refresh_time_sec;
218 	refresh_time_pci_clocks =
219 	        __hal_fix_time_ival_herc(hldev, refresh_time_pci_clocks);
220 
221 #ifdef XGE_HAL_HERC_EMULATION
222 	/*
223 	 * The clocks in the emulator are running ~1000 times slower than real world,
224 		* so the stats transfer will occur ~1000 times less frequent.
225 	 * STAT_CFG.STAT_TRSF_PERIOD should be set to 0x20C for Hercules emulation
226 		* (stats transferred every 0.5 sec).
227 	 */
228 
229 	val64 = (0x20C | XGE_HAL_STAT_CFG_STAT_RO | XGE_HAL_STAT_CFG_STAT_EN);
230 #else
231 	val64 = XGE_HAL_SET_UPDT_PERIOD(refresh_time_pci_clocks) |
232 			                XGE_HAL_STAT_CFG_STAT_RO |
233 					XGE_HAL_STAT_CFG_STAT_EN;
234 #endif
235 
236 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
237 	                       &bar0->stat_cfg);
238 
239 	xge_debug_stats(XGE_TRACE, "stats enabled at 0x%llx",
240 			 (unsigned long long)stats->dma_addr);
241 
242 	stats->is_enabled = 1;
243 }
244 
245 /*
246  * __hal_stats_update_latest - Update hw stats counters, based on the real
247  * hardware maintained counters and the stored "reset" values.
248  */
249 static void
250 __hal_stats_update_latest(xge_hal_device_h devh)
251 {
252 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
253 
254 #define set_latest_stat_cnt(_dev, _p)                                   \
255         hldev->stats.hw_info_latest._p =                                \
256 	((hldev->stats.hw_info->_p >= hldev->stats.hw_info_saved._p) ?  \
257           hldev->stats.hw_info->_p - hldev->stats.hw_info_saved._p :    \
258 	  ((-1) - hldev->stats.hw_info_saved._p) + hldev->stats.hw_info->_p)
259 
260 	/* Tx MAC statistics counters. */
261 	set_latest_stat_cnt(hldev, tmac_frms);
262 	set_latest_stat_cnt(hldev, tmac_data_octets);
263 	set_latest_stat_cnt(hldev, tmac_drop_frms);
264 	set_latest_stat_cnt(hldev, tmac_mcst_frms);
265 	set_latest_stat_cnt(hldev, tmac_bcst_frms);
266 	set_latest_stat_cnt(hldev, tmac_pause_ctrl_frms);
267 	set_latest_stat_cnt(hldev, tmac_ttl_octets);
268 	set_latest_stat_cnt(hldev, tmac_ucst_frms);
269 	set_latest_stat_cnt(hldev, tmac_nucst_frms);
270 	set_latest_stat_cnt(hldev, tmac_any_err_frms);
271 	set_latest_stat_cnt(hldev, tmac_ttl_less_fb_octets);
272 	set_latest_stat_cnt(hldev, tmac_vld_ip_octets);
273 	set_latest_stat_cnt(hldev, tmac_vld_ip);
274 	set_latest_stat_cnt(hldev, tmac_drop_ip);
275 	set_latest_stat_cnt(hldev, tmac_icmp);
276 	set_latest_stat_cnt(hldev, tmac_rst_tcp);
277 	set_latest_stat_cnt(hldev, tmac_tcp);
278 	set_latest_stat_cnt(hldev, tmac_udp);
279 	set_latest_stat_cnt(hldev, reserved_0);
280 
281 	/* Rx MAC Statistics counters. */
282 	set_latest_stat_cnt(hldev, rmac_vld_frms);
283 	set_latest_stat_cnt(hldev, rmac_data_octets);
284 	set_latest_stat_cnt(hldev, rmac_fcs_err_frms);
285 	set_latest_stat_cnt(hldev, rmac_drop_frms);
286 	set_latest_stat_cnt(hldev, rmac_vld_mcst_frms);
287 	set_latest_stat_cnt(hldev, rmac_vld_bcst_frms);
288 	set_latest_stat_cnt(hldev, rmac_in_rng_len_err_frms);
289 	set_latest_stat_cnt(hldev, rmac_out_rng_len_err_frms);
290 	set_latest_stat_cnt(hldev, rmac_long_frms);
291 	set_latest_stat_cnt(hldev, rmac_pause_ctrl_frms);
292 	set_latest_stat_cnt(hldev, rmac_unsup_ctrl_frms);
293 	set_latest_stat_cnt(hldev, rmac_ttl_octets);
294 	set_latest_stat_cnt(hldev, rmac_accepted_ucst_frms);
295 	set_latest_stat_cnt(hldev, rmac_accepted_nucst_frms);
296 	set_latest_stat_cnt(hldev, rmac_discarded_frms);
297 	set_latest_stat_cnt(hldev, rmac_drop_events);
298 	set_latest_stat_cnt(hldev, reserved_1);
299 	set_latest_stat_cnt(hldev, rmac_ttl_less_fb_octets);
300 	set_latest_stat_cnt(hldev, rmac_ttl_frms);
301 	set_latest_stat_cnt(hldev, reserved_2);
302 	set_latest_stat_cnt(hldev, reserved_3);
303 	set_latest_stat_cnt(hldev, rmac_usized_frms);
304 	set_latest_stat_cnt(hldev, rmac_osized_frms);
305 	set_latest_stat_cnt(hldev, rmac_frag_frms);
306 	set_latest_stat_cnt(hldev, rmac_jabber_frms);
307 	set_latest_stat_cnt(hldev, reserved_4);
308 	set_latest_stat_cnt(hldev, rmac_ttl_64_frms);
309 	set_latest_stat_cnt(hldev, rmac_ttl_65_127_frms);
310 	set_latest_stat_cnt(hldev, reserved_5);
311 	set_latest_stat_cnt(hldev, rmac_ttl_128_255_frms);
312 	set_latest_stat_cnt(hldev, rmac_ttl_256_511_frms);
313 	set_latest_stat_cnt(hldev, reserved_6);
314 	set_latest_stat_cnt(hldev, rmac_ttl_512_1023_frms);
315 	set_latest_stat_cnt(hldev, rmac_ttl_1024_1518_frms);
316 	set_latest_stat_cnt(hldev, reserved_7);
317 	set_latest_stat_cnt(hldev, rmac_ip);
318 	set_latest_stat_cnt(hldev, rmac_ip_octets);
319 	set_latest_stat_cnt(hldev, rmac_hdr_err_ip);
320 	set_latest_stat_cnt(hldev, rmac_drop_ip);
321 	set_latest_stat_cnt(hldev, rmac_icmp);
322 	set_latest_stat_cnt(hldev, reserved_8);
323 	set_latest_stat_cnt(hldev, rmac_tcp);
324 	set_latest_stat_cnt(hldev, rmac_udp);
325 	set_latest_stat_cnt(hldev, rmac_err_drp_udp);
326 	set_latest_stat_cnt(hldev, rmac_xgmii_err_sym);
327 	set_latest_stat_cnt(hldev, rmac_frms_q0);
328 	set_latest_stat_cnt(hldev, rmac_frms_q1);
329 	set_latest_stat_cnt(hldev, rmac_frms_q2);
330 	set_latest_stat_cnt(hldev, rmac_frms_q3);
331 	set_latest_stat_cnt(hldev, rmac_frms_q4);
332 	set_latest_stat_cnt(hldev, rmac_frms_q5);
333 	set_latest_stat_cnt(hldev, rmac_frms_q6);
334 	set_latest_stat_cnt(hldev, rmac_frms_q7);
335 	set_latest_stat_cnt(hldev, rmac_full_q0);
336 	set_latest_stat_cnt(hldev, rmac_full_q1);
337 	set_latest_stat_cnt(hldev, rmac_full_q2);
338 	set_latest_stat_cnt(hldev, rmac_full_q3);
339 	set_latest_stat_cnt(hldev, rmac_full_q4);
340 	set_latest_stat_cnt(hldev, rmac_full_q5);
341 	set_latest_stat_cnt(hldev, rmac_full_q6);
342 	set_latest_stat_cnt(hldev, rmac_full_q7);
343 	set_latest_stat_cnt(hldev, rmac_pause_cnt);
344 	set_latest_stat_cnt(hldev, reserved_9);
345 	set_latest_stat_cnt(hldev, rmac_xgmii_data_err_cnt);
346 	set_latest_stat_cnt(hldev, rmac_xgmii_ctrl_err_cnt);
347 	set_latest_stat_cnt(hldev, rmac_accepted_ip);
348 	set_latest_stat_cnt(hldev, rmac_err_tcp);
349 
350 	/* PCI/PCI-X Read transaction statistics. */
351 	set_latest_stat_cnt(hldev, rd_req_cnt);
352 	set_latest_stat_cnt(hldev, new_rd_req_cnt);
353 	set_latest_stat_cnt(hldev, new_rd_req_rtry_cnt);
354 	set_latest_stat_cnt(hldev, rd_rtry_cnt);
355 	set_latest_stat_cnt(hldev, wr_rtry_rd_ack_cnt);
356 
357 	/* PCI/PCI-X write transaction statistics. */
358 	set_latest_stat_cnt(hldev, wr_req_cnt);
359 	set_latest_stat_cnt(hldev, new_wr_req_cnt);
360 	set_latest_stat_cnt(hldev, new_wr_req_rtry_cnt);
361 	set_latest_stat_cnt(hldev, wr_rtry_cnt);
362 	set_latest_stat_cnt(hldev, wr_disc_cnt);
363 	set_latest_stat_cnt(hldev, rd_rtry_wr_ack_cnt);
364 
365 	/* DMA Transaction statistics. */
366 	set_latest_stat_cnt(hldev, txp_wr_cnt);
367 	set_latest_stat_cnt(hldev, txd_rd_cnt);
368 	set_latest_stat_cnt(hldev, txd_wr_cnt);
369 	set_latest_stat_cnt(hldev, rxd_rd_cnt);
370 	set_latest_stat_cnt(hldev, rxd_wr_cnt);
371 	set_latest_stat_cnt(hldev, txf_rd_cnt);
372 	set_latest_stat_cnt(hldev, rxf_wr_cnt);
373 
374 	/* Enhanced Herc statistics */
375 	set_latest_stat_cnt(hldev, tmac_frms_oflow);
376 	set_latest_stat_cnt(hldev, tmac_data_octets_oflow);
377 	set_latest_stat_cnt(hldev, tmac_mcst_frms_oflow);
378 	set_latest_stat_cnt(hldev, tmac_bcst_frms_oflow);
379 	set_latest_stat_cnt(hldev, tmac_ttl_octets_oflow);
380 	set_latest_stat_cnt(hldev, tmac_ucst_frms_oflow);
381 	set_latest_stat_cnt(hldev, tmac_nucst_frms_oflow);
382 	set_latest_stat_cnt(hldev, tmac_any_err_frms_oflow);
383 	set_latest_stat_cnt(hldev, tmac_vlan_frms);
384 	set_latest_stat_cnt(hldev, tmac_vld_ip_oflow);
385 	set_latest_stat_cnt(hldev, tmac_drop_ip_oflow);
386 	set_latest_stat_cnt(hldev, tmac_icmp_oflow);
387 	set_latest_stat_cnt(hldev, tmac_rst_tcp_oflow);
388 	set_latest_stat_cnt(hldev, tmac_udp_oflow);
389 	set_latest_stat_cnt(hldev, tpa_unknown_protocol);
390 	set_latest_stat_cnt(hldev, tpa_parse_failure);
391 	set_latest_stat_cnt(hldev, rmac_vld_frms_oflow);
392 	set_latest_stat_cnt(hldev, rmac_data_octets_oflow);
393 	set_latest_stat_cnt(hldev, rmac_vld_mcst_frms_oflow);
394 	set_latest_stat_cnt(hldev, rmac_vld_bcst_frms_oflow);
395 	set_latest_stat_cnt(hldev, rmac_ttl_octets_oflow);
396 	set_latest_stat_cnt(hldev, rmac_accepted_ucst_frms_oflow);
397 	set_latest_stat_cnt(hldev, rmac_accepted_nucst_frms_oflow);
398 	set_latest_stat_cnt(hldev, rmac_discarded_frms_oflow);
399 	set_latest_stat_cnt(hldev, rmac_drop_events_oflow);
400 	set_latest_stat_cnt(hldev, rmac_usized_frms_oflow);
401 	set_latest_stat_cnt(hldev, rmac_osized_frms_oflow);
402 	set_latest_stat_cnt(hldev, rmac_frag_frms_oflow);
403 	set_latest_stat_cnt(hldev, rmac_jabber_frms_oflow);
404 	set_latest_stat_cnt(hldev, rmac_ip_oflow);
405 	set_latest_stat_cnt(hldev, rmac_drop_ip_oflow);
406 	set_latest_stat_cnt(hldev, rmac_icmp_oflow);
407 	set_latest_stat_cnt(hldev, rmac_udp_oflow);
408 	set_latest_stat_cnt(hldev, rmac_err_drp_udp_oflow);
409 	set_latest_stat_cnt(hldev, rmac_pause_cnt_oflow);
410 	set_latest_stat_cnt(hldev, rmac_ttl_1519_4095_frms);
411 	set_latest_stat_cnt(hldev, rmac_ttl_4096_8191_frms);
412 	set_latest_stat_cnt(hldev, rmac_ttl_8192_max_frms);
413 	set_latest_stat_cnt(hldev, rmac_ttl_gt_max_frms);
414 	set_latest_stat_cnt(hldev, rmac_osized_alt_frms);
415 	set_latest_stat_cnt(hldev, rmac_jabber_alt_frms);
416 	set_latest_stat_cnt(hldev, rmac_gt_max_alt_frms);
417 	set_latest_stat_cnt(hldev, rmac_vlan_frms);
418 	set_latest_stat_cnt(hldev, rmac_fcs_discard);
419 	set_latest_stat_cnt(hldev, rmac_len_discard);
420 	set_latest_stat_cnt(hldev, rmac_da_discard);
421 	set_latest_stat_cnt(hldev, rmac_pf_discard);
422 	set_latest_stat_cnt(hldev, rmac_rts_discard);
423 	set_latest_stat_cnt(hldev, rmac_red_discard);
424 	set_latest_stat_cnt(hldev, rmac_ingm_full_discard);
425 	set_latest_stat_cnt(hldev, rmac_accepted_ip_oflow);
426 	set_latest_stat_cnt(hldev, link_fault_cnt);
427 }
428 
429 /**
430  * xge_hal_stats_hw - Get HW device statistics.
431  * @devh: HAL device handle.
432  * @hw_info: Xframe statistic counters. See xge_hal_stats_hw_info_t.
433  *           Returned by HAL.
434  *
435  * Get device and HAL statistics. The latter is part of the in-host statistics
436  * that HAL maintains for _that_ device.
437  *
438  * Returns: XGE_HAL_OK - success.
439  * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
440  * currently available.
441  *
442  * See also: xge_hal_status_e{}.
443  */
444 xge_hal_status_e
445 xge_hal_stats_hw(xge_hal_device_h devh, xge_hal_stats_hw_info_t **hw_info)
446 {
447 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
448 
449 	if (!hldev->stats.is_initialized ||
450 	    !hldev->stats.is_enabled) {
451 		*hw_info = NULL;
452 		return XGE_HAL_INF_STATS_IS_NOT_READY;
453 	}
454 
455 #if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_STATS_STREAMING)
456 	xge_os_dma_sync(hldev->pdev,
457 	              hldev->stats.hw_info_dmah,
458 		      hldev->stats.dma_addr,
459 		      0,
460 		      sizeof(xge_hal_stats_hw_info_t),
461 		      XGE_OS_DMA_DIR_FROMDEVICE);
462 #endif
463 
464         /*
465 	 * update hw counters, taking into account
466 	 * the "reset" or "saved"
467 	 * values
468 	 */
469 	__hal_stats_update_latest(devh);
470 
471 	*hw_info = &hldev->stats.hw_info_latest;
472 
473 	return XGE_HAL_OK;
474 }
475 
476 /**
477  * xge_hal_stats_device - Get HAL statistics.
478  * @devh: HAL device handle.
479  * @hw_info: Xframe statistic counters. See xge_hal_stats_hw_info_t.
480  *           Returned by HAL.
481  * @device_info: HAL statistics. See xge_hal_stats_device_info_t.
482  *               Returned by HAL.
483  *
484  * Get device and HAL statistics. The latter is part of the in-host statistics
485  * that HAL maintains for _that_ device.
486  *
487  * Returns: XGE_HAL_OK - success.
488  * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
489  * currently available.
490  *
491  * See also: xge_hal_status_e{}.
492  */
493 xge_hal_status_e
494 xge_hal_stats_device(xge_hal_device_h devh,
495 		xge_hal_stats_device_info_t **device_info)
496 {
497 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
498 
499 	if (!hldev->stats.is_initialized ||
500 	    !hldev->stats.is_enabled) {
501 		*device_info = NULL;
502 		return XGE_HAL_INF_STATS_IS_NOT_READY;
503 	}
504 
505 	hldev->stats.sw_dev_info_stats.traffic_intr_cnt =
506 		hldev->stats.sw_dev_info_stats.total_intr_cnt -
507 			hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt;
508 
509 	*device_info = &hldev->stats.sw_dev_info_stats;
510 
511 	return XGE_HAL_OK;
512 }
513 
514 /**
515  * xge_hal_stats_channel - Get channel statistics.
516  * @channelh: Channel handle.
517  * @channel_info: HAL channel statistic counters.
518  *                See xge_hal_stats_channel_info_t{}. Returned by HAL.
519  *
520  * Retrieve statistics of a particular HAL channel. This includes, for instance,
521  * number of completions per interrupt, number of traffic interrupts, etc.
522  *
523  * Returns: XGE_HAL_OK - success.
524  * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
525  * currently available.
526  *
527  * See also: xge_hal_status_e{}.
528  */
529 xge_hal_status_e
530 xge_hal_stats_channel(xge_hal_channel_h channelh,
531 		xge_hal_stats_channel_info_t **channel_info)
532 {
533 	xge_hal_stats_hw_info_t	*latest;
534 	xge_hal_channel_t *channel;
535 	xge_hal_device_t *hldev;
536 
537 	channel = (xge_hal_channel_t *)channelh;
538 	hldev = (xge_hal_device_t *)channel->devh;
539 	if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) {
540 		return XGE_HAL_ERR_INVALID_DEVICE;
541 	}
542 	if ((channel == NULL) || (channel->magic != XGE_HAL_MAGIC)) {
543 		return XGE_HAL_ERR_INVALID_DEVICE;
544 	}
545 
546 	if (!hldev->stats.is_initialized ||
547 	    !hldev->stats.is_enabled ||
548 	    !channel->is_open) {
549 		*channel_info = NULL;
550 		return XGE_HAL_INF_STATS_IS_NOT_READY;
551 	}
552 
553 	hldev->stats.sw_dev_info_stats.traffic_intr_cnt =
554 		hldev->stats.sw_dev_info_stats.total_intr_cnt -
555 			hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt;
556 
557 	if (hldev->stats.sw_dev_info_stats.traffic_intr_cnt) {
558 		channel->stats.avg_compl_per_intr_cnt =
559 			channel->stats.total_compl_cnt /
560 				hldev->stats.sw_dev_info_stats.traffic_intr_cnt;
561 		if (channel->stats.avg_compl_per_intr_cnt == 0) {
562 			/* to not confuse user */
563 			channel->stats.avg_compl_per_intr_cnt = 1;
564 		}
565 	}
566 
567 	(void) xge_hal_stats_hw(hldev, &latest);
568 
569 	if (channel->stats.total_posts) {
570 		channel->stats.avg_buffers_per_post =
571 			channel->stats.total_buffers /
572 				channel->stats.total_posts;
573 #ifdef XGE_OS_PLATFORM_64BIT
574 	        if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
575 		        channel->stats.avg_post_size =
576 			(u32)(latest->tmac_ttl_less_fb_octets /
577 				channel->stats.total_posts);
578 	        }
579 #endif
580 	}
581 
582 #ifdef XGE_OS_PLATFORM_64BIT
583 	if (channel->stats.total_buffers &&
584 	    channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
585 		channel->stats.avg_buffer_size =
586 			(u32)(latest->tmac_ttl_less_fb_octets /
587 				channel->stats.total_buffers);
588 	}
589 #endif
590 
591 	*channel_info = &channel->stats;
592 	return XGE_HAL_OK;
593 }
594 
595 /**
596  * xge_hal_stats_reset - Reset (zero-out) device statistics
597  * @devh: HAL device handle.
598  *
599  * Reset all device statistics.
600  * Returns: XGE_HAL_OK - success.
601  * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
602  * currently available.
603  *
604  * See also: xge_hal_status_e{}, xge_hal_stats_channel_info_t{},
605  * xge_hal_stats_sw_err_t{}, xge_hal_stats_device_info_t{}.
606  */
607 xge_hal_status_e
608 xge_hal_stats_reset(xge_hal_device_h devh)
609 {
610 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
611 
612 	if (!hldev->stats.is_initialized ||
613 	    !hldev->stats.is_enabled) {
614 		return XGE_HAL_INF_STATS_IS_NOT_READY;
615 	}
616 
617 	/* save hw stats to calculate the after-reset values */
618 	__hal_stats_save(&hldev->stats);
619 
620 	/* zero-out driver-maintained stats, don't reset the saved */
621         __hal_stats_soft_reset(hldev, 0);
622 
623 	return XGE_HAL_OK;
624 }
625 
626 /*
627  * __hal_stats_soft_reset - Reset software-maintained statistics.
628  */
629 void
630 __hal_stats_soft_reset (xge_hal_device_h devh, int reset_all)
631 {
632 	xge_list_t *item;
633 	xge_hal_channel_t *channel;
634 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
635 
636         if (reset_all)  {
637 	        xge_os_memzero(&hldev->stats.hw_info_saved,
638 		               sizeof(xge_hal_stats_hw_info_t));
639 	        xge_os_memzero(&hldev->stats.hw_info_latest,
640 		               sizeof(xge_hal_stats_hw_info_t));
641         }
642 
643 	/* Reset the "soft" error and informational statistics */
644 	xge_os_memzero(&hldev->stats.sw_dev_err_stats,
645 	             sizeof(xge_hal_stats_sw_err_t));
646 	xge_os_memzero(&hldev->stats.sw_dev_info_stats,
647 	             sizeof(xge_hal_stats_device_info_t));
648 
649 	/* for each Rx channel */
650 	xge_list_for_each(item, &hldev->ring_channels) {
651 		channel = xge_container_of(item, xge_hal_channel_t, item);
652 		xge_os_memzero(&channel->stats,
653 		             sizeof(xge_hal_stats_channel_info_t));
654 	}
655 
656 	/* for each Tx channel */
657 	xge_list_for_each(item, &hldev->fifo_channels) {
658 		channel = xge_container_of(item, xge_hal_channel_t, item);
659 		xge_os_memzero(&channel->stats,
660 		             sizeof(xge_hal_stats_channel_info_t));
661 	}
662 }
663 
664