]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/sfxge/common/siena_nic.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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_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 */