xref: /freebsd/sys/dev/sfxge/common/siena_nic.c (revision f39bffc62c1395bde25d152c7f68fdf7cbaab414)
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 
171 	/* Siena supports two 10G ports, and 8 lanes of PCIe Gen2 */
172 	encp->enc_required_pcie_bandwidth_mbps = 2 * 10000;
173 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN2;
174 
175 	encp->enc_fw_verified_nvram_update_required = B_FALSE;
176 
177 	return (0);
178 
179 fail2:
180 	EFSYS_PROBE(fail2);
181 fail1:
182 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
183 
184 	return (rc);
185 }
186 
187 static	__checkReturn	efx_rc_t
188 siena_phy_cfg(
189 	__in		efx_nic_t *enp)
190 {
191 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
192 	efx_rc_t rc;
193 
194 	/* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
195 	if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
196 		goto fail1;
197 
198 #if EFSYS_OPT_PHY_STATS
199 	/* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
200 	siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask,
201 			    NULL, &encp->enc_phy_stat_mask, NULL);
202 #endif	/* EFSYS_OPT_PHY_STATS */
203 
204 	return (0);
205 
206 fail1:
207 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
208 
209 	return (rc);
210 }
211 
212 	__checkReturn	efx_rc_t
213 siena_nic_probe(
214 	__in		efx_nic_t *enp)
215 {
216 	efx_port_t *epp = &(enp->en_port);
217 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
218 	siena_link_state_t sls;
219 	unsigned int mask;
220 	efx_oword_t oword;
221 	efx_rc_t rc;
222 
223 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
224 
225 	/* Test BIU */
226 	if ((rc = efx_nic_biu_test(enp)) != 0)
227 		goto fail1;
228 
229 	/* Clear the region register */
230 	EFX_POPULATE_OWORD_4(oword,
231 	    FRF_AZ_ADR_REGION0, 0,
232 	    FRF_AZ_ADR_REGION1, (1 << 16),
233 	    FRF_AZ_ADR_REGION2, (2 << 16),
234 	    FRF_AZ_ADR_REGION3, (3 << 16));
235 	EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
236 
237 	/* Read clear any assertion state */
238 	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
239 		goto fail2;
240 
241 	/* Exit the assertion handler */
242 	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
243 		goto fail3;
244 
245 	/* Wrestle control from the BMC */
246 	if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
247 		goto fail4;
248 
249 	if ((rc = siena_board_cfg(enp)) != 0)
250 		goto fail5;
251 
252 	if ((rc = siena_phy_cfg(enp)) != 0)
253 		goto fail6;
254 
255 	/* Obtain the default PHY advertised capabilities */
256 	if ((rc = siena_nic_reset(enp)) != 0)
257 		goto fail7;
258 	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
259 		goto fail8;
260 	epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
261 	epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
262 
263 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
264 	if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
265 		goto fail9;
266 	enp->en_u.siena.enu_partn_mask = mask;
267 #endif
268 
269 #if EFSYS_OPT_MAC_STATS
270 	/* Wipe the MAC statistics */
271 	if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
272 		goto fail10;
273 #endif
274 
275 #if EFSYS_OPT_LOOPBACK
276 	if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
277 		goto fail11;
278 #endif
279 
280 #if EFSYS_OPT_MON_STATS
281 	if ((rc = mcdi_mon_cfg_build(enp)) != 0)
282 		goto fail12;
283 #endif
284 
285 	encp->enc_features = enp->en_features;
286 
287 	return (0);
288 
289 #if EFSYS_OPT_MON_STATS
290 fail12:
291 	EFSYS_PROBE(fail12);
292 #endif
293 #if EFSYS_OPT_LOOPBACK
294 fail11:
295 	EFSYS_PROBE(fail11);
296 #endif
297 #if EFSYS_OPT_MAC_STATS
298 fail10:
299 	EFSYS_PROBE(fail10);
300 #endif
301 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
302 fail9:
303 	EFSYS_PROBE(fail9);
304 #endif
305 fail8:
306 	EFSYS_PROBE(fail8);
307 fail7:
308 	EFSYS_PROBE(fail7);
309 fail6:
310 	EFSYS_PROBE(fail6);
311 fail5:
312 	EFSYS_PROBE(fail5);
313 fail4:
314 	EFSYS_PROBE(fail4);
315 fail3:
316 	EFSYS_PROBE(fail3);
317 fail2:
318 	EFSYS_PROBE(fail2);
319 fail1:
320 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
321 
322 	return (rc);
323 }
324 
325 	__checkReturn	efx_rc_t
326 siena_nic_reset(
327 	__in		efx_nic_t *enp)
328 {
329 	efx_mcdi_req_t req;
330 	efx_rc_t rc;
331 
332 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
333 
334 	/* siena_nic_reset() is called to recover from BADASSERT failures. */
335 	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
336 		goto fail1;
337 	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
338 		goto fail2;
339 
340 	/*
341 	 * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied
342 	 * for backwards compatibility with PORT_RESET_IN_LEN.
343 	 */
344 	EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0);
345 
346 	req.emr_cmd = MC_CMD_ENTITY_RESET;
347 	req.emr_in_buf = NULL;
348 	req.emr_in_length = 0;
349 	req.emr_out_buf = NULL;
350 	req.emr_out_length = 0;
351 
352 	efx_mcdi_execute(enp, &req);
353 
354 	if (req.emr_rc != 0) {
355 		rc = req.emr_rc;
356 		goto fail3;
357 	}
358 
359 	return (0);
360 
361 fail3:
362 	EFSYS_PROBE(fail3);
363 fail2:
364 	EFSYS_PROBE(fail2);
365 fail1:
366 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
367 
368 	return (0);
369 }
370 
371 static			void
372 siena_nic_rx_cfg(
373 	__in		efx_nic_t *enp)
374 {
375 	efx_oword_t oword;
376 
377 	/*
378 	 * RX_INGR_EN is always enabled on Siena, because we rely on
379 	 * the RX parser to be resiliant to missing SOP/EOP.
380 	 */
381 	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
382 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
383 	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
384 
385 	/* Disable parsing of additional 802.1Q in Q packets */
386 	EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
387 	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
388 	EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
389 }
390 
391 static			void
392 siena_nic_usrev_dis(
393 	__in		efx_nic_t *enp)
394 {
395 	efx_oword_t	oword;
396 
397 	EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
398 	EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
399 }
400 
401 	__checkReturn	efx_rc_t
402 siena_nic_init(
403 	__in		efx_nic_t *enp)
404 {
405 	efx_rc_t rc;
406 
407 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
408 
409 	/* Enable reporting of some events (e.g. link change) */
410 	if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
411 		goto fail1;
412 
413 	siena_sram_init(enp);
414 
415 	/* Configure Siena's RX block */
416 	siena_nic_rx_cfg(enp);
417 
418 	/* Disable USR_EVents for now */
419 	siena_nic_usrev_dis(enp);
420 
421 	/* bug17057: Ensure set_link is called */
422 	if ((rc = siena_phy_reconfigure(enp)) != 0)
423 		goto fail2;
424 
425 	enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V1;
426 
427 	return (0);
428 
429 fail2:
430 	EFSYS_PROBE(fail2);
431 fail1:
432 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
433 
434 	return (rc);
435 }
436 
437 			void
438 siena_nic_fini(
439 	__in		efx_nic_t *enp)
440 {
441 	_NOTE(ARGUNUSED(enp))
442 }
443 
444 			void
445 siena_nic_unprobe(
446 	__in		efx_nic_t *enp)
447 {
448 #if EFSYS_OPT_MON_STATS
449 	mcdi_mon_cfg_free(enp);
450 #endif /* EFSYS_OPT_MON_STATS */
451 	(void) efx_mcdi_drv_attach(enp, B_FALSE);
452 }
453 
454 #if EFSYS_OPT_DIAG
455 
456 static efx_register_set_t __siena_registers[] = {
457 	{ FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
458 	{ FR_CZ_USR_EV_CFG_OFST, 0, 1 },
459 	{ FR_AZ_RX_CFG_REG_OFST, 0, 1 },
460 	{ FR_AZ_TX_CFG_REG_OFST, 0, 1 },
461 	{ FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
462 	{ FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
463 	{ FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
464 	{ FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
465 	{ FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
466 	{ FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
467 	{ FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
468 	{ FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
469 	{ FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
470 };
471 
472 static const uint32_t __siena_register_masks[] = {
473 	0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
474 	0x000103FF, 0x00000000, 0x00000000, 0x00000000,
475 	0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
476 	0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
477 	0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
478 	0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
479 	0x00000003, 0x00000000, 0x00000000, 0x00000000,
480 	0x000003FF, 0x00000000, 0x00000000, 0x00000000,
481 	0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
482 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
483 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
484 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
485 	0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
486 };
487 
488 static efx_register_set_t __siena_tables[] = {
489 	{ FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
490 	    FR_AZ_RX_FILTER_TBL0_ROWS },
491 	{ FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
492 	    FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
493 	{ FR_AZ_RX_DESC_PTR_TBL_OFST,
494 	    FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
495 	{ FR_AZ_TX_DESC_PTR_TBL_OFST,
496 	    FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
497 	{ FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
498 	{ FR_CZ_TX_FILTER_TBL0_OFST,
499 	    FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
500 	{ FR_CZ_TX_MAC_FILTER_TBL0_OFST,
501 	    FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
502 };
503 
504 static const uint32_t __siena_table_masks[] = {
505 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
506 	0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
507 	0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
508 	0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
509 	0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
510 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
511 	0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
512 };
513 
514 	__checkReturn	efx_rc_t
515 siena_nic_register_test(
516 	__in		efx_nic_t *enp)
517 {
518 	efx_register_set_t *rsp;
519 	const uint32_t *dwordp;
520 	unsigned int nitems;
521 	unsigned int count;
522 	efx_rc_t rc;
523 
524 	/* Fill out the register mask entries */
525 	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
526 		    == EFX_ARRAY_SIZE(__siena_registers) * 4);
527 
528 	nitems = EFX_ARRAY_SIZE(__siena_registers);
529 	dwordp = __siena_register_masks;
530 	for (count = 0; count < nitems; ++count) {
531 		rsp = __siena_registers + count;
532 		rsp->mask.eo_u32[0] = *dwordp++;
533 		rsp->mask.eo_u32[1] = *dwordp++;
534 		rsp->mask.eo_u32[2] = *dwordp++;
535 		rsp->mask.eo_u32[3] = *dwordp++;
536 	}
537 
538 	/* Fill out the register table entries */
539 	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
540 		    == EFX_ARRAY_SIZE(__siena_tables) * 4);
541 
542 	nitems = EFX_ARRAY_SIZE(__siena_tables);
543 	dwordp = __siena_table_masks;
544 	for (count = 0; count < nitems; ++count) {
545 		rsp = __siena_tables + count;
546 		rsp->mask.eo_u32[0] = *dwordp++;
547 		rsp->mask.eo_u32[1] = *dwordp++;
548 		rsp->mask.eo_u32[2] = *dwordp++;
549 		rsp->mask.eo_u32[3] = *dwordp++;
550 	}
551 
552 	if ((rc = efx_nic_test_registers(enp, __siena_registers,
553 	    EFX_ARRAY_SIZE(__siena_registers))) != 0)
554 		goto fail1;
555 
556 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
557 	    EFX_PATTERN_BYTE_ALTERNATE,
558 	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
559 		goto fail2;
560 
561 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
562 	    EFX_PATTERN_BYTE_CHANGING,
563 	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
564 		goto fail3;
565 
566 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
567 	    EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
568 		goto fail4;
569 
570 	return (0);
571 
572 fail4:
573 	EFSYS_PROBE(fail4);
574 fail3:
575 	EFSYS_PROBE(fail3);
576 fail2:
577 	EFSYS_PROBE(fail2);
578 fail1:
579 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
580 
581 	return (rc);
582 }
583 
584 #endif	/* EFSYS_OPT_DIAG */
585 
586 #endif	/* EFSYS_OPT_SIENA */
587