1 /*
2  * Copyright (c) 2009-2015 Solarflare Communications 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 are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * The views and conclusions contained in the software and documentation are
27  * those of the authors and should not be interpreted as representing official
28  * policies, either expressed or implied, of the FreeBSD Project.
29  */
30 
31 #include "efx.h"
32 #include "efx_impl.h"
33 
34 #if EFSYS_OPT_SIENA
35 
36 	__checkReturn	efx_rc_t
siena_mac_poll(__in efx_nic_t * enp,__out efx_link_mode_t * link_modep)37 siena_mac_poll(
38 	__in		efx_nic_t *enp,
39 	__out		efx_link_mode_t *link_modep)
40 {
41 	efx_port_t *epp = &(enp->en_port);
42 	siena_link_state_t sls;
43 	efx_rc_t rc;
44 
45 	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
46 		goto fail1;
47 
48 	epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
49 	epp->ep_fcntl = sls.sls_fcntl;
50 
51 	*link_modep = sls.sls_link_mode;
52 
53 	return (0);
54 
55 fail1:
56 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
57 
58 	*link_modep = EFX_LINK_UNKNOWN;
59 
60 	return (rc);
61 }
62 
63 	__checkReturn	efx_rc_t
siena_mac_up(__in efx_nic_t * enp,__out boolean_t * mac_upp)64 siena_mac_up(
65 	__in		efx_nic_t *enp,
66 	__out		boolean_t *mac_upp)
67 {
68 	siena_link_state_t sls;
69 	efx_rc_t rc;
70 
71 	/*
72 	 * Because Siena doesn't *require* polling, we can't rely on
73 	 * siena_mac_poll() being executed to populate epp->ep_mac_up.
74 	 */
75 	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
76 		goto fail1;
77 
78 	*mac_upp = sls.sls_mac_up;
79 
80 	return (0);
81 
82 fail1:
83 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
84 
85 	return (rc);
86 }
87 
88 	__checkReturn	efx_rc_t
siena_mac_reconfigure(__in efx_nic_t * enp)89 siena_mac_reconfigure(
90 	__in		efx_nic_t *enp)
91 {
92 	efx_port_t *epp = &(enp->en_port);
93 	efx_oword_t multicast_hash[2];
94 	efx_mcdi_req_t req;
95 	uint8_t payload[MAX(MAX(MC_CMD_SET_MAC_IN_LEN,
96 				MC_CMD_SET_MAC_OUT_LEN),
97 			    MAX(MC_CMD_SET_MCAST_HASH_IN_LEN,
98 				MC_CMD_SET_MCAST_HASH_OUT_LEN))];
99 	unsigned int fcntl;
100 	efx_rc_t rc;
101 
102 	(void) memset(payload, 0, sizeof (payload));
103 	req.emr_cmd = MC_CMD_SET_MAC;
104 	req.emr_in_buf = payload;
105 	req.emr_in_length = MC_CMD_SET_MAC_IN_LEN;
106 	req.emr_out_buf = payload;
107 	req.emr_out_length = MC_CMD_SET_MAC_OUT_LEN;
108 
109 	MCDI_IN_SET_DWORD(req, SET_MAC_IN_MTU, epp->ep_mac_pdu);
110 	MCDI_IN_SET_DWORD(req, SET_MAC_IN_DRAIN, epp->ep_mac_drain ? 1 : 0);
111 	EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t, SET_MAC_IN_ADDR),
112 			    epp->ep_mac_addr);
113 	MCDI_IN_POPULATE_DWORD_2(req, SET_MAC_IN_REJECT,
114 			    SET_MAC_IN_REJECT_UNCST, !epp->ep_all_unicst,
115 			    SET_MAC_IN_REJECT_BRDCST, !epp->ep_brdcst);
116 
117 	if (epp->ep_fcntl_autoneg)
118 		/* efx_fcntl_set() has already set the phy capabilities */
119 		fcntl = MC_CMD_FCNTL_AUTO;
120 	else if (epp->ep_fcntl & EFX_FCNTL_RESPOND)
121 		fcntl = (epp->ep_fcntl & EFX_FCNTL_GENERATE)
122 			? MC_CMD_FCNTL_BIDIR
123 			: MC_CMD_FCNTL_RESPOND;
124 	else
125 		fcntl = MC_CMD_FCNTL_OFF;
126 
127 	MCDI_IN_SET_DWORD(req, SET_MAC_IN_FCNTL, fcntl);
128 
129 	efx_mcdi_execute(enp, &req);
130 
131 	if (req.emr_rc != 0) {
132 		rc = req.emr_rc;
133 		goto fail1;
134 	}
135 
136 	/* Push multicast hash */
137 
138 	if (epp->ep_all_mulcst) {
139 		/* A hash matching all multicast is all 1s */
140 		EFX_SET_OWORD(multicast_hash[0]);
141 		EFX_SET_OWORD(multicast_hash[1]);
142 	} else if (epp->ep_mulcst) {
143 		/* Use the hash set by the multicast list */
144 		multicast_hash[0] = epp->ep_multicst_hash[0];
145 		multicast_hash[1] = epp->ep_multicst_hash[1];
146 	} else {
147 		/* A hash matching no traffic is simply 0 */
148 		EFX_ZERO_OWORD(multicast_hash[0]);
149 		EFX_ZERO_OWORD(multicast_hash[1]);
150 	}
151 
152 	/*
153 	 * Broadcast packets go through the multicast hash filter.
154 	 * The IEEE 802.3 CRC32 of the broadcast address is 0xbe2612ff
155 	 * so we always add bit 0xff to the mask (bit 0x7f in the
156 	 * second octword).
157 	 */
158 	if (epp->ep_brdcst) {
159 		/*
160 		 * NB: due to constant folding, some of this evaluates
161 		 * to null expressions, giving E_EXPR_NULL_EFFECT during
162 		 * lint.  No good way to fix this without explicit coding
163 		 * the individual word/bit setting. So just suppress lint
164 		 * for this one line.
165 		 */
166 		/* LINTED */
167 		EFX_SET_OWORD_BIT(multicast_hash[1], 0x7f);
168 	}
169 
170 	(void) memset(payload, 0, sizeof (payload));
171 	req.emr_cmd = MC_CMD_SET_MCAST_HASH;
172 	req.emr_in_buf = payload;
173 	req.emr_in_length = MC_CMD_SET_MCAST_HASH_IN_LEN;
174 	req.emr_out_buf = payload;
175 	req.emr_out_length = MC_CMD_SET_MCAST_HASH_OUT_LEN;
176 
177 	(void) memcpy(MCDI_IN2(req, uint8_t, SET_MCAST_HASH_IN_HASH0),
178 	    multicast_hash, sizeof (multicast_hash));
179 
180 	efx_mcdi_execute(enp, &req);
181 
182 	if (req.emr_rc != 0) {
183 		rc = req.emr_rc;
184 		goto fail2;
185 	}
186 
187 	return (0);
188 
189 fail2:
190 	EFSYS_PROBE(fail2);
191 fail1:
192 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
193 
194 	return (rc);
195 }
196 
197 #if EFSYS_OPT_LOOPBACK
198 
199 	__checkReturn	efx_rc_t
siena_mac_loopback_set(__in efx_nic_t * enp,__in efx_link_mode_t link_mode,__in efx_loopback_type_t loopback_type)200 siena_mac_loopback_set(
201 	__in		efx_nic_t *enp,
202 	__in		efx_link_mode_t link_mode,
203 	__in		efx_loopback_type_t loopback_type)
204 {
205 	efx_port_t *epp = &(enp->en_port);
206 	const efx_phy_ops_t *epop = epp->ep_epop;
207 	efx_loopback_type_t old_loopback_type;
208 	efx_link_mode_t old_loopback_link_mode;
209 	efx_rc_t rc;
210 
211 	/* The PHY object handles this on Siena */
212 	old_loopback_type = epp->ep_loopback_type;
213 	old_loopback_link_mode = epp->ep_loopback_link_mode;
214 	epp->ep_loopback_type = loopback_type;
215 	epp->ep_loopback_link_mode = link_mode;
216 
217 	if ((rc = epop->epo_reconfigure(enp)) != 0)
218 		goto fail1;
219 
220 	return (0);
221 
222 fail1:
223 	EFSYS_PROBE(fail2);
224 
225 	epp->ep_loopback_type = old_loopback_type;
226 	epp->ep_loopback_link_mode = old_loopback_link_mode;
227 
228 	return (rc);
229 }
230 
231 #endif	/* EFSYS_OPT_LOOPBACK */
232 
233 #if EFSYS_OPT_MAC_STATS
234 
235 #define	SIENA_MAC_STAT_READ(_esmp, _field, _eqp)			\
236 	EFSYS_MEM_READQ((_esmp), (_field) * sizeof (efx_qword_t), _eqp)
237 
238 	__checkReturn			efx_rc_t
siena_mac_stats_update(__in efx_nic_t * enp,__in efsys_mem_t * esmp,__inout_ecount (EFX_MAC_NSTATS)efsys_stat_t * stat,__inout_opt uint32_t * generationp)239 siena_mac_stats_update(
240 	__in				efx_nic_t *enp,
241 	__in				efsys_mem_t *esmp,
242 	__inout_ecount(EFX_MAC_NSTATS)	efsys_stat_t *stat,
243 	__inout_opt			uint32_t *generationp)
244 {
245 	efx_qword_t value;
246 	efx_qword_t generation_start;
247 	efx_qword_t generation_end;
248 
249 	_NOTE(ARGUNUSED(enp))
250 
251 	/* Read END first so we don't race with the MC */
252 	EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, EFX_MAC_STATS_SIZE);
253 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_END,
254 			    &generation_end);
255 	EFSYS_MEM_READ_BARRIER();
256 
257 	/* TX */
258 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_PKTS, &value);
259 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_PKTS]), &value);
260 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_CONTROL_PKTS, &value);
261 	EFSYS_STAT_SUBR_QWORD(&(stat[EFX_MAC_TX_PKTS]), &value);
262 
263 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_PAUSE_PKTS, &value);
264 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_PAUSE_PKTS]), &value);
265 
266 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_UNICAST_PKTS, &value);
267 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_UNICST_PKTS]), &value);
268 
269 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_MULTICAST_PKTS, &value);
270 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_MULTICST_PKTS]), &value);
271 
272 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BROADCAST_PKTS, &value);
273 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_BRDCST_PKTS]), &value);
274 
275 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BYTES, &value);
276 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_OCTETS]), &value);
277 
278 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_LT64_PKTS, &value);
279 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LE_64_PKTS]), &value);
280 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_64_PKTS, &value);
281 	EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_TX_LE_64_PKTS]), &value);
282 
283 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_65_TO_127_PKTS, &value);
284 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_65_TO_127_PKTS]), &value);
285 
286 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_128_TO_255_PKTS, &value);
287 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_128_TO_255_PKTS]), &value);
288 
289 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_256_TO_511_PKTS, &value);
290 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_256_TO_511_PKTS]), &value);
291 
292 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_512_TO_1023_PKTS, &value);
293 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_512_TO_1023_PKTS]), &value);
294 
295 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_1024_TO_15XX_PKTS, &value);
296 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_1024_TO_15XX_PKTS]), &value);
297 
298 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_15XX_TO_JUMBO_PKTS, &value);
299 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_GE_15XX_PKTS]), &value);
300 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_GTJUMBO_PKTS, &value);
301 	EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_TX_GE_15XX_PKTS]), &value);
302 
303 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BAD_FCS_PKTS, &value);
304 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_ERRORS]), &value);
305 
306 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_SINGLE_COLLISION_PKTS, &value);
307 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_SGL_COL_PKTS]), &value);
308 
309 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_MULTIPLE_COLLISION_PKTS,
310 			    &value);
311 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_MULT_COL_PKTS]), &value);
312 
313 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_EXCESSIVE_COLLISION_PKTS,
314 			    &value);
315 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_EX_COL_PKTS]), &value);
316 
317 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_LATE_COLLISION_PKTS, &value);
318 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LATE_COL_PKTS]), &value);
319 
320 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_DEFERRED_PKTS, &value);
321 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_DEF_PKTS]), &value);
322 
323 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_EXCESSIVE_DEFERRED_PKTS,
324 	    &value);
325 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_EX_DEF_PKTS]), &value);
326 
327 	/* RX */
328 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BYTES, &value);
329 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_OCTETS]), &value);
330 
331 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_PKTS, &value);
332 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_PKTS]), &value);
333 
334 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_UNICAST_PKTS, &value);
335 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_UNICST_PKTS]), &value);
336 
337 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_MULTICAST_PKTS, &value);
338 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_MULTICST_PKTS]), &value);
339 
340 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BROADCAST_PKTS, &value);
341 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_BRDCST_PKTS]), &value);
342 
343 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_PAUSE_PKTS, &value);
344 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_PAUSE_PKTS]), &value);
345 
346 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_UNDERSIZE_PKTS, &value);
347 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_LE_64_PKTS]), &value);
348 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_64_PKTS, &value);
349 	EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_RX_LE_64_PKTS]), &value);
350 
351 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_65_TO_127_PKTS, &value);
352 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_65_TO_127_PKTS]), &value);
353 
354 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_128_TO_255_PKTS, &value);
355 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_128_TO_255_PKTS]), &value);
356 
357 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_256_TO_511_PKTS, &value);
358 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_256_TO_511_PKTS]), &value);
359 
360 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_512_TO_1023_PKTS, &value);
361 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_512_TO_1023_PKTS]), &value);
362 
363 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_1024_TO_15XX_PKTS, &value);
364 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_1024_TO_15XX_PKTS]), &value);
365 
366 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_15XX_TO_JUMBO_PKTS, &value);
367 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_GE_15XX_PKTS]), &value);
368 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_GTJUMBO_PKTS, &value);
369 	EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_RX_GE_15XX_PKTS]), &value);
370 
371 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BAD_FCS_PKTS, &value);
372 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_FCS_ERRORS]), &value);
373 
374 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_OVERFLOW_PKTS, &value);
375 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_DROP_EVENTS]), &value);
376 
377 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_FALSE_CARRIER_PKTS, &value);
378 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_FALSE_CARRIER_ERRORS]), &value);
379 
380 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_SYMBOL_ERROR_PKTS, &value);
381 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_SYMBOL_ERRORS]), &value);
382 
383 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_ALIGN_ERROR_PKTS, &value);
384 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_ALIGN_ERRORS]), &value);
385 
386 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_INTERNAL_ERROR_PKTS, &value);
387 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_INTERNAL_ERRORS]), &value);
388 
389 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_JABBER_PKTS, &value);
390 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_JABBER_PKTS]), &value);
391 
392 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES01_CHAR_ERR, &value);
393 	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE0_CHAR_ERR]),
394 			    &(value.eq_dword[0]));
395 	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE1_CHAR_ERR]),
396 			    &(value.eq_dword[1]));
397 
398 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES23_CHAR_ERR, &value);
399 	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE2_CHAR_ERR]),
400 			    &(value.eq_dword[0]));
401 	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE3_CHAR_ERR]),
402 			    &(value.eq_dword[1]));
403 
404 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES01_DISP_ERR, &value);
405 	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE0_DISP_ERR]),
406 			    &(value.eq_dword[0]));
407 	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE1_DISP_ERR]),
408 			    &(value.eq_dword[1]));
409 
410 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES23_DISP_ERR, &value);
411 	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE2_DISP_ERR]),
412 			    &(value.eq_dword[0]));
413 	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE3_DISP_ERR]),
414 			    &(value.eq_dword[1]));
415 
416 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_MATCH_FAULT, &value);
417 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_MATCH_FAULT]), &value);
418 
419 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_NODESC_DROPS, &value);
420 	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_NODESC_DROP_CNT]), &value);
421 
422 	EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, EFX_MAC_STATS_SIZE);
423 	EFSYS_MEM_READ_BARRIER();
424 	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_START,
425 			    &generation_start);
426 
427 	/* Check that we didn't read the stats in the middle of a DMA */
428 	/* Not a good enough check ? */
429 	if (memcmp(&generation_start, &generation_end,
430 	    sizeof (generation_start)))
431 		return (EAGAIN);
432 
433 	if (generationp)
434 		*generationp = EFX_QWORD_FIELD(generation_start, EFX_DWORD_0);
435 
436 	return (0);
437 }
438 
439 #endif	/* EFSYS_OPT_MAC_STATS */
440 
441 #endif	/* EFSYS_OPT_SIENA */
442