xref: /freebsd/sys/dev/sfxge/common/siena_nic.c (revision ceeff9b1)
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 	/* Siena has a fixed 8Kbyte VI window size */
99 	EFX_STATIC_ASSERT(1U << EFX_VI_WINDOW_SHIFT_8K	== 8192);
100 	encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_8K;
101 
102 	/* External port identifier using one-based port numbering */
103 	encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port;
104 
105 	/* Board configuration */
106 	if ((rc = efx_mcdi_get_board_cfg(enp, &board_type,
107 		    &capabilities, mac_addr)) != 0)
108 		goto fail1;
109 
110 	EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
111 
112 	encp->enc_board_type = board_type;
113 
114 	/*
115 	 * There is no possibility to determine the number of PFs on Siena
116 	 * by issuing MCDI request, and it is not an easy task to find the
117 	 * value based on the board type, so 'enc_hw_pf_count' is set to 1
118 	 */
119 	encp->enc_hw_pf_count = 1;
120 
121 	/* Additional capabilities */
122 	encp->enc_clk_mult = 1;
123 	if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) {
124 		enp->en_features |= EFX_FEATURE_TURBO;
125 
126 		if (EFX_DWORD_FIELD(capabilities,
127 			MC_CMD_CAPABILITIES_TURBO_ACTIVE)) {
128 			encp->enc_clk_mult = 2;
129 		}
130 	}
131 
132 	encp->enc_evq_timer_quantum_ns =
133 		EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
134 	encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
135 		FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
136 
137 	/* When hash header insertion is enabled, Siena inserts 16 bytes */
138 	encp->enc_rx_prefix_size = 16;
139 
140 	/* Alignment for receive packet DMA buffers */
141 	encp->enc_rx_buf_align_start = 1;
142 	encp->enc_rx_buf_align_end = 1;
143 
144 	/* Alignment for WPTR updates */
145 	encp->enc_rx_push_align = 1;
146 
147 	/* There is one RSS context per function */
148 	encp->enc_rx_scale_max_exclusive_contexts = 1;
149 
150 	encp->enc_rx_scale_hash_alg_mask |= (1U << EFX_RX_HASHALG_LFSR);
151 	encp->enc_rx_scale_hash_alg_mask |= (1U << EFX_RX_HASHALG_TOEPLITZ);
152 
153 	/*
154 	 * It is always possible to use port numbers
155 	 * as the input data for hash computation.
156 	 */
157 	encp->enc_rx_scale_l4_hash_supported = B_TRUE;
158 
159 	/* There is no support for additional RSS modes */
160 	encp->enc_rx_scale_additional_modes_supported = B_FALSE;
161 
162 	encp->enc_tx_dma_desc_size_max = EFX_MASK32(FSF_AZ_TX_KER_BYTE_COUNT);
163 	/* Fragments must not span 4k boundaries. */
164 	encp->enc_tx_dma_desc_boundary = 4096;
165 
166 	/* Resource limits */
167 	rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq);
168 	if (rc != 0) {
169 		if (rc != ENOTSUP)
170 			goto fail2;
171 
172 		nevq = 1024;
173 		nrxq = EFX_RXQ_LIMIT_TARGET;
174 		ntxq = EFX_TXQ_LIMIT_TARGET;
175 	}
176 	encp->enc_evq_limit = nevq;
177 	encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq);
178 	encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq);
179 
180 	encp->enc_txq_max_ndescs = 4096;
181 
182 	encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
183 	    (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) -
184 	    (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
185 
186 	encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
187 	encp->enc_fw_assisted_tso_enabled = B_FALSE;
188 	encp->enc_fw_assisted_tso_v2_enabled = B_FALSE;
189 	encp->enc_fw_assisted_tso_v2_n_contexts = 0;
190 	encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
191 	encp->enc_rx_packed_stream_supported = B_FALSE;
192 	encp->enc_rx_var_packed_stream_supported = B_FALSE;
193 	encp->enc_rx_es_super_buffer_supported = B_FALSE;
194 	encp->enc_fw_subvariant_no_tx_csum_supported = B_FALSE;
195 
196 	/* Siena supports two 10G ports, and 8 lanes of PCIe Gen2 */
197 	encp->enc_required_pcie_bandwidth_mbps = 2 * 10000;
198 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN2;
199 
200 	encp->enc_nvram_update_verify_result_supported = B_FALSE;
201 
202 	encp->enc_mac_stats_nstats = MC_CMD_MAC_NSTATS;
203 
204 	return (0);
205 
206 fail2:
207 	EFSYS_PROBE(fail2);
208 fail1:
209 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
210 
211 	return (rc);
212 }
213 
214 static	__checkReturn	efx_rc_t
215 siena_phy_cfg(
216 	__in		efx_nic_t *enp)
217 {
218 #if EFSYS_OPT_PHY_STATS
219 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
220 #endif	/* EFSYS_OPT_PHY_STATS */
221 	efx_rc_t rc;
222 
223 	/* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
224 	if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
225 		goto fail1;
226 
227 #if EFSYS_OPT_PHY_STATS
228 	/* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
229 	siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask,
230 			    NULL, &encp->enc_phy_stat_mask, NULL);
231 #endif	/* EFSYS_OPT_PHY_STATS */
232 
233 	return (0);
234 
235 fail1:
236 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
237 
238 	return (rc);
239 }
240 
241 #define	SIENA_BIU_MAGIC0	0x01234567
242 #define	SIENA_BIU_MAGIC1	0xfedcba98
243 
244 static	__checkReturn	efx_rc_t
245 siena_nic_biu_test(
246 	__in		efx_nic_t *enp)
247 {
248 	efx_oword_t oword;
249 	efx_rc_t rc;
250 
251 	/*
252 	 * Write magic values to scratch registers 0 and 1, then
253 	 * verify that the values were written correctly.  Interleave
254 	 * the accesses to ensure that the BIU is not just reading
255 	 * back the cached value that was last written.
256 	 */
257 	EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC0);
258 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE);
259 
260 	EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC1);
261 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE);
262 
263 	EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE);
264 	if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC0) {
265 		rc = EIO;
266 		goto fail1;
267 	}
268 
269 	EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE);
270 	if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC1) {
271 		rc = EIO;
272 		goto fail2;
273 	}
274 
275 	/*
276 	 * Perform the same test, with the values swapped.  This
277 	 * ensures that subsequent tests don't start with the correct
278 	 * values already written into the scratch registers.
279 	 */
280 	EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC1);
281 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE);
282 
283 	EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC0);
284 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE);
285 
286 	EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE);
287 	if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC1) {
288 		rc = EIO;
289 		goto fail3;
290 	}
291 
292 	EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE);
293 	if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC0) {
294 		rc = EIO;
295 		goto fail4;
296 	}
297 
298 	return (0);
299 
300 fail4:
301 	EFSYS_PROBE(fail4);
302 fail3:
303 	EFSYS_PROBE(fail3);
304 fail2:
305 	EFSYS_PROBE(fail2);
306 fail1:
307 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
308 
309 	return (rc);
310 }
311 
312 	__checkReturn	efx_rc_t
313 siena_nic_probe(
314 	__in		efx_nic_t *enp)
315 {
316 	efx_port_t *epp = &(enp->en_port);
317 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
318 	siena_link_state_t sls;
319 	unsigned int mask;
320 	efx_oword_t oword;
321 	efx_rc_t rc;
322 
323 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
324 
325 	/* Test BIU */
326 	if ((rc = siena_nic_biu_test(enp)) != 0)
327 		goto fail1;
328 
329 	/* Clear the region register */
330 	EFX_POPULATE_OWORD_4(oword,
331 	    FRF_AZ_ADR_REGION0, 0,
332 	    FRF_AZ_ADR_REGION1, (1 << 16),
333 	    FRF_AZ_ADR_REGION2, (2 << 16),
334 	    FRF_AZ_ADR_REGION3, (3 << 16));
335 	EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
336 
337 	/* Read clear any assertion state */
338 	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
339 		goto fail2;
340 
341 	/* Exit the assertion handler */
342 	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
343 		goto fail3;
344 
345 	/* Wrestle control from the BMC */
346 	if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
347 		goto fail4;
348 
349 	if ((rc = siena_board_cfg(enp)) != 0)
350 		goto fail5;
351 
352 	if ((rc = siena_phy_cfg(enp)) != 0)
353 		goto fail6;
354 
355 	/* Obtain the default PHY advertised capabilities */
356 	if ((rc = siena_nic_reset(enp)) != 0)
357 		goto fail7;
358 	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
359 		goto fail8;
360 	epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
361 	epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
362 
363 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
364 	if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
365 		goto fail9;
366 	enp->en_u.siena.enu_partn_mask = mask;
367 #endif
368 
369 #if EFSYS_OPT_MAC_STATS
370 	/* Wipe the MAC statistics */
371 	if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
372 		goto fail10;
373 #endif
374 
375 #if EFSYS_OPT_LOOPBACK
376 	if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
377 		goto fail11;
378 #endif
379 
380 #if EFSYS_OPT_MON_STATS
381 	if ((rc = mcdi_mon_cfg_build(enp)) != 0)
382 		goto fail12;
383 #endif
384 
385 	encp->enc_features = enp->en_features;
386 
387 	return (0);
388 
389 #if EFSYS_OPT_MON_STATS
390 fail12:
391 	EFSYS_PROBE(fail12);
392 #endif
393 #if EFSYS_OPT_LOOPBACK
394 fail11:
395 	EFSYS_PROBE(fail11);
396 #endif
397 #if EFSYS_OPT_MAC_STATS
398 fail10:
399 	EFSYS_PROBE(fail10);
400 #endif
401 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
402 fail9:
403 	EFSYS_PROBE(fail9);
404 #endif
405 fail8:
406 	EFSYS_PROBE(fail8);
407 fail7:
408 	EFSYS_PROBE(fail7);
409 fail6:
410 	EFSYS_PROBE(fail6);
411 fail5:
412 	EFSYS_PROBE(fail5);
413 fail4:
414 	EFSYS_PROBE(fail4);
415 fail3:
416 	EFSYS_PROBE(fail3);
417 fail2:
418 	EFSYS_PROBE(fail2);
419 fail1:
420 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
421 
422 	return (rc);
423 }
424 
425 	__checkReturn	efx_rc_t
426 siena_nic_reset(
427 	__in		efx_nic_t *enp)
428 {
429 	efx_mcdi_req_t req;
430 	efx_rc_t rc;
431 
432 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
433 
434 	/* siena_nic_reset() is called to recover from BADASSERT failures. */
435 	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
436 		goto fail1;
437 	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
438 		goto fail2;
439 
440 	/*
441 	 * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied
442 	 * for backwards compatibility with PORT_RESET_IN_LEN.
443 	 */
444 	EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0);
445 
446 	req.emr_cmd = MC_CMD_ENTITY_RESET;
447 	req.emr_in_buf = NULL;
448 	req.emr_in_length = 0;
449 	req.emr_out_buf = NULL;
450 	req.emr_out_length = 0;
451 
452 	efx_mcdi_execute(enp, &req);
453 
454 	if (req.emr_rc != 0) {
455 		rc = req.emr_rc;
456 		goto fail3;
457 	}
458 
459 	return (0);
460 
461 fail3:
462 	EFSYS_PROBE(fail3);
463 fail2:
464 	EFSYS_PROBE(fail2);
465 fail1:
466 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
467 
468 	return (0);
469 }
470 
471 static			void
472 siena_nic_rx_cfg(
473 	__in		efx_nic_t *enp)
474 {
475 	efx_oword_t oword;
476 
477 	/*
478 	 * RX_INGR_EN is always enabled on Siena, because we rely on
479 	 * the RX parser to be resiliant to missing SOP/EOP.
480 	 */
481 	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
482 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
483 	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
484 
485 	/* Disable parsing of additional 802.1Q in Q packets */
486 	EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
487 	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
488 	EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
489 }
490 
491 static			void
492 siena_nic_usrev_dis(
493 	__in		efx_nic_t *enp)
494 {
495 	efx_oword_t	oword;
496 
497 	EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
498 	EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
499 }
500 
501 	__checkReturn	efx_rc_t
502 siena_nic_init(
503 	__in		efx_nic_t *enp)
504 {
505 	efx_rc_t rc;
506 
507 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
508 
509 	/* Enable reporting of some events (e.g. link change) */
510 	if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
511 		goto fail1;
512 
513 	siena_sram_init(enp);
514 
515 	/* Configure Siena's RX block */
516 	siena_nic_rx_cfg(enp);
517 
518 	/* Disable USR_EVents for now */
519 	siena_nic_usrev_dis(enp);
520 
521 	/* bug17057: Ensure set_link is called */
522 	if ((rc = siena_phy_reconfigure(enp)) != 0)
523 		goto fail2;
524 
525 	enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V1;
526 
527 	return (0);
528 
529 fail2:
530 	EFSYS_PROBE(fail2);
531 fail1:
532 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
533 
534 	return (rc);
535 }
536 
537 			void
538 siena_nic_fini(
539 	__in		efx_nic_t *enp)
540 {
541 	_NOTE(ARGUNUSED(enp))
542 }
543 
544 			void
545 siena_nic_unprobe(
546 	__in		efx_nic_t *enp)
547 {
548 #if EFSYS_OPT_MON_STATS
549 	mcdi_mon_cfg_free(enp);
550 #endif /* EFSYS_OPT_MON_STATS */
551 	(void) efx_mcdi_drv_attach(enp, B_FALSE);
552 }
553 
554 #if EFSYS_OPT_DIAG
555 
556 static siena_register_set_t __siena_registers[] = {
557 	{ FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
558 	{ FR_CZ_USR_EV_CFG_OFST, 0, 1 },
559 	{ FR_AZ_RX_CFG_REG_OFST, 0, 1 },
560 	{ FR_AZ_TX_CFG_REG_OFST, 0, 1 },
561 	{ FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
562 	{ FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
563 	{ FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
564 	{ FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
565 	{ FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
566 	{ FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
567 	{ FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
568 	{ FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
569 	{ FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
570 };
571 
572 static const uint32_t __siena_register_masks[] = {
573 	0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
574 	0x000103FF, 0x00000000, 0x00000000, 0x00000000,
575 	0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
576 	0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
577 	0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
578 	0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
579 	0x00000003, 0x00000000, 0x00000000, 0x00000000,
580 	0x000003FF, 0x00000000, 0x00000000, 0x00000000,
581 	0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
582 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
583 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
584 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
585 	0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
586 };
587 
588 static siena_register_set_t __siena_tables[] = {
589 	{ FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
590 	    FR_AZ_RX_FILTER_TBL0_ROWS },
591 	{ FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
592 	    FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
593 	{ FR_AZ_RX_DESC_PTR_TBL_OFST,
594 	    FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
595 	{ FR_AZ_TX_DESC_PTR_TBL_OFST,
596 	    FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
597 	{ FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
598 	{ FR_CZ_TX_FILTER_TBL0_OFST,
599 	    FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
600 	{ FR_CZ_TX_MAC_FILTER_TBL0_OFST,
601 	    FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
602 };
603 
604 static const uint32_t __siena_table_masks[] = {
605 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
606 	0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
607 	0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
608 	0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
609 	0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
610 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
611 	0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
612 };
613 
614 	__checkReturn	efx_rc_t
615 siena_nic_test_registers(
616 	__in		efx_nic_t *enp,
617 	__in		siena_register_set_t *rsp,
618 	__in		size_t count)
619 {
620 	unsigned int bit;
621 	efx_oword_t original;
622 	efx_oword_t reg;
623 	efx_oword_t buf;
624 	efx_rc_t rc;
625 
626 	while (count > 0) {
627 		/* This function is only suitable for registers */
628 		EFSYS_ASSERT(rsp->rows == 1);
629 
630 		/* bit sweep on and off */
631 		EFSYS_BAR_READO(enp->en_esbp, rsp->address, &original,
632 			    B_TRUE);
633 		for (bit = 0; bit < 128; bit++) {
634 			/* Is this bit in the mask? */
635 			if (~(rsp->mask.eo_u32[bit >> 5]) & (1 << bit))
636 				continue;
637 
638 			/* Test this bit can be set in isolation */
639 			reg = original;
640 			EFX_AND_OWORD(reg, rsp->mask);
641 			EFX_SET_OWORD_BIT(reg, bit);
642 
643 			EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &reg,
644 				    B_TRUE);
645 			EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf,
646 				    B_TRUE);
647 
648 			EFX_AND_OWORD(buf, rsp->mask);
649 			if (memcmp(&reg, &buf, sizeof (reg))) {
650 				rc = EIO;
651 				goto fail1;
652 			}
653 
654 			/* Test this bit can be cleared in isolation */
655 			EFX_OR_OWORD(reg, rsp->mask);
656 			EFX_CLEAR_OWORD_BIT(reg, bit);
657 
658 			EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &reg,
659 				    B_TRUE);
660 			EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf,
661 				    B_TRUE);
662 
663 			EFX_AND_OWORD(buf, rsp->mask);
664 			if (memcmp(&reg, &buf, sizeof (reg))) {
665 				rc = EIO;
666 				goto fail2;
667 			}
668 		}
669 
670 		/* Restore the old value */
671 		EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original,
672 			    B_TRUE);
673 
674 		--count;
675 		++rsp;
676 	}
677 
678 	return (0);
679 
680 fail2:
681 	EFSYS_PROBE(fail2);
682 fail1:
683 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
684 
685 	/* Restore the old value */
686 	EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, B_TRUE);
687 
688 	return (rc);
689 }
690 
691 	__checkReturn	efx_rc_t
692 siena_nic_test_tables(
693 	__in		efx_nic_t *enp,
694 	__in		siena_register_set_t *rsp,
695 	__in		efx_pattern_type_t pattern,
696 	__in		size_t count)
697 {
698 	efx_sram_pattern_fn_t func;
699 	unsigned int index;
700 	unsigned int address;
701 	efx_oword_t reg;
702 	efx_oword_t buf;
703 	efx_rc_t rc;
704 
705 	EFSYS_ASSERT(pattern < EFX_PATTERN_NTYPES);
706 	func = __efx_sram_pattern_fns[pattern];
707 
708 	while (count > 0) {
709 		/* Write */
710 		address = rsp->address;
711 		for (index = 0; index < rsp->rows; ++index) {
712 			func(2 * index + 0, B_FALSE, &reg.eo_qword[0]);
713 			func(2 * index + 1, B_FALSE, &reg.eo_qword[1]);
714 			EFX_AND_OWORD(reg, rsp->mask);
715 			EFSYS_BAR_WRITEO(enp->en_esbp, address, &reg, B_TRUE);
716 
717 			address += rsp->step;
718 		}
719 
720 		/* Read */
721 		address = rsp->address;
722 		for (index = 0; index < rsp->rows; ++index) {
723 			func(2 * index + 0, B_FALSE, &reg.eo_qword[0]);
724 			func(2 * index + 1, B_FALSE, &reg.eo_qword[1]);
725 			EFX_AND_OWORD(reg, rsp->mask);
726 			EFSYS_BAR_READO(enp->en_esbp, address, &buf, B_TRUE);
727 			if (memcmp(&reg, &buf, sizeof (reg))) {
728 				rc = EIO;
729 				goto fail1;
730 			}
731 
732 			address += rsp->step;
733 		}
734 
735 		++rsp;
736 		--count;
737 	}
738 
739 	return (0);
740 
741 fail1:
742 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
743 
744 	return (rc);
745 }
746 
747 
748 	__checkReturn	efx_rc_t
749 siena_nic_register_test(
750 	__in		efx_nic_t *enp)
751 {
752 	siena_register_set_t *rsp;
753 	const uint32_t *dwordp;
754 	unsigned int nitems;
755 	unsigned int count;
756 	efx_rc_t rc;
757 
758 	/* Fill out the register mask entries */
759 	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
760 		    == EFX_ARRAY_SIZE(__siena_registers) * 4);
761 
762 	nitems = EFX_ARRAY_SIZE(__siena_registers);
763 	dwordp = __siena_register_masks;
764 	for (count = 0; count < nitems; ++count) {
765 		rsp = __siena_registers + count;
766 		rsp->mask.eo_u32[0] = *dwordp++;
767 		rsp->mask.eo_u32[1] = *dwordp++;
768 		rsp->mask.eo_u32[2] = *dwordp++;
769 		rsp->mask.eo_u32[3] = *dwordp++;
770 	}
771 
772 	/* Fill out the register table entries */
773 	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
774 		    == EFX_ARRAY_SIZE(__siena_tables) * 4);
775 
776 	nitems = EFX_ARRAY_SIZE(__siena_tables);
777 	dwordp = __siena_table_masks;
778 	for (count = 0; count < nitems; ++count) {
779 		rsp = __siena_tables + count;
780 		rsp->mask.eo_u32[0] = *dwordp++;
781 		rsp->mask.eo_u32[1] = *dwordp++;
782 		rsp->mask.eo_u32[2] = *dwordp++;
783 		rsp->mask.eo_u32[3] = *dwordp++;
784 	}
785 
786 	if ((rc = siena_nic_test_registers(enp, __siena_registers,
787 	    EFX_ARRAY_SIZE(__siena_registers))) != 0)
788 		goto fail1;
789 
790 	if ((rc = siena_nic_test_tables(enp, __siena_tables,
791 	    EFX_PATTERN_BYTE_ALTERNATE,
792 	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
793 		goto fail2;
794 
795 	if ((rc = siena_nic_test_tables(enp, __siena_tables,
796 	    EFX_PATTERN_BYTE_CHANGING,
797 	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
798 		goto fail3;
799 
800 	if ((rc = siena_nic_test_tables(enp, __siena_tables,
801 	    EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
802 		goto fail4;
803 
804 	return (0);
805 
806 fail4:
807 	EFSYS_PROBE(fail4);
808 fail3:
809 	EFSYS_PROBE(fail3);
810 fail2:
811 	EFSYS_PROBE(fail2);
812 fail1:
813 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
814 
815 	return (rc);
816 }
817 
818 #endif	/* EFSYS_OPT_DIAG */
819 
820 #endif	/* EFSYS_OPT_SIENA */
821