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