xref: /freebsd/sys/dev/sfxge/common/siena_nic.c (revision c6a33c8e88c5684876e670c8189d03ad25108d8a)
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 <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33 
34 #include "efsys.h"
35 #include "efx.h"
36 #include "efx_impl.h"
37 #include "mcdi_mon.h"
38 
39 #if EFSYS_OPT_SIENA
40 
41 static	__checkReturn		efx_rc_t
42 siena_nic_get_partn_mask(
43 	__in			efx_nic_t *enp,
44 	__out			unsigned int *maskp)
45 {
46 	efx_mcdi_req_t req;
47 	uint8_t payload[MAX(MC_CMD_NVRAM_TYPES_IN_LEN,
48 			    MC_CMD_NVRAM_TYPES_OUT_LEN)];
49 	efx_rc_t rc;
50 
51 	(void) memset(payload, 0, sizeof (payload));
52 	req.emr_cmd = MC_CMD_NVRAM_TYPES;
53 	req.emr_in_buf = payload;
54 	req.emr_in_length = MC_CMD_NVRAM_TYPES_IN_LEN;
55 	req.emr_out_buf = payload;
56 	req.emr_out_length = MC_CMD_NVRAM_TYPES_OUT_LEN;
57 
58 	efx_mcdi_execute(enp, &req);
59 
60 	if (req.emr_rc != 0) {
61 		rc = req.emr_rc;
62 		goto fail1;
63 	}
64 
65 	if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
66 		rc = EMSGSIZE;
67 		goto fail2;
68 	}
69 
70 	*maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
71 
72 	return (0);
73 
74 fail2:
75 	EFSYS_PROBE(fail2);
76 fail1:
77 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
78 
79 	return (rc);
80 }
81 
82 #if EFSYS_OPT_PCIE_TUNE
83 
84 	__checkReturn	efx_rc_t
85 siena_nic_pcie_extended_sync(
86 	__in		efx_nic_t *enp)
87 {
88 	efx_rc_t rc;
89 
90 	if ((rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG17230,
91 		    B_TRUE, NULL) != 0))
92 		goto fail1;
93 
94 	return (0);
95 
96 fail1:
97 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
98 
99 	return (rc);
100 }
101 
102 #endif	/* EFSYS_OPT_PCIE_TUNE */
103 
104 static	__checkReturn	efx_rc_t
105 siena_board_cfg(
106 	__in		efx_nic_t *enp)
107 {
108 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
109 	uint8_t mac_addr[6];
110 	efx_dword_t capabilities;
111 	uint32_t board_type;
112 	uint32_t nevq, nrxq, ntxq;
113 	efx_rc_t rc;
114 
115 	/* External port identifier using one-based port numbering */
116 	encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port;
117 
118 	/* Board configuration */
119 	if ((rc = efx_mcdi_get_board_cfg(enp, &board_type,
120 		    &capabilities, mac_addr)) != 0)
121 		goto fail1;
122 
123 	EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
124 
125 	encp->enc_board_type = board_type;
126 
127 	/* Additional capabilities */
128 	encp->enc_clk_mult = 1;
129 	if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) {
130 		enp->en_features |= EFX_FEATURE_TURBO;
131 
132 		if (EFX_DWORD_FIELD(capabilities,
133 			MC_CMD_CAPABILITIES_TURBO_ACTIVE)) {
134 			encp->enc_clk_mult = 2;
135 		}
136 	}
137 
138 	encp->enc_evq_timer_quantum_ns =
139 		EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
140 	encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
141 		FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
142 
143 	/* When hash header insertion is enabled, Siena inserts 16 bytes */
144 	encp->enc_rx_prefix_size = 16;
145 
146 	/* Alignment for receive packet DMA buffers */
147 	encp->enc_rx_buf_align_start = 1;
148 	encp->enc_rx_buf_align_end = 1;
149 
150 	/* Alignment for WPTR updates */
151 	encp->enc_rx_push_align = 1;
152 
153 	/* Resource limits */
154 	rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq);
155 	if (rc != 0) {
156 		if (rc != ENOTSUP)
157 			goto fail2;
158 
159 		nevq = 1024;
160 		nrxq = EFX_RXQ_LIMIT_TARGET;
161 		ntxq = EFX_TXQ_LIMIT_TARGET;
162 	}
163 	encp->enc_evq_limit = nevq;
164 	encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq);
165 	encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq);
166 
167 	encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
168 	    (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) -
169 	    (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
170 
171 	encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
172 	encp->enc_fw_assisted_tso_enabled = B_FALSE;
173 	encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
174 
175 	return (0);
176 
177 fail2:
178 	EFSYS_PROBE(fail2);
179 fail1:
180 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
181 
182 	return (rc);
183 }
184 
185 static	__checkReturn	efx_rc_t
186 siena_phy_cfg(
187 	__in		efx_nic_t *enp)
188 {
189 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
190 	efx_rc_t rc;
191 
192 	/* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
193 	if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
194 		goto fail1;
195 
196 #if EFSYS_OPT_PHY_STATS
197 	/* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
198 	siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask,
199 			    NULL, &encp->enc_phy_stat_mask, NULL);
200 #endif	/* EFSYS_OPT_PHY_STATS */
201 
202 	return (0);
203 
204 fail1:
205 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
206 
207 	return (rc);
208 }
209 
210 	__checkReturn	efx_rc_t
211 siena_nic_probe(
212 	__in		efx_nic_t *enp)
213 {
214 	efx_port_t *epp = &(enp->en_port);
215 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
216 	siena_link_state_t sls;
217 	unsigned int mask;
218 	efx_oword_t oword;
219 	efx_rc_t rc;
220 
221 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
222 
223 	/* Test BIU */
224 	if ((rc = efx_nic_biu_test(enp)) != 0)
225 		goto fail1;
226 
227 	/* Clear the region register */
228 	EFX_POPULATE_OWORD_4(oword,
229 	    FRF_AZ_ADR_REGION0, 0,
230 	    FRF_AZ_ADR_REGION1, (1 << 16),
231 	    FRF_AZ_ADR_REGION2, (2 << 16),
232 	    FRF_AZ_ADR_REGION3, (3 << 16));
233 	EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
234 
235 	/* Read clear any assertion state */
236 	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
237 		goto fail2;
238 
239 	/* Exit the assertion handler */
240 	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
241 		goto fail3;
242 
243 	/* Wrestle control from the BMC */
244 	if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
245 		goto fail4;
246 
247 	if ((rc = siena_board_cfg(enp)) != 0)
248 		goto fail5;
249 
250 	if ((rc = siena_phy_cfg(enp)) != 0)
251 		goto fail6;
252 
253 	/* Obtain the default PHY advertised capabilities */
254 	if ((rc = siena_nic_reset(enp)) != 0)
255 		goto fail7;
256 	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
257 		goto fail8;
258 	epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
259 	epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
260 
261 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
262 	if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
263 		goto fail9;
264 	enp->en_u.siena.enu_partn_mask = mask;
265 #endif
266 
267 #if EFSYS_OPT_MAC_STATS
268 	/* Wipe the MAC statistics */
269 	if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
270 		goto fail10;
271 #endif
272 
273 #if EFSYS_OPT_LOOPBACK
274 	if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
275 		goto fail11;
276 #endif
277 
278 #if EFSYS_OPT_MON_STATS
279 	if ((rc = mcdi_mon_cfg_build(enp)) != 0)
280 		goto fail12;
281 #endif
282 
283 	encp->enc_features = enp->en_features;
284 
285 	return (0);
286 
287 #if EFSYS_OPT_MON_STATS
288 fail12:
289 	EFSYS_PROBE(fail12);
290 #endif
291 #if EFSYS_OPT_LOOPBACK
292 fail11:
293 	EFSYS_PROBE(fail11);
294 #endif
295 #if EFSYS_OPT_MAC_STATS
296 fail10:
297 	EFSYS_PROBE(fail10);
298 #endif
299 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
300 fail9:
301 	EFSYS_PROBE(fail9);
302 #endif
303 fail8:
304 	EFSYS_PROBE(fail8);
305 fail7:
306 	EFSYS_PROBE(fail7);
307 fail6:
308 	EFSYS_PROBE(fail6);
309 fail5:
310 	EFSYS_PROBE(fail5);
311 fail4:
312 	EFSYS_PROBE(fail4);
313 fail3:
314 	EFSYS_PROBE(fail3);
315 fail2:
316 	EFSYS_PROBE(fail2);
317 fail1:
318 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
319 
320 	return (rc);
321 }
322 
323 	__checkReturn	efx_rc_t
324 siena_nic_reset(
325 	__in		efx_nic_t *enp)
326 {
327 	efx_mcdi_req_t req;
328 	efx_rc_t rc;
329 
330 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
331 
332 	/* siena_nic_reset() is called to recover from BADASSERT failures. */
333 	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
334 		goto fail1;
335 	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
336 		goto fail2;
337 
338 	/*
339 	 * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied
340 	 * for backwards compatibility with PORT_RESET_IN_LEN.
341 	 */
342 	EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0);
343 
344 	req.emr_cmd = MC_CMD_ENTITY_RESET;
345 	req.emr_in_buf = NULL;
346 	req.emr_in_length = 0;
347 	req.emr_out_buf = NULL;
348 	req.emr_out_length = 0;
349 
350 	efx_mcdi_execute(enp, &req);
351 
352 	if (req.emr_rc != 0) {
353 		rc = req.emr_rc;
354 		goto fail3;
355 	}
356 
357 	return (0);
358 
359 fail3:
360 	EFSYS_PROBE(fail3);
361 fail2:
362 	EFSYS_PROBE(fail2);
363 fail1:
364 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
365 
366 	return (0);
367 }
368 
369 static			void
370 siena_nic_rx_cfg(
371 	__in		efx_nic_t *enp)
372 {
373 	efx_oword_t oword;
374 
375 	/*
376 	 * RX_INGR_EN is always enabled on Siena, because we rely on
377 	 * the RX parser to be resiliant to missing SOP/EOP.
378 	 */
379 	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
380 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
381 	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
382 
383 	/* Disable parsing of additional 802.1Q in Q packets */
384 	EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
385 	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
386 	EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
387 }
388 
389 static			void
390 siena_nic_usrev_dis(
391 	__in		efx_nic_t *enp)
392 {
393 	efx_oword_t	oword;
394 
395 	EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
396 	EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
397 }
398 
399 	__checkReturn	efx_rc_t
400 siena_nic_init(
401 	__in		efx_nic_t *enp)
402 {
403 	efx_rc_t rc;
404 
405 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
406 
407 	/* Enable reporting of some events (e.g. link change) */
408 	if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
409 		goto fail1;
410 
411 	siena_sram_init(enp);
412 
413 	/* Configure Siena's RX block */
414 	siena_nic_rx_cfg(enp);
415 
416 	/* Disable USR_EVents for now */
417 	siena_nic_usrev_dis(enp);
418 
419 	/* bug17057: Ensure set_link is called */
420 	if ((rc = siena_phy_reconfigure(enp)) != 0)
421 		goto fail2;
422 
423 	enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V1;
424 
425 	return (0);
426 
427 fail2:
428 	EFSYS_PROBE(fail2);
429 fail1:
430 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
431 
432 	return (rc);
433 }
434 
435 			void
436 siena_nic_fini(
437 	__in		efx_nic_t *enp)
438 {
439 	_NOTE(ARGUNUSED(enp))
440 }
441 
442 			void
443 siena_nic_unprobe(
444 	__in		efx_nic_t *enp)
445 {
446 #if EFSYS_OPT_MON_STATS
447 	mcdi_mon_cfg_free(enp);
448 #endif /* EFSYS_OPT_MON_STATS */
449 	(void) efx_mcdi_drv_attach(enp, B_FALSE);
450 }
451 
452 #if EFSYS_OPT_DIAG
453 
454 static efx_register_set_t __siena_registers[] = {
455 	{ FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
456 	{ FR_CZ_USR_EV_CFG_OFST, 0, 1 },
457 	{ FR_AZ_RX_CFG_REG_OFST, 0, 1 },
458 	{ FR_AZ_TX_CFG_REG_OFST, 0, 1 },
459 	{ FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
460 	{ FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
461 	{ FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
462 	{ FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
463 	{ FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
464 	{ FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
465 	{ FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
466 	{ FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
467 	{ FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
468 };
469 
470 static const uint32_t __siena_register_masks[] = {
471 	0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
472 	0x000103FF, 0x00000000, 0x00000000, 0x00000000,
473 	0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
474 	0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
475 	0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
476 	0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
477 	0x00000003, 0x00000000, 0x00000000, 0x00000000,
478 	0x000003FF, 0x00000000, 0x00000000, 0x00000000,
479 	0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
480 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
481 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
482 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
483 	0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
484 };
485 
486 static efx_register_set_t __siena_tables[] = {
487 	{ FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
488 	    FR_AZ_RX_FILTER_TBL0_ROWS },
489 	{ FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
490 	    FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
491 	{ FR_AZ_RX_DESC_PTR_TBL_OFST,
492 	    FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
493 	{ FR_AZ_TX_DESC_PTR_TBL_OFST,
494 	    FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
495 	{ FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
496 	{ FR_CZ_TX_FILTER_TBL0_OFST,
497 	    FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
498 	{ FR_CZ_TX_MAC_FILTER_TBL0_OFST,
499 	    FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
500 };
501 
502 static const uint32_t __siena_table_masks[] = {
503 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
504 	0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
505 	0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
506 	0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
507 	0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
508 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
509 	0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
510 };
511 
512 	__checkReturn	efx_rc_t
513 siena_nic_register_test(
514 	__in		efx_nic_t *enp)
515 {
516 	efx_register_set_t *rsp;
517 	const uint32_t *dwordp;
518 	unsigned int nitems;
519 	unsigned int count;
520 	efx_rc_t rc;
521 
522 	/* Fill out the register mask entries */
523 	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
524 		    == EFX_ARRAY_SIZE(__siena_registers) * 4);
525 
526 	nitems = EFX_ARRAY_SIZE(__siena_registers);
527 	dwordp = __siena_register_masks;
528 	for (count = 0; count < nitems; ++count) {
529 		rsp = __siena_registers + count;
530 		rsp->mask.eo_u32[0] = *dwordp++;
531 		rsp->mask.eo_u32[1] = *dwordp++;
532 		rsp->mask.eo_u32[2] = *dwordp++;
533 		rsp->mask.eo_u32[3] = *dwordp++;
534 	}
535 
536 	/* Fill out the register table entries */
537 	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
538 		    == EFX_ARRAY_SIZE(__siena_tables) * 4);
539 
540 	nitems = EFX_ARRAY_SIZE(__siena_tables);
541 	dwordp = __siena_table_masks;
542 	for (count = 0; count < nitems; ++count) {
543 		rsp = __siena_tables + count;
544 		rsp->mask.eo_u32[0] = *dwordp++;
545 		rsp->mask.eo_u32[1] = *dwordp++;
546 		rsp->mask.eo_u32[2] = *dwordp++;
547 		rsp->mask.eo_u32[3] = *dwordp++;
548 	}
549 
550 	if ((rc = efx_nic_test_registers(enp, __siena_registers,
551 	    EFX_ARRAY_SIZE(__siena_registers))) != 0)
552 		goto fail1;
553 
554 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
555 	    EFX_PATTERN_BYTE_ALTERNATE,
556 	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
557 		goto fail2;
558 
559 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
560 	    EFX_PATTERN_BYTE_CHANGING,
561 	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
562 		goto fail3;
563 
564 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
565 	    EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
566 		goto fail4;
567 
568 	return (0);
569 
570 fail4:
571 	EFSYS_PROBE(fail4);
572 fail3:
573 	EFSYS_PROBE(fail3);
574 fail2:
575 	EFSYS_PROBE(fail2);
576 fail1:
577 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
578 
579 	return (rc);
580 }
581 
582 #endif	/* EFSYS_OPT_DIAG */
583 
584 #endif	/* EFSYS_OPT_SIENA */
585