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