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