xref: /freebsd/sys/dev/sfxge/common/siena_nic.c (revision 86390f9444433b00296741d03d069a587ad8e4bf)
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_LEN,
280 		    MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN)];
281 	efx_mcdi_req_t req;
282 	uint8_t *src;
283 	int rc;
284 
285 	/* Board configuration */
286 	req.emr_cmd = MC_CMD_GET_BOARD_CFG;
287 	EFX_STATIC_ASSERT(MC_CMD_GET_BOARD_CFG_IN_LEN == 0);
288 	req.emr_in_buf = NULL;
289 	req.emr_in_length = 0;
290 	req.emr_out_buf = outbuf;
291 	req.emr_out_length = MC_CMD_GET_BOARD_CFG_OUT_LEN;
292 
293 	efx_mcdi_execute(enp, &req);
294 
295 	if (req.emr_rc != 0) {
296 		rc = req.emr_rc;
297 		goto fail1;
298 	}
299 
300 	if (req.emr_out_length_used < MC_CMD_GET_BOARD_CFG_OUT_LEN) {
301 		rc = EMSGSIZE;
302 		goto fail2;
303 	}
304 
305 	if (emip->emi_port == 1)
306 		src = MCDI_OUT2(req, uint8_t,
307 			    GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0);
308 	else
309 		src = MCDI_OUT2(req, uint8_t,
310 			    GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1);
311 	EFX_MAC_ADDR_COPY(encp->enc_mac_addr, src);
312 
313 	encp->enc_board_type = MCDI_OUT_DWORD(req,
314 				    GET_BOARD_CFG_OUT_BOARD_TYPE);
315 
316 	/* Resource limits */
317 	req.emr_cmd = MC_CMD_GET_RESOURCE_LIMITS;
318 	EFX_STATIC_ASSERT(MC_CMD_GET_RESOURCE_LIMITS_IN_LEN == 0);
319 	req.emr_in_buf = NULL;
320 	req.emr_in_length = 0;
321 	req.emr_out_buf = outbuf;
322 	req.emr_out_length = MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN;
323 
324 	efx_mcdi_execute(enp, &req);
325 
326 	if (req.emr_rc == 0) {
327 		if (req.emr_out_length_used < MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN) {
328 			rc = EMSGSIZE;
329 			goto fail3;
330 		}
331 
332 		encp->enc_evq_limit = MCDI_OUT_DWORD(req,
333 		    GET_RESOURCE_LIMITS_OUT_EVQ);
334 		encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET,
335 		    MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_TXQ));
336 		encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET,
337 		    MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_RXQ));
338 	} else if (req.emr_rc == ENOTSUP) {
339 		encp->enc_evq_limit = 1024;
340 		encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
341 		encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
342 	} else {
343 		rc = req.emr_rc;
344 		goto fail4;
345 	}
346 
347 	encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
348 	    (encp->enc_txq_limit * 16) - (encp->enc_rxq_limit * 64);
349 
350 	return (0);
351 
352 fail4:
353 	EFSYS_PROBE(fail4);
354 fail3:
355 	EFSYS_PROBE(fail3);
356 fail2:
357 	EFSYS_PROBE(fail2);
358 fail1:
359 	EFSYS_PROBE1(fail1, int, rc);
360 
361 	return (rc);
362 }
363 
364 static	__checkReturn	int
365 siena_phy_cfg(
366 	__in		efx_nic_t *enp)
367 {
368 	efx_port_t *epp = &(enp->en_port);
369 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
370 	efx_mcdi_req_t req;
371 	uint8_t outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN];
372 	int rc;
373 
374 	req.emr_cmd = MC_CMD_GET_PHY_CFG;
375 	EFX_STATIC_ASSERT(MC_CMD_GET_PHY_CFG_IN_LEN == 0);
376 	req.emr_in_buf = NULL;
377 	req.emr_in_length = 0;
378 	req.emr_out_buf = outbuf;
379 	req.emr_out_length = sizeof (outbuf);
380 
381 	efx_mcdi_execute(enp, &req);
382 
383 	if (req.emr_rc != 0) {
384 		rc = req.emr_rc;
385 		goto fail1;
386 	}
387 
388 	if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN) {
389 		rc = EMSGSIZE;
390 		goto fail2;
391 	}
392 
393 	encp->enc_phy_type = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_TYPE);
394 #if EFSYS_OPT_NAMES
395 	(void) strncpy(encp->enc_phy_name,
396 		MCDI_OUT2(req, char, GET_PHY_CFG_OUT_NAME),
397 		MIN(sizeof (encp->enc_phy_name) - 1,
398 		    MC_CMD_GET_PHY_CFG_OUT_NAME_LEN));
399 #endif	/* EFSYS_OPT_NAMES */
400 	(void) memset(encp->enc_phy_revision, 0,
401 	    sizeof (encp->enc_phy_revision));
402 	memcpy(encp->enc_phy_revision,
403 		MCDI_OUT2(req, char, GET_PHY_CFG_OUT_REVISION),
404 		MIN(sizeof (encp->enc_phy_revision) - 1,
405 		    MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN));
406 #if EFSYS_OPT_PHY_LED_CONTROL
407 	encp->enc_led_mask = ((1 << EFX_PHY_LED_DEFAULT) |
408 			    (1 << EFX_PHY_LED_OFF) |
409 			    (1 << EFX_PHY_LED_ON));
410 #endif	/* EFSYS_OPT_PHY_LED_CONTROL */
411 
412 #if EFSYS_OPT_PHY_PROPS
413 	encp->enc_phy_nprops  = 0;
414 #endif	/* EFSYS_OPT_PHY_PROPS */
415 
416 	/* Get the media type of the fixed port, if recognised. */
417 	EFX_STATIC_ASSERT(MC_CMD_MEDIA_XAUI == EFX_PHY_MEDIA_XAUI);
418 	EFX_STATIC_ASSERT(MC_CMD_MEDIA_CX4 == EFX_PHY_MEDIA_CX4);
419 	EFX_STATIC_ASSERT(MC_CMD_MEDIA_KX4 == EFX_PHY_MEDIA_KX4);
420 	EFX_STATIC_ASSERT(MC_CMD_MEDIA_XFP == EFX_PHY_MEDIA_XFP);
421 	EFX_STATIC_ASSERT(MC_CMD_MEDIA_SFP_PLUS == EFX_PHY_MEDIA_SFP_PLUS);
422 	EFX_STATIC_ASSERT(MC_CMD_MEDIA_BASE_T == EFX_PHY_MEDIA_BASE_T);
423 	epp->ep_fixed_port_type =
424 		MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_MEDIA_TYPE);
425 	if (epp->ep_fixed_port_type >= EFX_PHY_MEDIA_NTYPES)
426 		epp->ep_fixed_port_type = EFX_PHY_MEDIA_INVALID;
427 
428 	epp->ep_phy_cap_mask =
429 		MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_SUPPORTED_CAP);
430 #if EFSYS_OPT_PHY_FLAGS
431 	encp->enc_phy_flags_mask = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_FLAGS);
432 #endif	/* EFSYS_OPT_PHY_FLAGS */
433 
434 	encp->enc_port = (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_PRT);
435 
436 	/* Populate internal state */
437 	encp->enc_siena_channel =
438 		(uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_CHANNEL);
439 
440 #if EFSYS_OPT_PHY_STATS
441 	encp->enc_siena_phy_stat_mask =
442 		MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_STATS_MASK);
443 
444 	/* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
445 	siena_phy_decode_stats(enp, encp->enc_siena_phy_stat_mask,
446 			    NULL, &encp->enc_phy_stat_mask, NULL);
447 #endif	/* EFSYS_OPT_PHY_STATS */
448 
449 #if EFSYS_OPT_PHY_BIST
450 	encp->enc_bist_mask = 0;
451 	if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
452 	    GET_PHY_CFG_OUT_BIST_CABLE_SHORT))
453 		encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_SHORT);
454 	if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
455 	    GET_PHY_CFG_OUT_BIST_CABLE_LONG))
456 		encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_LONG);
457 	if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
458 	    GET_PHY_CFG_OUT_BIST))
459 		encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_NORMAL);
460 #endif	/* EFSYS_OPT_BIST */
461 
462 	return (0);
463 
464 fail2:
465 	EFSYS_PROBE(fail2);
466 fail1:
467 	EFSYS_PROBE1(fail1, int, rc);
468 
469 	return (rc);
470 }
471 
472 #if EFSYS_OPT_LOOPBACK
473 
474 static	__checkReturn	int
475 siena_loopback_cfg(
476 	__in		efx_nic_t *enp)
477 {
478 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
479 	efx_mcdi_req_t req;
480 	uint8_t outbuf[MC_CMD_GET_LOOPBACK_MODES_OUT_LEN];
481 	int rc;
482 
483 	req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES;
484 	EFX_STATIC_ASSERT(MC_CMD_GET_LOOPBACK_MODES_IN_LEN == 0);
485 	req.emr_in_buf = NULL;
486 	req.emr_in_length = 0;
487 	req.emr_out_buf = outbuf;
488 	req.emr_out_length = sizeof (outbuf);
489 
490 	efx_mcdi_execute(enp, &req);
491 
492 	if (req.emr_rc != 0) {
493 		rc = req.emr_rc;
494 		goto fail1;
495 	}
496 
497 	if (req.emr_out_length_used < MC_CMD_GET_LOOPBACK_MODES_OUT_LEN) {
498 		rc = EMSGSIZE;
499 		goto fail2;
500 	}
501 
502 	/*
503 	 * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree
504 	 * in siena_phy.c:siena_phy_get_link()
505 	 */
506 	encp->enc_loopback_types[EFX_LINK_100FDX] = EFX_LOOPBACK_MASK &
507 	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_100M) &
508 	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
509 	encp->enc_loopback_types[EFX_LINK_1000FDX] = EFX_LOOPBACK_MASK &
510 	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_1G) &
511 	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
512 	encp->enc_loopback_types[EFX_LINK_10000FDX] = EFX_LOOPBACK_MASK &
513 	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_10G) &
514 	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
515 	encp->enc_loopback_types[EFX_LINK_UNKNOWN] =
516 	    (1 << EFX_LOOPBACK_OFF) |
517 	    encp->enc_loopback_types[EFX_LINK_100FDX] |
518 	    encp->enc_loopback_types[EFX_LINK_1000FDX] |
519 	    encp->enc_loopback_types[EFX_LINK_10000FDX];
520 
521 	return (0);
522 
523 fail2:
524 	EFSYS_PROBE(fail2);
525 fail1:
526 	EFSYS_PROBE1(fail1, int, rc);
527 
528 	return (rc);
529 }
530 
531 #endif	/* EFSYS_OPT_LOOPBACK */
532 
533 #if EFSYS_OPT_MON_STATS
534 
535 static	__checkReturn	int
536 siena_monitor_cfg(
537 	__in		efx_nic_t *enp)
538 {
539 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
540 	efx_mcdi_req_t req;
541 	uint8_t outbuf[MCDI_CTL_SDU_LEN_MAX];
542 	int rc;
543 
544 	req.emr_cmd = MC_CMD_SENSOR_INFO;
545 	EFX_STATIC_ASSERT(MC_CMD_SENSOR_INFO_IN_LEN == 0);
546 	req.emr_in_buf = NULL;
547 	req.emr_in_length = 0;
548 	req.emr_out_buf = outbuf;
549 	req.emr_out_length = sizeof (outbuf);
550 
551 	efx_mcdi_execute(enp, &req);
552 
553 	if (req.emr_rc != 0) {
554 		rc = req.emr_rc;
555 		goto fail1;
556 	}
557 
558 	if (req.emr_out_length_used < MC_CMD_SENSOR_INFO_OUT_MASK_OFST + 4) {
559 		rc = EMSGSIZE;
560 		goto fail2;
561 	}
562 
563 	encp->enc_siena_mon_stat_mask =
564 		MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK);
565 	encp->enc_mon_type = EFX_MON_SFC90X0;
566 
567 	siena_mon_decode_stats(enp, encp->enc_siena_mon_stat_mask,
568 			    NULL, &(encp->enc_mon_stat_mask), NULL);
569 
570 	return (0);
571 
572 fail2:
573 	EFSYS_PROBE(fail2);
574 fail1:
575 	EFSYS_PROBE1(fail1, int, rc);
576 
577 	return (rc);
578 }
579 
580 #endif	/* EFSYS_OPT_MON_STATS */
581 
582 	__checkReturn	int
583 siena_nic_probe(
584 	__in		efx_nic_t *enp)
585 {
586 	efx_port_t *epp = &(enp->en_port);
587 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
588 	siena_link_state_t sls;
589 	unsigned int mask;
590 	int rc;
591 
592 	mask = 0;	/* XXX: pacify gcc */
593 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
594 
595 	/* Read clear any assertion state */
596 	if ((rc = siena_nic_read_assertion(enp)) != 0)
597 		goto fail1;
598 
599 	/* Exit the assertion handler */
600 	if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
601 		goto fail2;
602 
603 	/* Wrestle control from the BMC */
604 	if ((rc = siena_nic_attach(enp, B_TRUE)) != 0)
605 		goto fail3;
606 
607 	if ((rc = siena_board_cfg(enp)) != 0)
608 		goto fail4;
609 
610 	encp->enc_evq_moderation_max =
611 		EFX_EV_TIMER_QUANTUM << FRF_CZ_TIMER_VAL_WIDTH;
612 
613 	if ((rc = siena_phy_cfg(enp)) != 0)
614 		goto fail5;
615 
616 	/* Obtain the default PHY advertised capabilities */
617 	if ((rc = siena_nic_reset(enp)) != 0)
618 		goto fail6;
619 	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
620 		goto fail7;
621 	epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
622 	epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
623 
624 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
625 	if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
626 		goto fail8;
627 	enp->en_u.siena.enu_partn_mask = mask;
628 #endif
629 
630 #if EFSYS_OPT_MAC_STATS
631 	/* Wipe the MAC statistics */
632 	if ((rc = siena_mac_stats_clear(enp)) != 0)
633 		goto fail9;
634 #endif
635 
636 #if EFSYS_OPT_LOOPBACK
637 	if ((rc = siena_loopback_cfg(enp)) != 0)
638 		goto fail10;
639 #endif
640 
641 #if EFSYS_OPT_MON_STATS
642 	if ((rc = siena_monitor_cfg(enp)) != 0)
643 		goto fail11;
644 #endif
645 
646 	encp->enc_features = enp->en_features;
647 
648 	return (0);
649 
650 #if EFSYS_OPT_MON_STATS
651 fail11:
652 	EFSYS_PROBE(fail11);
653 #endif
654 #if EFSYS_OPT_LOOPBACK
655 fail10:
656 	EFSYS_PROBE(fail10);
657 #endif
658 #if EFSYS_OPT_MAC_STATS
659 fail9:
660 	EFSYS_PROBE(fail9);
661 #endif
662 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
663 fail8:
664 	EFSYS_PROBE(fail8);
665 #endif
666 fail7:
667 	EFSYS_PROBE(fail7);
668 fail6:
669 	EFSYS_PROBE(fail6);
670 fail5:
671 	EFSYS_PROBE(fail5);
672 fail4:
673 	EFSYS_PROBE(fail4);
674 fail3:
675 	EFSYS_PROBE(fail3);
676 fail2:
677 	EFSYS_PROBE(fail2);
678 fail1:
679 	EFSYS_PROBE1(fail1, int, rc);
680 
681 	return (rc);
682 }
683 
684 	__checkReturn	int
685 siena_nic_reset(
686 	__in		efx_nic_t *enp)
687 {
688 	efx_mcdi_req_t req;
689 	int rc;
690 
691 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
692 
693 	/* siena_nic_reset() is called to recover from BADASSERT failures. */
694 	if ((rc = siena_nic_read_assertion(enp)) != 0)
695 		goto fail1;
696 	if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
697 		goto fail2;
698 
699 	req.emr_cmd = MC_CMD_PORT_RESET;
700 	EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_IN_LEN == 0);
701 	req.emr_in_buf = NULL;
702 	req.emr_in_length = 0;
703 	EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_OUT_LEN == 0);
704 	req.emr_out_buf = NULL;
705 	req.emr_out_length = 0;
706 
707 	efx_mcdi_execute(enp, &req);
708 
709 	if (req.emr_rc != 0) {
710 		rc = req.emr_rc;
711 		goto fail3;
712 	}
713 
714 	return (0);
715 
716 fail3:
717 	EFSYS_PROBE(fail3);
718 fail2:
719 	EFSYS_PROBE(fail2);
720 fail1:
721 	EFSYS_PROBE1(fail1, int, rc);
722 
723 	return (0);
724 }
725 
726 static	__checkReturn	int
727 siena_nic_logging(
728 	__in		efx_nic_t *enp)
729 {
730 	efx_mcdi_req_t req;
731 	uint8_t payload[MC_CMD_LOG_CTRL_IN_LEN];
732 	int rc;
733 
734 	req.emr_cmd = MC_CMD_LOG_CTRL;
735 	req.emr_in_buf = payload;
736 	req.emr_in_length = MC_CMD_LOG_CTRL_IN_LEN;
737 	EFX_STATIC_ASSERT(MC_CMD_LOG_CTRL_OUT_LEN == 0);
738 	req.emr_out_buf = NULL;
739 	req.emr_out_length = 0;
740 
741 	MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST,
742 		    MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ);
743 	MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST_EVQ, 0);
744 
745 	efx_mcdi_execute(enp, &req);
746 
747 	if (req.emr_rc != 0) {
748 		rc = req.emr_rc;
749 		goto fail1;
750 	}
751 
752 	return (0);
753 
754 fail1:
755 	EFSYS_PROBE1(fail1, int, rc);
756 
757 	return (rc);
758 }
759 
760 static			void
761 siena_nic_rx_cfg(
762 	__in		efx_nic_t *enp)
763 {
764 	efx_oword_t oword;
765 
766 	/*
767 	 * RX_INGR_EN is always enabled on Siena, because we rely on
768 	 * the RX parser to be resiliant to missing SOP/EOP.
769 	 */
770 	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
771 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
772 	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
773 
774 	/* Disable parsing of additional 802.1Q in Q packets */
775 	EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
776 	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
777 	EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
778 }
779 
780 static			void
781 siena_nic_usrev_dis(
782 	__in		efx_nic_t *enp)
783 {
784 	efx_oword_t	oword;
785 
786 	EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
787 	EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
788 }
789 
790 	__checkReturn	int
791 siena_nic_init(
792 	__in		efx_nic_t *enp)
793 {
794 	int rc;
795 
796 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
797 
798 	if ((rc = siena_nic_logging(enp)) != 0)
799 		goto fail1;
800 
801 	siena_sram_init(enp);
802 
803 	/* Configure Siena's RX block */
804 	siena_nic_rx_cfg(enp);
805 
806 	/* Disable USR_EVents for now */
807 	siena_nic_usrev_dis(enp);
808 
809 	/* bug17057: Ensure set_link is called */
810 	if ((rc = siena_phy_reconfigure(enp)) != 0)
811 		goto fail2;
812 
813 	return (0);
814 
815 fail2:
816 	EFSYS_PROBE(fail2);
817 fail1:
818 	EFSYS_PROBE1(fail1, int, rc);
819 
820 	return (rc);
821 }
822 
823 			void
824 siena_nic_fini(
825 	__in		efx_nic_t *enp)
826 {
827 	_NOTE(ARGUNUSED(enp))
828 }
829 
830 			void
831 siena_nic_unprobe(
832 	__in		efx_nic_t *enp)
833 {
834 	(void) siena_nic_attach(enp, B_FALSE);
835 }
836 
837 #if EFSYS_OPT_DIAG
838 
839 static efx_register_set_t __cs	__siena_registers[] = {
840 	{ FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
841 	{ FR_CZ_USR_EV_CFG_OFST, 0, 1 },
842 	{ FR_AZ_RX_CFG_REG_OFST, 0, 1 },
843 	{ FR_AZ_TX_CFG_REG_OFST, 0, 1 },
844 	{ FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
845 	{ FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
846 	{ FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
847 	{ FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
848 	{ FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
849 	{ FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
850 	{ FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
851 	{ FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
852 	{ FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
853 };
854 
855 static const uint32_t __cs	__siena_register_masks[] = {
856 	0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
857 	0x000103FF, 0x00000000, 0x00000000, 0x00000000,
858 	0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
859 	0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
860 	0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
861 	0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
862 	0x00000003, 0x00000000, 0x00000000, 0x00000000,
863 	0x000003FF, 0x00000000, 0x00000000, 0x00000000,
864 	0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
865 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
866 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
867 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
868 	0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
869 };
870 
871 static efx_register_set_t __cs	__siena_tables[] = {
872 	{ FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
873 	    FR_AZ_RX_FILTER_TBL0_ROWS },
874 	{ FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
875 	    FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
876 	{ FR_AZ_RX_DESC_PTR_TBL_OFST,
877 	    FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
878 	{ FR_AZ_TX_DESC_PTR_TBL_OFST,
879 	    FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
880 	{ FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
881 	{ FR_CZ_TX_FILTER_TBL0_OFST,
882 	    FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
883 	{ FR_CZ_TX_MAC_FILTER_TBL0_OFST,
884 	    FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
885 };
886 
887 static const uint32_t __cs	__siena_table_masks[] = {
888 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
889 	0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
890 	0xFFFFFFFF, 0x0FFFFFFF, 0x01800000, 0x00000000,
891 	0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
892 	0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
893 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
894 	0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
895 };
896 
897 	__checkReturn	int
898 siena_nic_register_test(
899 	__in		efx_nic_t *enp)
900 {
901 	efx_register_set_t *rsp;
902 	const uint32_t *dwordp;
903 	unsigned int nitems;
904 	unsigned int count;
905 	int rc;
906 
907 	/* Fill out the register mask entries */
908 	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
909 		    == EFX_ARRAY_SIZE(__siena_registers) * 4);
910 
911 	nitems = EFX_ARRAY_SIZE(__siena_registers);
912 	dwordp = __siena_register_masks;
913 	for (count = 0; count < nitems; ++count) {
914 		rsp = __siena_registers + count;
915 		rsp->mask.eo_u32[0] = *dwordp++;
916 		rsp->mask.eo_u32[1] = *dwordp++;
917 		rsp->mask.eo_u32[2] = *dwordp++;
918 		rsp->mask.eo_u32[3] = *dwordp++;
919 	}
920 
921 	/* Fill out the register table entries */
922 	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
923 		    == EFX_ARRAY_SIZE(__siena_tables) * 4);
924 
925 	nitems = EFX_ARRAY_SIZE(__siena_tables);
926 	dwordp = __siena_table_masks;
927 	for (count = 0; count < nitems; ++count) {
928 		rsp = __siena_tables + count;
929 		rsp->mask.eo_u32[0] = *dwordp++;
930 		rsp->mask.eo_u32[1] = *dwordp++;
931 		rsp->mask.eo_u32[2] = *dwordp++;
932 		rsp->mask.eo_u32[3] = *dwordp++;
933 	}
934 
935 	if ((rc = efx_nic_test_registers(enp, __siena_registers,
936 	    EFX_ARRAY_SIZE(__siena_registers))) != 0)
937 		goto fail1;
938 
939 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
940 	    EFX_PATTERN_BYTE_ALTERNATE,
941 	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
942 		goto fail2;
943 
944 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
945 	    EFX_PATTERN_BYTE_CHANGING,
946 	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
947 		goto fail3;
948 
949 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
950 	    EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
951 		goto fail4;
952 
953 	return (0);
954 
955 fail4:
956 	EFSYS_PROBE(fail4);
957 fail3:
958 	EFSYS_PROBE(fail3);
959 fail2:
960 	EFSYS_PROBE(fail2);
961 fail1:
962 	EFSYS_PROBE1(fail1, int, rc);
963 
964 	return (rc);
965 }
966 
967 #endif	/* EFSYS_OPT_DIAG */
968 
969 #endif	/* EFSYS_OPT_SIENA */
970