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