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