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
siena_nic_get_partn_mask(__in efx_nic_t * enp,__out unsigned int * maskp)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
siena_nic_exit_assertion_handler(__in efx_nic_t * enp)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
siena_nic_read_assertion(__in efx_nic_t * enp)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
siena_nic_attach(__in efx_nic_t * enp,__in boolean_t attach)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
siena_nic_pcie_extended_sync(__in efx_nic_t * enp)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
siena_board_cfg(__in efx_nic_t * enp)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
siena_phy_cfg(__in efx_nic_t * enp)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
siena_loopback_cfg(__in efx_nic_t * enp)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
siena_monitor_cfg(__in efx_nic_t * enp)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
siena_nic_probe(__in efx_nic_t * enp)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
siena_nic_reset(__in efx_nic_t * enp)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
siena_nic_logging(__in efx_nic_t * enp)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
siena_nic_rx_cfg(__in efx_nic_t * enp)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
siena_nic_usrev_dis(__in efx_nic_t * enp)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
siena_nic_init(__in efx_nic_t * enp)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
siena_nic_fini(__in efx_nic_t * enp)843 siena_nic_fini(
844 __in efx_nic_t *enp)
845 {
846 _NOTE(ARGUNUSED(enp))
847 }
848
849 void
siena_nic_unprobe(__in efx_nic_t * enp)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
siena_nic_register_test(__in efx_nic_t * enp)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