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