xref: /freebsd/sys/dev/sfxge/common/siena_nic.c (revision cc16dea626cf2fc80cde667ac4798065108e596c)
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 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
593 
594 	/* Read clear any assertion state */
595 	if ((rc = siena_nic_read_assertion(enp)) != 0)
596 		goto fail1;
597 
598 	/* Exit the assertion handler */
599 	if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
600 		goto fail2;
601 
602 	/* Wrestle control from the BMC */
603 	if ((rc = siena_nic_attach(enp, B_TRUE)) != 0)
604 		goto fail3;
605 
606 	if ((rc = siena_board_cfg(enp)) != 0)
607 		goto fail4;
608 
609 	encp->enc_evq_moderation_max =
610 		EFX_EV_TIMER_QUANTUM << FRF_CZ_TIMER_VAL_WIDTH;
611 
612 	if ((rc = siena_phy_cfg(enp)) != 0)
613 		goto fail5;
614 
615 	/* Obtain the default PHY advertised capabilities */
616 	if ((rc = siena_nic_reset(enp)) != 0)
617 		goto fail6;
618 	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
619 		goto fail7;
620 	epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
621 	epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
622 
623 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
624 	if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
625 		goto fail8;
626 	enp->en_u.siena.enu_partn_mask = mask;
627 #endif
628 
629 #if EFSYS_OPT_MAC_STATS
630 	/* Wipe the MAC statistics */
631 	if ((rc = siena_mac_stats_clear(enp)) != 0)
632 		goto fail9;
633 #endif
634 
635 #if EFSYS_OPT_LOOPBACK
636 	if ((rc = siena_loopback_cfg(enp)) != 0)
637 		goto fail10;
638 #endif
639 
640 #if EFSYS_OPT_MON_STATS
641 	if ((rc = siena_monitor_cfg(enp)) != 0)
642 		goto fail11;
643 #endif
644 
645 	encp->enc_features = enp->en_features;
646 
647 	return (0);
648 
649 #if EFSYS_OPT_MON_STATS
650 fail11:
651 	EFSYS_PROBE(fail11);
652 #endif
653 #if EFSYS_OPT_LOOPBACK
654 fail10:
655 	EFSYS_PROBE(fail10);
656 #endif
657 #if EFSYS_OPT_MAC_STATS
658 fail9:
659 	EFSYS_PROBE(fail9);
660 #endif
661 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
662 fail8:
663 	EFSYS_PROBE(fail8);
664 #endif
665 fail7:
666 	EFSYS_PROBE(fail7);
667 fail6:
668 	EFSYS_PROBE(fail6);
669 fail5:
670 	EFSYS_PROBE(fail5);
671 fail4:
672 	EFSYS_PROBE(fail4);
673 fail3:
674 	EFSYS_PROBE(fail3);
675 fail2:
676 	EFSYS_PROBE(fail2);
677 fail1:
678 	EFSYS_PROBE1(fail1, int, rc);
679 
680 	return (rc);
681 }
682 
683 	__checkReturn	int
684 siena_nic_reset(
685 	__in		efx_nic_t *enp)
686 {
687 	efx_mcdi_req_t req;
688 	int rc;
689 
690 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
691 
692 	/* siena_nic_reset() is called to recover from BADASSERT failures. */
693 	if ((rc = siena_nic_read_assertion(enp)) != 0)
694 		goto fail1;
695 	if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
696 		goto fail2;
697 
698 	req.emr_cmd = MC_CMD_PORT_RESET;
699 	EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_IN_LEN == 0);
700 	req.emr_in_buf = NULL;
701 	req.emr_in_length = 0;
702 	EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_OUT_LEN == 0);
703 	req.emr_out_buf = NULL;
704 	req.emr_out_length = 0;
705 
706 	efx_mcdi_execute(enp, &req);
707 
708 	if (req.emr_rc != 0) {
709 		rc = req.emr_rc;
710 		goto fail3;
711 	}
712 
713 	return (0);
714 
715 fail3:
716 	EFSYS_PROBE(fail3);
717 fail2:
718 	EFSYS_PROBE(fail2);
719 fail1:
720 	EFSYS_PROBE1(fail1, int, rc);
721 
722 	return (0);
723 }
724 
725 static	__checkReturn	int
726 siena_nic_logging(
727 	__in		efx_nic_t *enp)
728 {
729 	efx_mcdi_req_t req;
730 	uint8_t payload[MC_CMD_LOG_CTRL_IN_LEN];
731 	int rc;
732 
733 	req.emr_cmd = MC_CMD_LOG_CTRL;
734 	req.emr_in_buf = payload;
735 	req.emr_in_length = MC_CMD_LOG_CTRL_IN_LEN;
736 	EFX_STATIC_ASSERT(MC_CMD_LOG_CTRL_OUT_LEN == 0);
737 	req.emr_out_buf = NULL;
738 	req.emr_out_length = 0;
739 
740 	MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST,
741 		    MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ);
742 	MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST_EVQ, 0);
743 
744 	efx_mcdi_execute(enp, &req);
745 
746 	if (req.emr_rc != 0) {
747 		rc = req.emr_rc;
748 		goto fail1;
749 	}
750 
751 	return (0);
752 
753 fail1:
754 	EFSYS_PROBE1(fail1, int, rc);
755 
756 	return (rc);
757 }
758 
759 static			void
760 siena_nic_rx_cfg(
761 	__in		efx_nic_t *enp)
762 {
763 	efx_oword_t oword;
764 
765 	/*
766 	 * RX_INGR_EN is always enabled on Siena, because we rely on
767 	 * the RX parser to be resiliant to missing SOP/EOP.
768 	 */
769 	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
770 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
771 	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
772 
773 	/* Disable parsing of additional 802.1Q in Q packets */
774 	EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
775 	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
776 	EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
777 }
778 
779 static			void
780 siena_nic_usrev_dis(
781 	__in		efx_nic_t *enp)
782 {
783 	efx_oword_t	oword;
784 
785 	EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
786 	EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
787 }
788 
789 	__checkReturn	int
790 siena_nic_init(
791 	__in		efx_nic_t *enp)
792 {
793 	int rc;
794 
795 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
796 
797 	if ((rc = siena_nic_logging(enp)) != 0)
798 		goto fail1;
799 
800 	siena_sram_init(enp);
801 
802 	/* Configure Siena's RX block */
803 	siena_nic_rx_cfg(enp);
804 
805 	/* Disable USR_EVents for now */
806 	siena_nic_usrev_dis(enp);
807 
808 	/* bug17057: Ensure set_link is called */
809 	if ((rc = siena_phy_reconfigure(enp)) != 0)
810 		goto fail2;
811 
812 	return (0);
813 
814 fail2:
815 	EFSYS_PROBE(fail2);
816 fail1:
817 	EFSYS_PROBE1(fail1, int, rc);
818 
819 	return (rc);
820 }
821 
822 			void
823 siena_nic_fini(
824 	__in		efx_nic_t *enp)
825 {
826 	_NOTE(ARGUNUSED(enp))
827 }
828 
829 			void
830 siena_nic_unprobe(
831 	__in		efx_nic_t *enp)
832 {
833 	(void) siena_nic_attach(enp, B_FALSE);
834 }
835 
836 #if EFSYS_OPT_DIAG
837 
838 static efx_register_set_t __cs	__siena_registers[] = {
839 	{ FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
840 	{ FR_CZ_USR_EV_CFG_OFST, 0, 1 },
841 	{ FR_AZ_RX_CFG_REG_OFST, 0, 1 },
842 	{ FR_AZ_TX_CFG_REG_OFST, 0, 1 },
843 	{ FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
844 	{ FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
845 	{ FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
846 	{ FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
847 	{ FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
848 	{ FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
849 	{ FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
850 	{ FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
851 	{ FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
852 };
853 
854 static const uint32_t __cs	__siena_register_masks[] = {
855 	0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
856 	0x000103FF, 0x00000000, 0x00000000, 0x00000000,
857 	0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
858 	0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
859 	0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
860 	0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
861 	0x00000003, 0x00000000, 0x00000000, 0x00000000,
862 	0x000003FF, 0x00000000, 0x00000000, 0x00000000,
863 	0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
864 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
865 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
866 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
867 	0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
868 };
869 
870 static efx_register_set_t __cs	__siena_tables[] = {
871 	{ FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
872 	    FR_AZ_RX_FILTER_TBL0_ROWS },
873 	{ FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
874 	    FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
875 	{ FR_AZ_RX_DESC_PTR_TBL_OFST,
876 	    FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
877 	{ FR_AZ_TX_DESC_PTR_TBL_OFST,
878 	    FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
879 	{ FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
880 	{ FR_CZ_TX_FILTER_TBL0_OFST,
881 	    FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
882 	{ FR_CZ_TX_MAC_FILTER_TBL0_OFST,
883 	    FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
884 };
885 
886 static const uint32_t __cs	__siena_table_masks[] = {
887 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
888 	0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
889 	0xFFFFFFFF, 0x0FFFFFFF, 0x01800000, 0x00000000,
890 	0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
891 	0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
892 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
893 	0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
894 };
895 
896 	__checkReturn	int
897 siena_nic_register_test(
898 	__in		efx_nic_t *enp)
899 {
900 	efx_register_set_t *rsp;
901 	const uint32_t *dwordp;
902 	unsigned int nitems;
903 	unsigned int count;
904 	int rc;
905 
906 	/* Fill out the register mask entries */
907 	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
908 		    == EFX_ARRAY_SIZE(__siena_registers) * 4);
909 
910 	nitems = EFX_ARRAY_SIZE(__siena_registers);
911 	dwordp = __siena_register_masks;
912 	for (count = 0; count < nitems; ++count) {
913 		rsp = __siena_registers + count;
914 		rsp->mask.eo_u32[0] = *dwordp++;
915 		rsp->mask.eo_u32[1] = *dwordp++;
916 		rsp->mask.eo_u32[2] = *dwordp++;
917 		rsp->mask.eo_u32[3] = *dwordp++;
918 	}
919 
920 	/* Fill out the register table entries */
921 	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
922 		    == EFX_ARRAY_SIZE(__siena_tables) * 4);
923 
924 	nitems = EFX_ARRAY_SIZE(__siena_tables);
925 	dwordp = __siena_table_masks;
926 	for (count = 0; count < nitems; ++count) {
927 		rsp = __siena_tables + count;
928 		rsp->mask.eo_u32[0] = *dwordp++;
929 		rsp->mask.eo_u32[1] = *dwordp++;
930 		rsp->mask.eo_u32[2] = *dwordp++;
931 		rsp->mask.eo_u32[3] = *dwordp++;
932 	}
933 
934 	if ((rc = efx_nic_test_registers(enp, __siena_registers,
935 	    EFX_ARRAY_SIZE(__siena_registers))) != 0)
936 		goto fail1;
937 
938 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
939 	    EFX_PATTERN_BYTE_ALTERNATE,
940 	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
941 		goto fail2;
942 
943 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
944 	    EFX_PATTERN_BYTE_CHANGING,
945 	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
946 		goto fail3;
947 
948 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
949 	    EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
950 		goto fail4;
951 
952 	return (0);
953 
954 fail4:
955 	EFSYS_PROBE(fail4);
956 fail3:
957 	EFSYS_PROBE(fail3);
958 fail2:
959 	EFSYS_PROBE(fail2);
960 fail1:
961 	EFSYS_PROBE1(fail1, int, rc);
962 
963 	return (rc);
964 }
965 
966 #endif	/* EFSYS_OPT_DIAG */
967 
968 #endif	/* EFSYS_OPT_SIENA */
969