xref: /freebsd/sys/dev/sfxge/common/siena_mac.c (revision 10b59a9b4add0320d52c15ce057dd697261e7dfc)
1 /*-
2  * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 #include "efsys.h"
26 #include "efx.h"
27 #include "efx_impl.h"
28 
29 #if EFSYS_OPT_SIENA
30 
31 	__checkReturn	int
32 siena_mac_poll(
33 	__in		efx_nic_t *enp,
34 	__out		efx_link_mode_t *link_modep)
35 {
36 	efx_port_t *epp = &(enp->en_port);
37 	siena_link_state_t sls;
38 	int rc;
39 
40 	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
41 		goto fail1;
42 
43 	epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
44 	epp->ep_fcntl = sls.sls_fcntl;
45 
46 	*link_modep = sls.sls_link_mode;
47 
48 	return (0);
49 
50 fail1:
51 	EFSYS_PROBE1(fail1, int, rc);
52 
53 	*link_modep = EFX_LINK_UNKNOWN;
54 
55 	return (rc);
56 }
57 
58 	__checkReturn	int
59 siena_mac_up(
60 	__in		efx_nic_t *enp,
61 	__out		boolean_t *mac_upp)
62 {
63 	siena_link_state_t sls;
64 	int rc;
65 
66 	/*
67 	 * Because Siena doesn't *require* polling, we can't rely on
68 	 * siena_mac_poll() being executed to populate epp->ep_mac_up.
69 	 */
70 	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
71 		goto fail1;
72 
73 	*mac_upp = sls.sls_mac_up;
74 
75 	return (0);
76 
77 fail1:
78 	EFSYS_PROBE1(fail1, int, rc);
79 
80 	return (rc);
81 }
82 
83 	__checkReturn	int
84 siena_mac_reconfigure(
85 	__in		efx_nic_t *enp)
86 {
87 	efx_port_t *epp = &(enp->en_port);
88 	uint8_t payload[MAX(MC_CMD_SET_MAC_IN_LEN,
89 			    MC_CMD_SET_MCAST_HASH_IN_LEN)];
90 	efx_mcdi_req_t req;
91 	unsigned int fcntl;
92 	int rc;
93 
94 	req.emr_cmd = MC_CMD_SET_MAC;
95 	req.emr_in_buf = payload;
96 	req.emr_in_length = MC_CMD_SET_MAC_IN_LEN;
97 	EFX_STATIC_ASSERT(MC_CMD_SET_MAC_OUT_LEN == 0);
98 	req.emr_out_buf = NULL;
99 	req.emr_out_length = 0;
100 
101 	MCDI_IN_SET_DWORD(req, SET_MAC_IN_MTU, epp->ep_mac_pdu);
102 	MCDI_IN_SET_DWORD(req, SET_MAC_IN_DRAIN, epp->ep_mac_drain ? 1 : 0);
103 	EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t, SET_MAC_IN_ADDR),
104 			    epp->ep_mac_addr);
105 	MCDI_IN_POPULATE_DWORD_2(req, SET_MAC_IN_REJECT,
106 				    SET_MAC_IN_REJECT_UNCST, !epp->ep_unicst,
107 				    SET_MAC_IN_REJECT_BRDCST, !epp->ep_brdcst);
108 
109 	if (epp->ep_fcntl_autoneg)
110 		/* efx_fcntl_set() has already set the phy capabilities */
111 		fcntl = MC_CMD_FCNTL_AUTO;
112 	else if (epp->ep_fcntl & EFX_FCNTL_RESPOND)
113 		fcntl = (epp->ep_fcntl & EFX_FCNTL_GENERATE)
114 			? MC_CMD_FCNTL_BIDIR
115 			: MC_CMD_FCNTL_RESPOND;
116 	else
117 		fcntl = MC_CMD_FCNTL_OFF;
118 
119 	MCDI_IN_SET_DWORD(req, SET_MAC_IN_FCNTL, fcntl);
120 
121 	efx_mcdi_execute(enp, &req);
122 
123 	if (req.emr_rc != 0) {
124 		rc = req.emr_rc;
125 		goto fail1;
126 	}
127 
128 	/* Push multicast hash. Set the broadcast bit (0xff) appropriately */
129 	req.emr_cmd = MC_CMD_SET_MCAST_HASH;
130 	req.emr_in_buf = payload;
131 	req.emr_in_length = MC_CMD_SET_MCAST_HASH_IN_LEN;
132 	EFX_STATIC_ASSERT(MC_CMD_SET_MCAST_HASH_OUT_LEN == 0);
133 	req.emr_out_buf = NULL;
134 	req.emr_out_length = 0;
135 
136 	memcpy(MCDI_IN2(req, uint8_t, SET_MCAST_HASH_IN_HASH0),
137 	    epp->ep_multicst_hash, sizeof (epp->ep_multicst_hash));
138 	if (epp->ep_brdcst)
139 		EFX_SET_OWORD_BIT(*MCDI_IN2(req, efx_oword_t,
140 		    SET_MCAST_HASH_IN_HASH1), 0x7f);
141 
142 	efx_mcdi_execute(enp, &req);
143 
144 	if (req.emr_rc != 0) {
145 		rc = req.emr_rc;
146 		goto fail2;
147 	}
148 
149 	return (0);
150 
151 fail2:
152 	EFSYS_PROBE(fail2);
153 fail1:
154 	EFSYS_PROBE1(fail1, int, rc);
155 
156 	return (rc);
157 }
158 
159 #if EFSYS_OPT_LOOPBACK
160 
161 	__checkReturn	int
162 siena_mac_loopback_set(
163 	__in		efx_nic_t *enp,
164 	__in		efx_link_mode_t link_mode,
165 	__in		efx_loopback_type_t loopback_type)
166 {
167 	efx_port_t *epp = &(enp->en_port);
168 	efx_phy_ops_t *epop = epp->ep_epop;
169 	efx_loopback_type_t old_loopback_type;
170 	efx_link_mode_t old_loopback_link_mode;
171 	int rc;
172 
173 	/* The PHY object handles this on Siena */
174 	old_loopback_type = epp->ep_loopback_type;
175 	old_loopback_link_mode = epp->ep_loopback_link_mode;
176 	epp->ep_loopback_type = loopback_type;
177 	epp->ep_loopback_link_mode = link_mode;
178 
179 	if ((rc = epop->epo_reconfigure(enp)) != 0)
180 		goto fail1;
181 
182 	return (0);
183 
184 fail1:
185 	EFSYS_PROBE(fail2);
186 
187 	epp->ep_loopback_type = old_loopback_type;
188 	epp->ep_loopback_link_mode = old_loopback_link_mode;
189 
190 	return (rc);
191 }
192 
193 #endif	/* EFSYS_OPT_LOOPBACK */
194 
195 #if EFSYS_OPT_MAC_STATS
196 
197 	__checkReturn			int
198 siena_mac_stats_clear(
199 	__in				efx_nic_t *enp)
200 {
201 	uint8_t payload[MC_CMD_MAC_STATS_IN_LEN];
202 	efx_mcdi_req_t req;
203 	int rc;
204 
205 	req.emr_cmd = MC_CMD_MAC_STATS;
206 	req.emr_in_buf = payload;
207 	req.emr_in_length = sizeof (payload);
208 	EFX_STATIC_ASSERT(MC_CMD_MAC_STATS_OUT_DMA_LEN == 0);
209 	req.emr_out_buf = NULL;
210 	req.emr_out_length = 0;
211 
212 	MCDI_IN_POPULATE_DWORD_3(req, MAC_STATS_IN_CMD,
213 				    MAC_STATS_IN_DMA, 0,
214 				    MAC_STATS_IN_CLEAR, 1,
215 				    MAC_STATS_IN_PERIODIC_CHANGE, 0);
216 
217 	efx_mcdi_execute(enp, &req);
218 
219 	if (req.emr_rc != 0) {
220 		rc = req.emr_rc;
221 		goto fail1;
222 	}
223 
224 	return (0);
225 
226 fail1:
227 	EFSYS_PROBE1(fail1, int, rc);
228 
229 	return (rc);
230 }
231 
232 	__checkReturn			int
233 siena_mac_stats_upload(
234 	__in				efx_nic_t *enp,
235 	__in				efsys_mem_t *esmp)
236 {
237 	uint8_t payload[MC_CMD_MAC_STATS_IN_LEN];
238 	efx_mcdi_req_t req;
239 	size_t bytes;
240 	int rc;
241 
242 	EFX_STATIC_ASSERT(MC_CMD_MAC_NSTATS * sizeof (uint64_t) <=
243 	    EFX_MAC_STATS_SIZE);
244 
245 	bytes = MC_CMD_MAC_NSTATS * sizeof (uint64_t);
246 
247 	req.emr_cmd = MC_CMD_MAC_STATS;
248 	req.emr_in_buf = payload;
249 	req.emr_in_length = sizeof (payload);
250 	EFX_STATIC_ASSERT(MC_CMD_MAC_STATS_OUT_DMA_LEN == 0);
251 	req.emr_out_buf = NULL;
252 	req.emr_out_length = 0;
253 
254 	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_ADDR_LO,
255 			    EFSYS_MEM_ADDR(esmp) & 0xffffffff);
256 	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_ADDR_HI,
257 			    EFSYS_MEM_ADDR(esmp) >> 32);
258 	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_LEN, bytes);
259 
260 	/*
261 	 * The MC DMAs aggregate statistics for our convinience, so we can
262 	 * avoid having to pull the statistics buffer into the cache to
263 	 * maintain cumulative statistics.
264 	 */
265 	MCDI_IN_POPULATE_DWORD_3(req, MAC_STATS_IN_CMD,
266 				    MAC_STATS_IN_DMA, 1,
267 				    MAC_STATS_IN_CLEAR, 0,
268 				    MAC_STATS_IN_PERIODIC_CHANGE, 0);
269 
270 	efx_mcdi_execute(enp, &req);
271 
272 	if (req.emr_rc != 0) {
273 		rc = req.emr_rc;
274 		goto fail1;
275 	}
276 
277 	return (0);
278 
279 fail1:
280 	EFSYS_PROBE1(fail1, int, rc);
281 
282 	return (rc);
283 }
284 
285 	__checkReturn			int
286 siena_mac_stats_periodic(
287 	__in				efx_nic_t *enp,
288 	__in				efsys_mem_t *esmp,
289 	__in				uint16_t period,
290 	__in				boolean_t events)
291 {
292 	uint8_t payload[MC_CMD_MAC_STATS_IN_LEN];
293 	efx_mcdi_req_t req;
294 	size_t bytes;
295 	int rc;
296 
297 	bytes = MC_CMD_MAC_NSTATS * sizeof (uint64_t);
298 
299 	req.emr_cmd = MC_CMD_MAC_STATS;
300 	req.emr_in_buf = payload;
301 	req.emr_in_length = sizeof (payload);
302 	EFX_STATIC_ASSERT(MC_CMD_MAC_STATS_OUT_DMA_LEN == 0);
303 	req.emr_out_buf = NULL;
304 	req.emr_out_length = 0;
305 
306 	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_ADDR_LO,
307 			    EFSYS_MEM_ADDR(esmp) & 0xffffffff);
308 	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_ADDR_HI,
309 			    EFSYS_MEM_ADDR(esmp) >> 32);
310 	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_LEN, bytes);
311 
312 	/*
313 	 * The MC DMAs aggregate statistics for our convinience, so we can
314 	 * avoid having to pull the statistics buffer into the cache to
315 	 * maintain cumulative statistics.
316 	 */
317 	MCDI_IN_POPULATE_DWORD_6(req, MAC_STATS_IN_CMD,
318 			    MAC_STATS_IN_DMA, 0,
319 			    MAC_STATS_IN_CLEAR, 0,
320 			    MAC_STATS_IN_PERIODIC_CHANGE, 1,
321 			    MAC_STATS_IN_PERIODIC_ENABLE, period ? 1 : 0,
322 			    MAC_STATS_IN_PERIODIC_NOEVENT, events ? 0 : 1,
323 			    MAC_STATS_IN_PERIOD_MS, period);
324 
325 	efx_mcdi_execute(enp, &req);
326 
327 	if (req.emr_rc != 0) {
328 		rc = req.emr_rc;
329 		goto fail1;
330 	}
331 
332 	return (0);
333 
334 fail1:
335 	EFSYS_PROBE1(fail1, int, rc);
336 
337 	return (rc);
338 }
339 
340 
341 #define	SIENA_MAC_STAT_READ(_esmp, _field, _eqp)			\
342 	EFSYS_MEM_READQ((_esmp), (_field) * sizeof (efx_qword_t), _eqp)
343 
344 	__checkReturn			int
345 siena_mac_stats_update(
346 	__in				efx_nic_t *enp,
347 	__in				efsys_mem_t *esmp,
348 	__out_ecount(EFX_MAC_NSTATS)	efsys_stat_t *stat,
349 	__out_opt			uint32_t *generationp)
350 {
351 	efx_qword_t rx_pkts;
352 	efx_qword_t value;
353 	efx_qword_t generation_start;
354 	efx_qword_t generation_end;
355 
356 	_NOTE(ARGUNUSED(enp))
357 
358 	/* Read END first so we don't race with the MC */
359 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_END,
360 			    &generation_end);
361 	EFSYS_MEM_READ_BARRIER();
362 
363 	/* TX */
364 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_PKTS, &value);
365 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_PKTS]), &value);
366 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_CONTROL_PKTS, &value);
367 	EFSYS_STAT_SUBR_QWORD(&(stat[EFX_MAC_TX_PKTS]), &value);
368 
369 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_PAUSE_PKTS, &value);
370 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_PAUSE_PKTS]), &value);
371 
372 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_UNICAST_PKTS, &value);
373 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_UNICST_PKTS]), &value);
374 
375 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_MULTICAST_PKTS, &value);
376 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_MULTICST_PKTS]), &value);
377 
378 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BROADCAST_PKTS, &value);
379 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_BRDCST_PKTS]), &value);
380 
381 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BYTES, &value);
382 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_OCTETS]), &value);
383 
384 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_LT64_PKTS, &value);
385 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LE_64_PKTS]), &value);
386 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_64_PKTS, &value);
387 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LE_64_PKTS]), &value);
388 
389 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_65_TO_127_PKTS, &value);
390 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_65_TO_127_PKTS]), &value);
391 
392 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_128_TO_255_PKTS, &value);
393 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_128_TO_255_PKTS]), &value);
394 
395 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_256_TO_511_PKTS, &value);
396 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_256_TO_511_PKTS]), &value);
397 
398 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_512_TO_1023_PKTS, &value);
399 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_512_TO_1023_PKTS]), &value);
400 
401 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_1024_TO_15XX_PKTS, &value);
402 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_1024_TO_15XX_PKTS]), &value);
403 
404 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_15XX_TO_JUMBO_PKTS, &value);
405 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_GE_15XX_PKTS]), &value);
406 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_GTJUMBO_PKTS, &value);
407 	EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_TX_GE_15XX_PKTS]), &value);
408 
409 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BAD_FCS_PKTS, &value);
410 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_ERRORS]), &value);
411 
412 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_SINGLE_COLLISION_PKTS, &value);
413 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_SGL_COL_PKTS]), &value);
414 
415 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_MULTIPLE_COLLISION_PKTS,
416 			    &value);
417 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_MULT_COL_PKTS]), &value);
418 
419 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_EXCESSIVE_COLLISION_PKTS,
420 			    &value);
421 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_EX_COL_PKTS]), &value);
422 
423 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_LATE_COLLISION_PKTS, &value);
424 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LATE_COL_PKTS]), &value);
425 
426 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_DEFERRED_PKTS, &value);
427 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_DEF_PKTS]), &value);
428 
429 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_EXCESSIVE_DEFERRED_PKTS,
430 	    &value);
431 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_EX_DEF_PKTS]), &value);
432 
433 	/* RX */
434 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BYTES, &rx_pkts);
435 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_OCTETS]), &rx_pkts);
436 
437 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_PKTS, &value);
438 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_PKTS]), &value);
439 
440 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_UNICAST_PKTS, &value);
441 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_UNICST_PKTS]), &value);
442 
443 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_MULTICAST_PKTS, &value);
444 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_MULTICST_PKTS]), &value);
445 
446 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BROADCAST_PKTS, &value);
447 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_BRDCST_PKTS]), &value);
448 
449 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_PAUSE_PKTS, &value);
450 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_PAUSE_PKTS]), &value);
451 
452 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_UNDERSIZE_PKTS, &value);
453 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_LE_64_PKTS]), &value);
454 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_64_PKTS, &value);
455 	EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_RX_LE_64_PKTS]), &value);
456 
457 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_65_TO_127_PKTS, &value);
458 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_65_TO_127_PKTS]), &value);
459 
460 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_128_TO_255_PKTS, &value);
461 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_128_TO_255_PKTS]), &value);
462 
463 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_256_TO_511_PKTS, &value);
464 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_256_TO_511_PKTS]), &value);
465 
466 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_512_TO_1023_PKTS, &value);
467 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_512_TO_1023_PKTS]), &value);
468 
469 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_1024_TO_15XX_PKTS, &value);
470 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_1024_TO_15XX_PKTS]), &value);
471 
472 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_15XX_TO_JUMBO_PKTS, &value);
473 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_GE_15XX_PKTS]), &value);
474 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_GTJUMBO_PKTS, &value);
475 	EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_RX_GE_15XX_PKTS]), &value);
476 
477 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BAD_FCS_PKTS, &value);
478 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_FCS_ERRORS]), &value);
479 
480 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_OVERFLOW_PKTS, &value);
481 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_DROP_EVENTS]), &value);
482 
483 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_FALSE_CARRIER_PKTS, &value);
484 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_FALSE_CARRIER_ERRORS]), &value);
485 
486 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_SYMBOL_ERROR_PKTS, &value);
487 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_SYMBOL_ERRORS]), &value);
488 
489 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_ALIGN_ERROR_PKTS, &value);
490 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_ALIGN_ERRORS]), &value);
491 
492 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_INTERNAL_ERROR_PKTS, &value);
493 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_INTERNAL_ERRORS]), &value);
494 
495 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_JABBER_PKTS, &value);
496 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_JABBER_PKTS]), &value);
497 
498 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES01_CHAR_ERR, &value);
499 	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE0_CHAR_ERR]),
500 			    &(value.eq_dword[0]));
501 	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE1_CHAR_ERR]),
502 			    &(value.eq_dword[1]));
503 
504 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES23_CHAR_ERR, &value);
505 	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE2_CHAR_ERR]),
506 			    &(value.eq_dword[0]));
507 	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE3_CHAR_ERR]),
508 			    &(value.eq_dword[1]));
509 
510 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES01_DISP_ERR, &value);
511 	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE0_DISP_ERR]),
512 			    &(value.eq_dword[0]));
513 	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE1_DISP_ERR]),
514 			    &(value.eq_dword[1]));
515 
516 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES23_DISP_ERR, &value);
517 	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE2_DISP_ERR]),
518 			    &(value.eq_dword[0]));
519 	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE3_DISP_ERR]),
520 			    &(value.eq_dword[1]));
521 
522 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_MATCH_FAULT, &value);
523 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_MATCH_FAULT]), &value);
524 
525 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_NODESC_DROPS, &value);
526 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_NODESC_DROP_CNT]), &value);
527 
528 	EFSYS_MEM_READ_BARRIER();
529 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_START,
530 			    &generation_start);
531 
532 	/* Check that we didn't read the stats in the middle of a DMA */
533 	if (memcmp(&generation_start, &generation_end,
534 	    sizeof (generation_start)))
535 		return (EAGAIN);
536 
537 	if (generationp)
538 		*generationp = EFX_QWORD_FIELD(generation_start, EFX_DWORD_0);
539 
540 	return (0);
541 }
542 
543 #endif	/* EFSYS_OPT_MAC_STATS */
544 
545 #endif	/* EFSYS_OPT_SIENA */
546