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