xref: /freebsd/sys/dev/sfxge/common/siena_nic.c (revision b740c88bfb6453416926271c089262e7164dace3)
1 /*-
2  * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28 
29 #include "efsys.h"
30 #include "efx.h"
31 #include "efx_impl.h"
32 
33 #if EFSYS_OPT_SIENA
34 
35 static	__checkReturn		int
36 siena_nic_get_partn_mask(
37 	__in			efx_nic_t *enp,
38 	__out			unsigned int *maskp)
39 {
40 	efx_mcdi_req_t req;
41 	uint8_t outbuf[MC_CMD_NVRAM_TYPES_OUT_LEN];
42 	int rc;
43 
44 	req.emr_cmd = MC_CMD_NVRAM_TYPES;
45 	EFX_STATIC_ASSERT(MC_CMD_NVRAM_TYPES_IN_LEN == 0);
46 	req.emr_in_buf = NULL;
47 	req.emr_in_length = 0;
48 	req.emr_out_buf = outbuf;
49 	req.emr_out_length = sizeof (outbuf);
50 
51 	efx_mcdi_execute(enp, &req);
52 
53 	if (req.emr_rc != 0) {
54 		rc = req.emr_rc;
55 		goto fail1;
56 	}
57 
58 	if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
59 		rc = EMSGSIZE;
60 		goto fail2;
61 	}
62 
63 	*maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
64 
65 	return (0);
66 
67 fail2:
68 	EFSYS_PROBE(fail2);
69 fail1:
70 	EFSYS_PROBE1(fail1, int, rc);
71 
72 	return (rc);
73 }
74 
75 static	__checkReturn	int
76 siena_nic_exit_assertion_handler(
77 	__in		efx_nic_t *enp)
78 {
79 	efx_mcdi_req_t req;
80 	uint8_t payload[MC_CMD_REBOOT_IN_LEN];
81 	int rc;
82 
83 	req.emr_cmd = MC_CMD_REBOOT;
84 	req.emr_in_buf = payload;
85 	req.emr_in_length = MC_CMD_REBOOT_IN_LEN;
86 	EFX_STATIC_ASSERT(MC_CMD_REBOOT_OUT_LEN == 0);
87 	req.emr_out_buf = NULL;
88 	req.emr_out_length = 0;
89 
90 	MCDI_IN_SET_DWORD(req, REBOOT_IN_FLAGS,
91 			    MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION);
92 
93 	efx_mcdi_execute(enp, &req);
94 
95 	if (req.emr_rc != 0 && req.emr_rc != EIO) {
96 		rc = req.emr_rc;
97 		goto fail1;
98 	}
99 
100 	return (0);
101 
102 fail1:
103 	EFSYS_PROBE1(fail1, int, rc);
104 
105 	return (rc);
106 }
107 
108 static	__checkReturn	int
109 siena_nic_read_assertion(
110 	__in		efx_nic_t *enp)
111 {
112 	efx_mcdi_req_t req;
113 	uint8_t payload[MAX(MC_CMD_GET_ASSERTS_IN_LEN,
114 			    MC_CMD_GET_ASSERTS_OUT_LEN)];
115 	const char *reason;
116 	unsigned int flags;
117 	unsigned int index;
118 	unsigned int ofst;
119 	int retry;
120 	int rc;
121 
122 	/*
123 	 * Before we attempt to chat to the MC, we should verify that the MC
124 	 * isn't in it's assertion handler, either due to a previous reboot,
125 	 * or because we're reinitializing due to an eec_exception().
126 	 *
127 	 * Use GET_ASSERTS to read any assertion state that may be present.
128 	 * Retry this command twice. Once because a boot-time assertion failure
129 	 * might cause the 1st MCDI request to fail. And once again because
130 	 * we might race with siena_nic_exit_assertion_handler() running on the
131 	 * other port.
132 	 */
133 	retry = 2;
134 	do {
135 		req.emr_cmd = MC_CMD_GET_ASSERTS;
136 		req.emr_in_buf = payload;
137 		req.emr_in_length = MC_CMD_GET_ASSERTS_IN_LEN;
138 		req.emr_out_buf = payload;
139 		req.emr_out_length = MC_CMD_GET_ASSERTS_OUT_LEN;
140 
141 		MCDI_IN_SET_DWORD(req, GET_ASSERTS_IN_CLEAR, 1);
142 		efx_mcdi_execute(enp, &req);
143 
144 	} while ((req.emr_rc == EINTR || req.emr_rc == EIO) && retry-- > 0);
145 
146 	if (req.emr_rc != 0) {
147 		rc = req.emr_rc;
148 		goto fail1;
149 	}
150 
151 	if (req.emr_out_length_used < MC_CMD_GET_ASSERTS_OUT_LEN) {
152 		rc = EMSGSIZE;
153 		goto fail2;
154 	}
155 
156 	/* Print out any assertion state recorded */
157 	flags = MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_GLOBAL_FLAGS);
158 	if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS)
159 		return (0);
160 
161 	reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL)
162 		? "system-level assertion"
163 		: (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL)
164 		? "thread-level assertion"
165 		: (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED)
166 		? "watchdog reset"
167 		: "unknown assertion";
168 	EFSYS_PROBE3(mcpu_assertion,
169 	    const char *, reason, unsigned int,
170 	    MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_SAVED_PC_OFFS),
171 	    unsigned int,
172 	    MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_THREAD_OFFS));
173 
174 	/* Print out the registers */
175 	ofst = MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST;
176 	for (index = 1; index < 32; index++) {
177 		EFSYS_PROBE2(mcpu_register, unsigned int, index, unsigned int,
178 			    EFX_DWORD_FIELD(*MCDI_OUT(req, efx_dword_t, ofst),
179 					    EFX_DWORD_0));
180 		ofst += sizeof (efx_dword_t);
181 	}
182 	EFSYS_ASSERT(ofst <= MC_CMD_GET_ASSERTS_OUT_LEN);
183 
184 	return (0);
185 
186 fail2:
187 	EFSYS_PROBE(fail2);
188 fail1:
189 	EFSYS_PROBE1(fail1, int, rc);
190 
191 	return (rc);
192 }
193 
194 static	__checkReturn	int
195 siena_nic_attach(
196 	__in		efx_nic_t *enp,
197 	__in		boolean_t attach)
198 {
199 	efx_mcdi_req_t req;
200 	uint8_t payload[MC_CMD_DRV_ATTACH_IN_LEN];
201 	int rc;
202 
203 	req.emr_cmd = MC_CMD_DRV_ATTACH;
204 	req.emr_in_buf = payload;
205 	req.emr_in_length = MC_CMD_DRV_ATTACH_IN_LEN;
206 	req.emr_out_buf = NULL;
207 	req.emr_out_length = 0;
208 
209 	MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_NEW_STATE, attach ? 1 : 0);
210 	MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_UPDATE, 1);
211 
212 	efx_mcdi_execute(enp, &req);
213 
214 	if (req.emr_rc != 0) {
215 		rc = req.emr_rc;
216 		goto fail1;
217 	}
218 
219 	if (req.emr_out_length_used < MC_CMD_DRV_ATTACH_OUT_LEN) {
220 		rc = EMSGSIZE;
221 		goto fail2;
222 	}
223 
224 	return (0);
225 
226 fail2:
227 	EFSYS_PROBE(fail2);
228 fail1:
229 	EFSYS_PROBE1(fail1, int, rc);
230 
231 	return (rc);
232 }
233 
234 #if EFSYS_OPT_PCIE_TUNE
235 
236 	__checkReturn	int
237 siena_nic_pcie_extended_sync(
238 	__in		efx_nic_t *enp)
239 {
240 	uint8_t inbuf[MC_CMD_WORKAROUND_IN_LEN];
241 	efx_mcdi_req_t req;
242 	int rc;
243 
244 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
245 
246 	req.emr_cmd = MC_CMD_WORKAROUND;
247 	req.emr_in_buf = inbuf;
248 	req.emr_in_length = sizeof (inbuf);
249 	EFX_STATIC_ASSERT(MC_CMD_WORKAROUND_OUT_LEN == 0);
250 	req.emr_out_buf = NULL;
251 	req.emr_out_length = 0;
252 
253 	MCDI_IN_SET_DWORD(req, WORKAROUND_IN_TYPE, MC_CMD_WORKAROUND_BUG17230);
254 	MCDI_IN_SET_DWORD(req, WORKAROUND_IN_ENABLED, 1);
255 
256 	efx_mcdi_execute(enp, &req);
257 
258 	if (req.emr_rc != 0) {
259 		rc = req.emr_rc;
260 		goto fail1;
261 	}
262 
263 	return (0);
264 
265 fail1:
266 	EFSYS_PROBE1(fail1, int, rc);
267 
268 	return (rc);
269 }
270 
271 #endif	/* EFSYS_OPT_PCIE_TUNE */
272 
273 static	__checkReturn	int
274 siena_board_cfg(
275 	__in		efx_nic_t *enp)
276 {
277 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
278 	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
279 	uint8_t outbuf[MAX(MC_CMD_GET_BOARD_CFG_OUT_LENMIN,
280 		    MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN)];
281 	efx_mcdi_req_t req;
282 	uint8_t *mac_addr;
283 	efx_dword_t *capabilities;
284 	int rc;
285 
286 	/* Board configuration */
287 	req.emr_cmd = MC_CMD_GET_BOARD_CFG;
288 	EFX_STATIC_ASSERT(MC_CMD_GET_BOARD_CFG_IN_LEN == 0);
289 	req.emr_in_buf = NULL;
290 	req.emr_in_length = 0;
291 	req.emr_out_buf = outbuf;
292 	req.emr_out_length = MC_CMD_GET_BOARD_CFG_OUT_LENMIN;
293 
294 	efx_mcdi_execute(enp, &req);
295 
296 	if (req.emr_rc != 0) {
297 		rc = req.emr_rc;
298 		goto fail1;
299 	}
300 
301 	if (req.emr_out_length_used < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) {
302 		rc = EMSGSIZE;
303 		goto fail2;
304 	}
305 
306 	if (emip->emi_port == 1) {
307 		mac_addr = MCDI_OUT2(req, uint8_t,
308 			    GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0);
309 		capabilities = MCDI_OUT2(req, efx_dword_t,
310 			    GET_BOARD_CFG_OUT_CAPABILITIES_PORT0);
311 	} else {
312 		mac_addr = MCDI_OUT2(req, uint8_t,
313 			    GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1);
314 		capabilities = MCDI_OUT2(req, efx_dword_t,
315 			    GET_BOARD_CFG_OUT_CAPABILITIES_PORT1);
316 	}
317 	EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
318 
319 	encp->enc_board_type = MCDI_OUT_DWORD(req,
320 				    GET_BOARD_CFG_OUT_BOARD_TYPE);
321 
322 	/* Additional capabilities */
323 	encp->enc_clk_mult = 1;
324 	if (MCDI_CMD_DWORD_FIELD(capabilities, CAPABILITIES_TURBO)) {
325 		enp->en_features |= EFX_FEATURE_TURBO;
326 
327 		if (MCDI_CMD_DWORD_FIELD(capabilities,
328 		    CAPABILITIES_TURBO_ACTIVE))
329 			encp->enc_clk_mult = 2;
330 	}
331 
332 	encp->enc_evq_timer_quantum_ns =
333 		EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
334 	encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
335 		FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
336 
337 	/* Resource limits */
338 	req.emr_cmd = MC_CMD_GET_RESOURCE_LIMITS;
339 	EFX_STATIC_ASSERT(MC_CMD_GET_RESOURCE_LIMITS_IN_LEN == 0);
340 	req.emr_in_buf = NULL;
341 	req.emr_in_length = 0;
342 	req.emr_out_buf = outbuf;
343 	req.emr_out_length = MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN;
344 
345 	efx_mcdi_execute(enp, &req);
346 
347 	if (req.emr_rc == 0) {
348 		if (req.emr_out_length_used <
349 		    MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN) {
350 			rc = EMSGSIZE;
351 			goto fail3;
352 		}
353 
354 		encp->enc_evq_limit = MCDI_OUT_DWORD(req,
355 		    GET_RESOURCE_LIMITS_OUT_EVQ);
356 		encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET,
357 		    MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_TXQ));
358 		encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET,
359 		    MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_RXQ));
360 	} else if (req.emr_rc == ENOTSUP) {
361 		encp->enc_evq_limit = 1024;
362 		encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
363 		encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
364 	} else {
365 		rc = req.emr_rc;
366 		goto fail4;
367 	}
368 
369 	encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
370 	    (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) -
371 	    (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
372 
373 	return (0);
374 
375 fail4:
376 	EFSYS_PROBE(fail4);
377 fail3:
378 	EFSYS_PROBE(fail3);
379 fail2:
380 	EFSYS_PROBE(fail2);
381 fail1:
382 	EFSYS_PROBE1(fail1, int, rc);
383 
384 	return (rc);
385 }
386 
387 static	__checkReturn	int
388 siena_phy_cfg(
389 	__in		efx_nic_t *enp)
390 {
391 	efx_port_t *epp = &(enp->en_port);
392 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
393 	efx_mcdi_req_t req;
394 	uint8_t outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN];
395 	int rc;
396 
397 	req.emr_cmd = MC_CMD_GET_PHY_CFG;
398 	EFX_STATIC_ASSERT(MC_CMD_GET_PHY_CFG_IN_LEN == 0);
399 	req.emr_in_buf = NULL;
400 	req.emr_in_length = 0;
401 	req.emr_out_buf = outbuf;
402 	req.emr_out_length = sizeof (outbuf);
403 
404 	efx_mcdi_execute(enp, &req);
405 
406 	if (req.emr_rc != 0) {
407 		rc = req.emr_rc;
408 		goto fail1;
409 	}
410 
411 	if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN) {
412 		rc = EMSGSIZE;
413 		goto fail2;
414 	}
415 
416 	encp->enc_phy_type = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_TYPE);
417 #if EFSYS_OPT_NAMES
418 	(void) strncpy(encp->enc_phy_name,
419 		MCDI_OUT2(req, char, GET_PHY_CFG_OUT_NAME),
420 		MIN(sizeof (encp->enc_phy_name) - 1,
421 		    MC_CMD_GET_PHY_CFG_OUT_NAME_LEN));
422 #endif	/* EFSYS_OPT_NAMES */
423 	(void) memset(encp->enc_phy_revision, 0,
424 	    sizeof (encp->enc_phy_revision));
425 	memcpy(encp->enc_phy_revision,
426 		MCDI_OUT2(req, char, GET_PHY_CFG_OUT_REVISION),
427 		MIN(sizeof (encp->enc_phy_revision) - 1,
428 		    MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN));
429 #if EFSYS_OPT_PHY_LED_CONTROL
430 	encp->enc_led_mask = ((1 << EFX_PHY_LED_DEFAULT) |
431 			    (1 << EFX_PHY_LED_OFF) |
432 			    (1 << EFX_PHY_LED_ON));
433 #endif	/* EFSYS_OPT_PHY_LED_CONTROL */
434 
435 #if EFSYS_OPT_PHY_PROPS
436 	encp->enc_phy_nprops  = 0;
437 #endif	/* EFSYS_OPT_PHY_PROPS */
438 
439 	/* Get the media type of the fixed port, if recognised. */
440 	EFX_STATIC_ASSERT(MC_CMD_MEDIA_XAUI == EFX_PHY_MEDIA_XAUI);
441 	EFX_STATIC_ASSERT(MC_CMD_MEDIA_CX4 == EFX_PHY_MEDIA_CX4);
442 	EFX_STATIC_ASSERT(MC_CMD_MEDIA_KX4 == EFX_PHY_MEDIA_KX4);
443 	EFX_STATIC_ASSERT(MC_CMD_MEDIA_XFP == EFX_PHY_MEDIA_XFP);
444 	EFX_STATIC_ASSERT(MC_CMD_MEDIA_SFP_PLUS == EFX_PHY_MEDIA_SFP_PLUS);
445 	EFX_STATIC_ASSERT(MC_CMD_MEDIA_BASE_T == EFX_PHY_MEDIA_BASE_T);
446 	epp->ep_fixed_port_type =
447 		MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_MEDIA_TYPE);
448 	if (epp->ep_fixed_port_type >= EFX_PHY_MEDIA_NTYPES)
449 		epp->ep_fixed_port_type = EFX_PHY_MEDIA_INVALID;
450 
451 	epp->ep_phy_cap_mask =
452 		MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_SUPPORTED_CAP);
453 #if EFSYS_OPT_PHY_FLAGS
454 	encp->enc_phy_flags_mask = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_FLAGS);
455 #endif	/* EFSYS_OPT_PHY_FLAGS */
456 
457 	encp->enc_port = (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_PRT);
458 
459 	/* Populate internal state */
460 	encp->enc_siena_channel =
461 		(uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_CHANNEL);
462 
463 #if EFSYS_OPT_PHY_STATS
464 	encp->enc_siena_phy_stat_mask =
465 		MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_STATS_MASK);
466 
467 	/* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
468 	siena_phy_decode_stats(enp, encp->enc_siena_phy_stat_mask,
469 			    NULL, &encp->enc_phy_stat_mask, NULL);
470 #endif	/* EFSYS_OPT_PHY_STATS */
471 
472 #if EFSYS_OPT_PHY_BIST
473 	encp->enc_bist_mask = 0;
474 	if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
475 	    GET_PHY_CFG_OUT_BIST_CABLE_SHORT))
476 		encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_SHORT);
477 	if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
478 	    GET_PHY_CFG_OUT_BIST_CABLE_LONG))
479 		encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_LONG);
480 	if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
481 	    GET_PHY_CFG_OUT_BIST))
482 		encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_NORMAL);
483 #endif	/* EFSYS_OPT_PHY_BIST */
484 
485 	return (0);
486 
487 fail2:
488 	EFSYS_PROBE(fail2);
489 fail1:
490 	EFSYS_PROBE1(fail1, int, rc);
491 
492 	return (rc);
493 }
494 
495 #if EFSYS_OPT_LOOPBACK
496 
497 static	__checkReturn	int
498 siena_loopback_cfg(
499 	__in		efx_nic_t *enp)
500 {
501 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
502 	efx_mcdi_req_t req;
503 	uint8_t outbuf[MC_CMD_GET_LOOPBACK_MODES_OUT_LEN];
504 	int rc;
505 
506 	req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES;
507 	EFX_STATIC_ASSERT(MC_CMD_GET_LOOPBACK_MODES_IN_LEN == 0);
508 	req.emr_in_buf = NULL;
509 	req.emr_in_length = 0;
510 	req.emr_out_buf = outbuf;
511 	req.emr_out_length = sizeof (outbuf);
512 
513 	efx_mcdi_execute(enp, &req);
514 
515 	if (req.emr_rc != 0) {
516 		rc = req.emr_rc;
517 		goto fail1;
518 	}
519 
520 	if (req.emr_out_length_used < MC_CMD_GET_LOOPBACK_MODES_OUT_LEN) {
521 		rc = EMSGSIZE;
522 		goto fail2;
523 	}
524 
525 	/*
526 	 * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree
527 	 * in siena_phy.c:siena_phy_get_link()
528 	 */
529 	encp->enc_loopback_types[EFX_LINK_100FDX] = EFX_LOOPBACK_MASK &
530 	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_100M) &
531 	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
532 	encp->enc_loopback_types[EFX_LINK_1000FDX] = EFX_LOOPBACK_MASK &
533 	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_1G) &
534 	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
535 	encp->enc_loopback_types[EFX_LINK_10000FDX] = EFX_LOOPBACK_MASK &
536 	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_10G) &
537 	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
538 	encp->enc_loopback_types[EFX_LINK_UNKNOWN] =
539 	    (1 << EFX_LOOPBACK_OFF) |
540 	    encp->enc_loopback_types[EFX_LINK_100FDX] |
541 	    encp->enc_loopback_types[EFX_LINK_1000FDX] |
542 	    encp->enc_loopback_types[EFX_LINK_10000FDX];
543 
544 	return (0);
545 
546 fail2:
547 	EFSYS_PROBE(fail2);
548 fail1:
549 	EFSYS_PROBE1(fail1, int, rc);
550 
551 	return (rc);
552 }
553 
554 #endif	/* EFSYS_OPT_LOOPBACK */
555 
556 #if EFSYS_OPT_MON_STATS
557 
558 static	__checkReturn	int
559 siena_monitor_cfg(
560 	__in		efx_nic_t *enp)
561 {
562 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
563 	efx_mcdi_req_t req;
564 	uint8_t outbuf[MCDI_CTL_SDU_LEN_MAX];
565 	int rc;
566 
567 	req.emr_cmd = MC_CMD_SENSOR_INFO;
568 	EFX_STATIC_ASSERT(MC_CMD_SENSOR_INFO_IN_LEN == 0);
569 	req.emr_in_buf = NULL;
570 	req.emr_in_length = 0;
571 	req.emr_out_buf = outbuf;
572 	req.emr_out_length = sizeof (outbuf);
573 
574 	efx_mcdi_execute(enp, &req);
575 
576 	if (req.emr_rc != 0) {
577 		rc = req.emr_rc;
578 		goto fail1;
579 	}
580 
581 	if (req.emr_out_length_used < MC_CMD_SENSOR_INFO_OUT_MASK_OFST + 4) {
582 		rc = EMSGSIZE;
583 		goto fail2;
584 	}
585 
586 	encp->enc_siena_mon_stat_mask =
587 		MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK);
588 	encp->enc_mon_type = EFX_MON_SFC90X0;
589 
590 	siena_mon_decode_stats(enp, encp->enc_siena_mon_stat_mask,
591 			    NULL, &(encp->enc_mon_stat_mask), NULL);
592 
593 	return (0);
594 
595 fail2:
596 	EFSYS_PROBE(fail2);
597 fail1:
598 	EFSYS_PROBE1(fail1, int, rc);
599 
600 	return (rc);
601 }
602 
603 #endif	/* EFSYS_OPT_MON_STATS */
604 
605 	__checkReturn	int
606 siena_nic_probe(
607 	__in		efx_nic_t *enp)
608 {
609 	efx_port_t *epp = &(enp->en_port);
610 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
611 	siena_link_state_t sls;
612 	unsigned int mask;
613 	int rc;
614 
615 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
616 
617 	/* Read clear any assertion state */
618 	if ((rc = siena_nic_read_assertion(enp)) != 0)
619 		goto fail1;
620 
621 	/* Exit the assertion handler */
622 	if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
623 		goto fail2;
624 
625 	/* Wrestle control from the BMC */
626 	if ((rc = siena_nic_attach(enp, B_TRUE)) != 0)
627 		goto fail3;
628 
629 	if ((rc = siena_board_cfg(enp)) != 0)
630 		goto fail4;
631 
632 	if ((rc = siena_phy_cfg(enp)) != 0)
633 		goto fail5;
634 
635 	/* Obtain the default PHY advertised capabilities */
636 	if ((rc = siena_nic_reset(enp)) != 0)
637 		goto fail6;
638 	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
639 		goto fail7;
640 	epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
641 	epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
642 
643 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
644 	if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
645 		goto fail8;
646 	enp->en_u.siena.enu_partn_mask = mask;
647 #endif
648 
649 #if EFSYS_OPT_MAC_STATS
650 	/* Wipe the MAC statistics */
651 	if ((rc = siena_mac_stats_clear(enp)) != 0)
652 		goto fail9;
653 #endif
654 
655 #if EFSYS_OPT_LOOPBACK
656 	if ((rc = siena_loopback_cfg(enp)) != 0)
657 		goto fail10;
658 #endif
659 
660 #if EFSYS_OPT_MON_STATS
661 	if ((rc = siena_monitor_cfg(enp)) != 0)
662 		goto fail11;
663 #endif
664 
665 	encp->enc_features = enp->en_features;
666 
667 	return (0);
668 
669 #if EFSYS_OPT_MON_STATS
670 fail11:
671 	EFSYS_PROBE(fail11);
672 #endif
673 #if EFSYS_OPT_LOOPBACK
674 fail10:
675 	EFSYS_PROBE(fail10);
676 #endif
677 #if EFSYS_OPT_MAC_STATS
678 fail9:
679 	EFSYS_PROBE(fail9);
680 #endif
681 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
682 fail8:
683 	EFSYS_PROBE(fail8);
684 #endif
685 fail7:
686 	EFSYS_PROBE(fail7);
687 fail6:
688 	EFSYS_PROBE(fail6);
689 fail5:
690 	EFSYS_PROBE(fail5);
691 fail4:
692 	EFSYS_PROBE(fail4);
693 fail3:
694 	EFSYS_PROBE(fail3);
695 fail2:
696 	EFSYS_PROBE(fail2);
697 fail1:
698 	EFSYS_PROBE1(fail1, int, rc);
699 
700 	return (rc);
701 }
702 
703 	__checkReturn	int
704 siena_nic_reset(
705 	__in		efx_nic_t *enp)
706 {
707 	efx_mcdi_req_t req;
708 	int rc;
709 
710 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
711 
712 	/* siena_nic_reset() is called to recover from BADASSERT failures. */
713 	if ((rc = siena_nic_read_assertion(enp)) != 0)
714 		goto fail1;
715 	if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
716 		goto fail2;
717 
718 	req.emr_cmd = MC_CMD_PORT_RESET;
719 	EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_IN_LEN == 0);
720 	req.emr_in_buf = NULL;
721 	req.emr_in_length = 0;
722 	EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_OUT_LEN == 0);
723 	req.emr_out_buf = NULL;
724 	req.emr_out_length = 0;
725 
726 	efx_mcdi_execute(enp, &req);
727 
728 	if (req.emr_rc != 0) {
729 		rc = req.emr_rc;
730 		goto fail3;
731 	}
732 
733 	return (0);
734 
735 fail3:
736 	EFSYS_PROBE(fail3);
737 fail2:
738 	EFSYS_PROBE(fail2);
739 fail1:
740 	EFSYS_PROBE1(fail1, int, rc);
741 
742 	return (0);
743 }
744 
745 static	__checkReturn	int
746 siena_nic_logging(
747 	__in		efx_nic_t *enp)
748 {
749 	efx_mcdi_req_t req;
750 	uint8_t payload[MC_CMD_LOG_CTRL_IN_LEN];
751 	int rc;
752 
753 	req.emr_cmd = MC_CMD_LOG_CTRL;
754 	req.emr_in_buf = payload;
755 	req.emr_in_length = MC_CMD_LOG_CTRL_IN_LEN;
756 	EFX_STATIC_ASSERT(MC_CMD_LOG_CTRL_OUT_LEN == 0);
757 	req.emr_out_buf = NULL;
758 	req.emr_out_length = 0;
759 
760 	MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST,
761 		    MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ);
762 	MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST_EVQ, 0);
763 
764 	efx_mcdi_execute(enp, &req);
765 
766 	if (req.emr_rc != 0) {
767 		rc = req.emr_rc;
768 		goto fail1;
769 	}
770 
771 	return (0);
772 
773 fail1:
774 	EFSYS_PROBE1(fail1, int, rc);
775 
776 	return (rc);
777 }
778 
779 static			void
780 siena_nic_rx_cfg(
781 	__in		efx_nic_t *enp)
782 {
783 	efx_oword_t oword;
784 
785 	/*
786 	 * RX_INGR_EN is always enabled on Siena, because we rely on
787 	 * the RX parser to be resiliant to missing SOP/EOP.
788 	 */
789 	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
790 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
791 	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
792 
793 	/* Disable parsing of additional 802.1Q in Q packets */
794 	EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
795 	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
796 	EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
797 }
798 
799 static			void
800 siena_nic_usrev_dis(
801 	__in		efx_nic_t *enp)
802 {
803 	efx_oword_t	oword;
804 
805 	EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
806 	EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
807 }
808 
809 	__checkReturn	int
810 siena_nic_init(
811 	__in		efx_nic_t *enp)
812 {
813 	int rc;
814 
815 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
816 
817 	if ((rc = siena_nic_logging(enp)) != 0)
818 		goto fail1;
819 
820 	siena_sram_init(enp);
821 
822 	/* Configure Siena's RX block */
823 	siena_nic_rx_cfg(enp);
824 
825 	/* Disable USR_EVents for now */
826 	siena_nic_usrev_dis(enp);
827 
828 	/* bug17057: Ensure set_link is called */
829 	if ((rc = siena_phy_reconfigure(enp)) != 0)
830 		goto fail2;
831 
832 	return (0);
833 
834 fail2:
835 	EFSYS_PROBE(fail2);
836 fail1:
837 	EFSYS_PROBE1(fail1, int, rc);
838 
839 	return (rc);
840 }
841 
842 			void
843 siena_nic_fini(
844 	__in		efx_nic_t *enp)
845 {
846 	_NOTE(ARGUNUSED(enp))
847 }
848 
849 			void
850 siena_nic_unprobe(
851 	__in		efx_nic_t *enp)
852 {
853 	(void) siena_nic_attach(enp, B_FALSE);
854 }
855 
856 #if EFSYS_OPT_DIAG
857 
858 static efx_register_set_t __cs	__siena_registers[] = {
859 	{ FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
860 	{ FR_CZ_USR_EV_CFG_OFST, 0, 1 },
861 	{ FR_AZ_RX_CFG_REG_OFST, 0, 1 },
862 	{ FR_AZ_TX_CFG_REG_OFST, 0, 1 },
863 	{ FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
864 	{ FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
865 	{ FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
866 	{ FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
867 	{ FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
868 	{ FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
869 	{ FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
870 	{ FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
871 	{ FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
872 };
873 
874 static const uint32_t __cs	__siena_register_masks[] = {
875 	0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
876 	0x000103FF, 0x00000000, 0x00000000, 0x00000000,
877 	0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
878 	0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
879 	0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
880 	0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
881 	0x00000003, 0x00000000, 0x00000000, 0x00000000,
882 	0x000003FF, 0x00000000, 0x00000000, 0x00000000,
883 	0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
884 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
885 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
886 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
887 	0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
888 };
889 
890 static efx_register_set_t __cs	__siena_tables[] = {
891 	{ FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
892 	    FR_AZ_RX_FILTER_TBL0_ROWS },
893 	{ FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
894 	    FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
895 	{ FR_AZ_RX_DESC_PTR_TBL_OFST,
896 	    FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
897 	{ FR_AZ_TX_DESC_PTR_TBL_OFST,
898 	    FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
899 	{ FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
900 	{ FR_CZ_TX_FILTER_TBL0_OFST,
901 	    FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
902 	{ FR_CZ_TX_MAC_FILTER_TBL0_OFST,
903 	    FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
904 };
905 
906 static const uint32_t __cs	__siena_table_masks[] = {
907 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
908 	0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
909 	0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
910 	0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
911 	0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
912 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
913 	0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
914 };
915 
916 	__checkReturn	int
917 siena_nic_register_test(
918 	__in		efx_nic_t *enp)
919 {
920 	efx_register_set_t *rsp;
921 	const uint32_t *dwordp;
922 	unsigned int nitems;
923 	unsigned int count;
924 	int rc;
925 
926 	/* Fill out the register mask entries */
927 	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
928 		    == EFX_ARRAY_SIZE(__siena_registers) * 4);
929 
930 	nitems = EFX_ARRAY_SIZE(__siena_registers);
931 	dwordp = __siena_register_masks;
932 	for (count = 0; count < nitems; ++count) {
933 		rsp = __siena_registers + count;
934 		rsp->mask.eo_u32[0] = *dwordp++;
935 		rsp->mask.eo_u32[1] = *dwordp++;
936 		rsp->mask.eo_u32[2] = *dwordp++;
937 		rsp->mask.eo_u32[3] = *dwordp++;
938 	}
939 
940 	/* Fill out the register table entries */
941 	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
942 		    == EFX_ARRAY_SIZE(__siena_tables) * 4);
943 
944 	nitems = EFX_ARRAY_SIZE(__siena_tables);
945 	dwordp = __siena_table_masks;
946 	for (count = 0; count < nitems; ++count) {
947 		rsp = __siena_tables + count;
948 		rsp->mask.eo_u32[0] = *dwordp++;
949 		rsp->mask.eo_u32[1] = *dwordp++;
950 		rsp->mask.eo_u32[2] = *dwordp++;
951 		rsp->mask.eo_u32[3] = *dwordp++;
952 	}
953 
954 	if ((rc = efx_nic_test_registers(enp, __siena_registers,
955 	    EFX_ARRAY_SIZE(__siena_registers))) != 0)
956 		goto fail1;
957 
958 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
959 	    EFX_PATTERN_BYTE_ALTERNATE,
960 	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
961 		goto fail2;
962 
963 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
964 	    EFX_PATTERN_BYTE_CHANGING,
965 	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
966 		goto fail3;
967 
968 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
969 	    EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
970 		goto fail4;
971 
972 	return (0);
973 
974 fail4:
975 	EFSYS_PROBE(fail4);
976 fail3:
977 	EFSYS_PROBE(fail3);
978 fail2:
979 	EFSYS_PROBE(fail2);
980 fail1:
981 	EFSYS_PROBE1(fail1, int, rc);
982 
983 	return (rc);
984 }
985 
986 #endif	/* EFSYS_OPT_DIAG */
987 
988 #endif	/* EFSYS_OPT_SIENA */
989