xref: /freebsd/sys/dev/sfxge/common/siena_nic.c (revision 1c05a6ea6b849ff95e539c31adea887c644a6a01)
1 /*-
2  * Copyright (c) 2009-2016 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 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
41 
42 static	__checkReturn		efx_rc_t
43 siena_nic_get_partn_mask(
44 	__in			efx_nic_t *enp,
45 	__out			unsigned int *maskp)
46 {
47 	efx_mcdi_req_t req;
48 	uint8_t payload[MAX(MC_CMD_NVRAM_TYPES_IN_LEN,
49 			    MC_CMD_NVRAM_TYPES_OUT_LEN)];
50 	efx_rc_t rc;
51 
52 	(void) memset(payload, 0, sizeof (payload));
53 	req.emr_cmd = MC_CMD_NVRAM_TYPES;
54 	req.emr_in_buf = payload;
55 	req.emr_in_length = MC_CMD_NVRAM_TYPES_IN_LEN;
56 	req.emr_out_buf = payload;
57 	req.emr_out_length = MC_CMD_NVRAM_TYPES_OUT_LEN;
58 
59 	efx_mcdi_execute(enp, &req);
60 
61 	if (req.emr_rc != 0) {
62 		rc = req.emr_rc;
63 		goto fail1;
64 	}
65 
66 	if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
67 		rc = EMSGSIZE;
68 		goto fail2;
69 	}
70 
71 	*maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
72 
73 	return (0);
74 
75 fail2:
76 	EFSYS_PROBE(fail2);
77 fail1:
78 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
79 
80 	return (rc);
81 }
82 
83 #endif /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */
84 
85 static	__checkReturn	efx_rc_t
86 siena_board_cfg(
87 	__in		efx_nic_t *enp)
88 {
89 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
90 	uint8_t mac_addr[6];
91 	efx_dword_t capabilities;
92 	uint32_t board_type;
93 	uint32_t nevq, nrxq, ntxq;
94 	efx_rc_t rc;
95 
96 	/* External port identifier using one-based port numbering */
97 	encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port;
98 
99 	/* Board configuration */
100 	if ((rc = efx_mcdi_get_board_cfg(enp, &board_type,
101 		    &capabilities, mac_addr)) != 0)
102 		goto fail1;
103 
104 	EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
105 
106 	encp->enc_board_type = board_type;
107 
108 	/*
109 	 * There is no possibility to determine the number of PFs on Siena
110 	 * by issuing MCDI request, and it is not an easy task to find the
111 	 * value based on the board type, so 'enc_hw_pf_count' is set to 1
112 	 */
113 	encp->enc_hw_pf_count = 1;
114 
115 	/* Additional capabilities */
116 	encp->enc_clk_mult = 1;
117 	if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) {
118 		enp->en_features |= EFX_FEATURE_TURBO;
119 
120 		if (EFX_DWORD_FIELD(capabilities,
121 			MC_CMD_CAPABILITIES_TURBO_ACTIVE)) {
122 			encp->enc_clk_mult = 2;
123 		}
124 	}
125 
126 	encp->enc_evq_timer_quantum_ns =
127 		EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
128 	encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
129 		FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
130 
131 	/* When hash header insertion is enabled, Siena inserts 16 bytes */
132 	encp->enc_rx_prefix_size = 16;
133 
134 	/* Alignment for receive packet DMA buffers */
135 	encp->enc_rx_buf_align_start = 1;
136 	encp->enc_rx_buf_align_end = 1;
137 
138 	/* Alignment for WPTR updates */
139 	encp->enc_rx_push_align = 1;
140 
141 	encp->enc_tx_dma_desc_size_max = EFX_MASK32(FSF_AZ_TX_KER_BYTE_COUNT);
142 	/* Fragments must not span 4k boundaries. */
143 	encp->enc_tx_dma_desc_boundary = 4096;
144 
145 	/* Resource limits */
146 	rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq);
147 	if (rc != 0) {
148 		if (rc != ENOTSUP)
149 			goto fail2;
150 
151 		nevq = 1024;
152 		nrxq = EFX_RXQ_LIMIT_TARGET;
153 		ntxq = EFX_TXQ_LIMIT_TARGET;
154 	}
155 	encp->enc_evq_limit = nevq;
156 	encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq);
157 	encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq);
158 
159 	encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
160 	    (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) -
161 	    (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
162 
163 	encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
164 	encp->enc_fw_assisted_tso_enabled = B_FALSE;
165 	encp->enc_fw_assisted_tso_v2_enabled = B_FALSE;
166 	encp->enc_fw_assisted_tso_v2_n_contexts = 0;
167 	encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
168 
169 	/* Siena supports two 10G ports, and 8 lanes of PCIe Gen2 */
170 	encp->enc_required_pcie_bandwidth_mbps = 2 * 10000;
171 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN2;
172 
173 	encp->enc_fw_verified_nvram_update_required = B_FALSE;
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