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