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