1/*-
2 * Copyright (c) 2009-2015 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/siena_nic.c 293891 2016-01-14 09:05:51Z arybchik $");
33
34#include "efx.h"
35#include "efx_impl.h"
36#include "mcdi_mon.h"
37
38#if EFSYS_OPT_SIENA
39
40static __checkReturn efx_rc_t
41siena_nic_get_partn_mask(
42 __in efx_nic_t *enp,
43 __out unsigned int *maskp)
44{
45 efx_mcdi_req_t req;
46 uint8_t payload[MAX(MC_CMD_NVRAM_TYPES_IN_LEN,
47 MC_CMD_NVRAM_TYPES_OUT_LEN)];
48 efx_rc_t rc;
49
50 (void) memset(payload, 0, sizeof (payload));
51 req.emr_cmd = MC_CMD_NVRAM_TYPES;
52 req.emr_in_buf = payload;
53 req.emr_in_length = MC_CMD_NVRAM_TYPES_IN_LEN;
54 req.emr_out_buf = payload;
55 req.emr_out_length = MC_CMD_NVRAM_TYPES_OUT_LEN;
56
57 efx_mcdi_execute(enp, &req);
58
59 if (req.emr_rc != 0) {
60 rc = req.emr_rc;
61 goto fail1;
62 }
63
64 if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
65 rc = EMSGSIZE;
66 goto fail2;
67 }
68
69 *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
70
71 return (0);
72
73fail2:
74 EFSYS_PROBE(fail2);
75fail1:
76 EFSYS_PROBE1(fail1, efx_rc_t, rc);
77
78 return (rc);
79}
80
81#if EFSYS_OPT_PCIE_TUNE
82
83 __checkReturn efx_rc_t
84siena_nic_pcie_extended_sync(
85 __in efx_nic_t *enp)
86{
87 efx_rc_t rc;
88
89 if ((rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG17230,
90 B_TRUE, NULL) != 0))
91 goto fail1;
92
93 return (0);
94
95fail1:
96 EFSYS_PROBE1(fail1, efx_rc_t, rc);
97
98 return (rc);
99}
100
101#endif /* EFSYS_OPT_PCIE_TUNE */
102
103static __checkReturn efx_rc_t
104siena_board_cfg(
105 __in efx_nic_t *enp)
106{
107 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
108 uint8_t mac_addr[6];
109 efx_dword_t capabilities;
110 uint32_t board_type;
111 uint32_t nevq, nrxq, ntxq;
112 efx_rc_t rc;
113
114 /* External port identifier using one-based port numbering */
115 encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port;
116
117 /* Board configuration */
118 if ((rc = efx_mcdi_get_board_cfg(enp, &board_type,
119 &capabilities, mac_addr)) != 0)
120 goto fail1;
121
122 EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
123
124 encp->enc_board_type = board_type;
125
126 /* Additional capabilities */
127 encp->enc_clk_mult = 1;
128 if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) {
129 enp->en_features |= EFX_FEATURE_TURBO;
130
131 if (EFX_DWORD_FIELD(capabilities,
132 MC_CMD_CAPABILITIES_TURBO_ACTIVE)) {
133 encp->enc_clk_mult = 2;
134 }
135 }
136
137 encp->enc_evq_timer_quantum_ns =
138 EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
139 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
140 FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
141
142 /* When hash header insertion is enabled, Siena inserts 16 bytes */
143 encp->enc_rx_prefix_size = 16;
144
145 /* Alignment for receive packet DMA buffers */
146 encp->enc_rx_buf_align_start = 1;
147 encp->enc_rx_buf_align_end = 1;
148
149 /* Alignment for WPTR updates */
150 encp->enc_rx_push_align = 1;
151
152 /* Resource limits */
153 rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq);
154 if (rc != 0) {
155 if (rc != ENOTSUP)
156 goto fail2;
157
158 nevq = 1024;
159 nrxq = EFX_RXQ_LIMIT_TARGET;
160 ntxq = EFX_TXQ_LIMIT_TARGET;
161 }
162 encp->enc_evq_limit = nevq;
163 encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq);
164 encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq);
165
166 encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
167 (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) -
168 (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
169
170 encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
171 encp->enc_fw_assisted_tso_enabled = B_FALSE;
172 encp->enc_fw_assisted_tso_v2_enabled = B_FALSE;
173 encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
174
175 return (0);
176
177fail2:
178 EFSYS_PROBE(fail2);
179fail1:
180 EFSYS_PROBE1(fail1, efx_rc_t, rc);
181
182 return (rc);
183}
184
185static __checkReturn efx_rc_t
186siena_phy_cfg(
187 __in efx_nic_t *enp)
188{
189 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
190 efx_rc_t rc;
191
192 /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
193 if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
194 goto fail1;
195
196#if EFSYS_OPT_PHY_STATS
197 /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
198 siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask,
199 NULL, &encp->enc_phy_stat_mask, NULL);
200#endif /* EFSYS_OPT_PHY_STATS */
201
202 return (0);
203
204fail1:
205 EFSYS_PROBE1(fail1, efx_rc_t, rc);
206
207 return (rc);
208}
209
210 __checkReturn efx_rc_t
211siena_nic_probe(
212 __in efx_nic_t *enp)
213{
214 efx_port_t *epp = &(enp->en_port);
215 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
216 siena_link_state_t sls;
217 unsigned int mask;
218 efx_oword_t oword;
219 efx_rc_t rc;
220
221 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
222
223 /* Test BIU */
224 if ((rc = efx_nic_biu_test(enp)) != 0)
225 goto fail1;
226
227 /* Clear the region register */
228 EFX_POPULATE_OWORD_4(oword,
229 FRF_AZ_ADR_REGION0, 0,
230 FRF_AZ_ADR_REGION1, (1 << 16),
231 FRF_AZ_ADR_REGION2, (2 << 16),
232 FRF_AZ_ADR_REGION3, (3 << 16));
233 EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
234
235 /* Read clear any assertion state */
236 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
237 goto fail2;
238
239 /* Exit the assertion handler */
240 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
241 goto fail3;
242
243 /* Wrestle control from the BMC */
244 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
245 goto fail4;
246
247 if ((rc = siena_board_cfg(enp)) != 0)
248 goto fail5;
249
250 if ((rc = siena_phy_cfg(enp)) != 0)
251 goto fail6;
252
253 /* Obtain the default PHY advertised capabilities */
254 if ((rc = siena_nic_reset(enp)) != 0)
255 goto fail7;
256 if ((rc = siena_phy_get_link(enp, &sls)) != 0)
257 goto fail8;
258 epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
259 epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
260
261#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
262 if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
263 goto fail9;
264 enp->en_u.siena.enu_partn_mask = mask;
265#endif
266
267#if EFSYS_OPT_MAC_STATS
268 /* Wipe the MAC statistics */
269 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
270 goto fail10;
271#endif
272
273#if EFSYS_OPT_LOOPBACK
274 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
275 goto fail11;
276#endif
277
278#if EFSYS_OPT_MON_STATS
279 if ((rc = mcdi_mon_cfg_build(enp)) != 0)
280 goto fail12;
281#endif
282
283 encp->enc_features = enp->en_features;
284
285 return (0);
286
287#if EFSYS_OPT_MON_STATS
288fail12:
289 EFSYS_PROBE(fail12);
290#endif
291#if EFSYS_OPT_LOOPBACK
292fail11:
293 EFSYS_PROBE(fail11);
294#endif
295#if EFSYS_OPT_MAC_STATS
296fail10:
297 EFSYS_PROBE(fail10);
298#endif
299#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
300fail9:
301 EFSYS_PROBE(fail9);
302#endif
303fail8:
304 EFSYS_PROBE(fail8);
305fail7:
306 EFSYS_PROBE(fail7);
307fail6:
308 EFSYS_PROBE(fail6);
309fail5:
310 EFSYS_PROBE(fail5);
311fail4:
312 EFSYS_PROBE(fail4);
313fail3:
314 EFSYS_PROBE(fail3);
315fail2:
316 EFSYS_PROBE(fail2);
317fail1:
318 EFSYS_PROBE1(fail1, efx_rc_t, rc);
319
320 return (rc);
321}
322
323 __checkReturn efx_rc_t
324siena_nic_reset(
325 __in efx_nic_t *enp)
326{
327 efx_mcdi_req_t req;
328 efx_rc_t rc;
329
330 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
331
332 /* siena_nic_reset() is called to recover from BADASSERT failures. */
333 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
334 goto fail1;
335 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
336 goto fail2;
337
338 /*
339 * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied
340 * for backwards compatibility with PORT_RESET_IN_LEN.
341 */
342 EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0);
343
344 req.emr_cmd = MC_CMD_ENTITY_RESET;
345 req.emr_in_buf = NULL;
346 req.emr_in_length = 0;
347 req.emr_out_buf = NULL;
348 req.emr_out_length = 0;
349
350 efx_mcdi_execute(enp, &req);
351
352 if (req.emr_rc != 0) {
353 rc = req.emr_rc;
354 goto fail3;
355 }
356
357 return (0);
358
359fail3:
360 EFSYS_PROBE(fail3);
361fail2:
362 EFSYS_PROBE(fail2);
363fail1:
364 EFSYS_PROBE1(fail1, efx_rc_t, rc);
365
366 return (0);
367}
368
369static void
370siena_nic_rx_cfg(
371 __in efx_nic_t *enp)
372{
373 efx_oword_t oword;
374
375 /*
376 * RX_INGR_EN is always enabled on Siena, because we rely on
377 * the RX parser to be resiliant to missing SOP/EOP.
378 */
379 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
380 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
381 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
382
383 /* Disable parsing of additional 802.1Q in Q packets */
384 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
385 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
386 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
387}
388
389static void
390siena_nic_usrev_dis(
391 __in efx_nic_t *enp)
392{
393 efx_oword_t oword;
394
395 EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
396 EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
397}
398
399 __checkReturn efx_rc_t
400siena_nic_init(
401 __in efx_nic_t *enp)
402{
403 efx_rc_t rc;
404
405 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
406
407 /* Enable reporting of some events (e.g. link change) */
408 if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
409 goto fail1;
410
411 siena_sram_init(enp);
412
413 /* Configure Siena's RX block */
414 siena_nic_rx_cfg(enp);
415
416 /* Disable USR_EVents for now */
417 siena_nic_usrev_dis(enp);
418
419 /* bug17057: Ensure set_link is called */
420 if ((rc = siena_phy_reconfigure(enp)) != 0)
421 goto fail2;
422
423 enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V1;
424
425 return (0);
426
427fail2:
428 EFSYS_PROBE(fail2);
429fail1:
430 EFSYS_PROBE1(fail1, efx_rc_t, rc);
431
432 return (rc);
433}
434
435 void
436siena_nic_fini(
437 __in efx_nic_t *enp)
438{
439 _NOTE(ARGUNUSED(enp))
440}
441
442 void
443siena_nic_unprobe(
444 __in efx_nic_t *enp)
445{
446#if EFSYS_OPT_MON_STATS
447 mcdi_mon_cfg_free(enp);
448#endif /* EFSYS_OPT_MON_STATS */
449 (void) efx_mcdi_drv_attach(enp, B_FALSE);
450}
451
452#if EFSYS_OPT_DIAG
453
454static efx_register_set_t __siena_registers[] = {
455 { FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
456 { FR_CZ_USR_EV_CFG_OFST, 0, 1 },
457 { FR_AZ_RX_CFG_REG_OFST, 0, 1 },
458 { FR_AZ_TX_CFG_REG_OFST, 0, 1 },
459 { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
460 { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
461 { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
462 { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
463 { FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
464 { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
465 { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
466 { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
467 { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
468};
469
470static const uint32_t __siena_register_masks[] = {
471 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
472 0x000103FF, 0x00000000, 0x00000000, 0x00000000,
473 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
474 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
475 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
476 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
477 0x00000003, 0x00000000, 0x00000000, 0x00000000,
478 0x000003FF, 0x00000000, 0x00000000, 0x00000000,
479 0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
480 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
481 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
482 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
483 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
484};
485
486static efx_register_set_t __siena_tables[] = {
487 { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
488 FR_AZ_RX_FILTER_TBL0_ROWS },
489 { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
490 FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
491 { FR_AZ_RX_DESC_PTR_TBL_OFST,
492 FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
493 { FR_AZ_TX_DESC_PTR_TBL_OFST,
494 FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
495 { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
496 { FR_CZ_TX_FILTER_TBL0_OFST,
497 FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
498 { FR_CZ_TX_MAC_FILTER_TBL0_OFST,
499 FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
500};
501
502static const uint32_t __siena_table_masks[] = {
503 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
504 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
505 0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
506 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
507 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
508 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
509 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
510};
511
512 __checkReturn efx_rc_t
513siena_nic_register_test(
514 __in efx_nic_t *enp)
515{
516 efx_register_set_t *rsp;
517 const uint32_t *dwordp;
518 unsigned int nitems;
519 unsigned int count;
520 efx_rc_t rc;
521
522 /* Fill out the register mask entries */
523 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
524 == EFX_ARRAY_SIZE(__siena_registers) * 4);
525
526 nitems = EFX_ARRAY_SIZE(__siena_registers);
527 dwordp = __siena_register_masks;
528 for (count = 0; count < nitems; ++count) {
529 rsp = __siena_registers + count;
530 rsp->mask.eo_u32[0] = *dwordp++;
531 rsp->mask.eo_u32[1] = *dwordp++;
532 rsp->mask.eo_u32[2] = *dwordp++;
533 rsp->mask.eo_u32[3] = *dwordp++;
534 }
535
536 /* Fill out the register table entries */
537 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
538 == EFX_ARRAY_SIZE(__siena_tables) * 4);
539
540 nitems = EFX_ARRAY_SIZE(__siena_tables);
541 dwordp = __siena_table_masks;
542 for (count = 0; count < nitems; ++count) {
543 rsp = __siena_tables + count;
544 rsp->mask.eo_u32[0] = *dwordp++;
545 rsp->mask.eo_u32[1] = *dwordp++;
546 rsp->mask.eo_u32[2] = *dwordp++;
547 rsp->mask.eo_u32[3] = *dwordp++;
548 }
549
550 if ((rc = efx_nic_test_registers(enp, __siena_registers,
551 EFX_ARRAY_SIZE(__siena_registers))) != 0)
552 goto fail1;
553
554 if ((rc = efx_nic_test_tables(enp, __siena_tables,
555 EFX_PATTERN_BYTE_ALTERNATE,
556 EFX_ARRAY_SIZE(__siena_tables))) != 0)
557 goto fail2;
558
559 if ((rc = efx_nic_test_tables(enp, __siena_tables,
560 EFX_PATTERN_BYTE_CHANGING,
561 EFX_ARRAY_SIZE(__siena_tables))) != 0)
562 goto fail3;
563
564 if ((rc = efx_nic_test_tables(enp, __siena_tables,
565 EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
566 goto fail4;
567
568 return (0);
569
570fail4:
571 EFSYS_PROBE(fail4);
572fail3:
573 EFSYS_PROBE(fail3);
574fail2:
575 EFSYS_PROBE(fail2);
576fail1:
577 EFSYS_PROBE1(fail1, efx_rc_t, rc);
578
579 return (rc);
580}
581
582#endif /* EFSYS_OPT_DIAG */
583
584#endif /* EFSYS_OPT_SIENA */
2 * Copyright (c) 2009-2015 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/siena_nic.c 293891 2016-01-14 09:05:51Z arybchik $");
33
34#include "efx.h"
35#include "efx_impl.h"
36#include "mcdi_mon.h"
37
38#if EFSYS_OPT_SIENA
39
40static __checkReturn efx_rc_t
41siena_nic_get_partn_mask(
42 __in efx_nic_t *enp,
43 __out unsigned int *maskp)
44{
45 efx_mcdi_req_t req;
46 uint8_t payload[MAX(MC_CMD_NVRAM_TYPES_IN_LEN,
47 MC_CMD_NVRAM_TYPES_OUT_LEN)];
48 efx_rc_t rc;
49
50 (void) memset(payload, 0, sizeof (payload));
51 req.emr_cmd = MC_CMD_NVRAM_TYPES;
52 req.emr_in_buf = payload;
53 req.emr_in_length = MC_CMD_NVRAM_TYPES_IN_LEN;
54 req.emr_out_buf = payload;
55 req.emr_out_length = MC_CMD_NVRAM_TYPES_OUT_LEN;
56
57 efx_mcdi_execute(enp, &req);
58
59 if (req.emr_rc != 0) {
60 rc = req.emr_rc;
61 goto fail1;
62 }
63
64 if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
65 rc = EMSGSIZE;
66 goto fail2;
67 }
68
69 *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
70
71 return (0);
72
73fail2:
74 EFSYS_PROBE(fail2);
75fail1:
76 EFSYS_PROBE1(fail1, efx_rc_t, rc);
77
78 return (rc);
79}
80
81#if EFSYS_OPT_PCIE_TUNE
82
83 __checkReturn efx_rc_t
84siena_nic_pcie_extended_sync(
85 __in efx_nic_t *enp)
86{
87 efx_rc_t rc;
88
89 if ((rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG17230,
90 B_TRUE, NULL) != 0))
91 goto fail1;
92
93 return (0);
94
95fail1:
96 EFSYS_PROBE1(fail1, efx_rc_t, rc);
97
98 return (rc);
99}
100
101#endif /* EFSYS_OPT_PCIE_TUNE */
102
103static __checkReturn efx_rc_t
104siena_board_cfg(
105 __in efx_nic_t *enp)
106{
107 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
108 uint8_t mac_addr[6];
109 efx_dword_t capabilities;
110 uint32_t board_type;
111 uint32_t nevq, nrxq, ntxq;
112 efx_rc_t rc;
113
114 /* External port identifier using one-based port numbering */
115 encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port;
116
117 /* Board configuration */
118 if ((rc = efx_mcdi_get_board_cfg(enp, &board_type,
119 &capabilities, mac_addr)) != 0)
120 goto fail1;
121
122 EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
123
124 encp->enc_board_type = board_type;
125
126 /* Additional capabilities */
127 encp->enc_clk_mult = 1;
128 if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) {
129 enp->en_features |= EFX_FEATURE_TURBO;
130
131 if (EFX_DWORD_FIELD(capabilities,
132 MC_CMD_CAPABILITIES_TURBO_ACTIVE)) {
133 encp->enc_clk_mult = 2;
134 }
135 }
136
137 encp->enc_evq_timer_quantum_ns =
138 EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
139 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
140 FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
141
142 /* When hash header insertion is enabled, Siena inserts 16 bytes */
143 encp->enc_rx_prefix_size = 16;
144
145 /* Alignment for receive packet DMA buffers */
146 encp->enc_rx_buf_align_start = 1;
147 encp->enc_rx_buf_align_end = 1;
148
149 /* Alignment for WPTR updates */
150 encp->enc_rx_push_align = 1;
151
152 /* Resource limits */
153 rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq);
154 if (rc != 0) {
155 if (rc != ENOTSUP)
156 goto fail2;
157
158 nevq = 1024;
159 nrxq = EFX_RXQ_LIMIT_TARGET;
160 ntxq = EFX_TXQ_LIMIT_TARGET;
161 }
162 encp->enc_evq_limit = nevq;
163 encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq);
164 encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq);
165
166 encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
167 (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) -
168 (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
169
170 encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
171 encp->enc_fw_assisted_tso_enabled = B_FALSE;
172 encp->enc_fw_assisted_tso_v2_enabled = B_FALSE;
173 encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
174
175 return (0);
176
177fail2:
178 EFSYS_PROBE(fail2);
179fail1:
180 EFSYS_PROBE1(fail1, efx_rc_t, rc);
181
182 return (rc);
183}
184
185static __checkReturn efx_rc_t
186siena_phy_cfg(
187 __in efx_nic_t *enp)
188{
189 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
190 efx_rc_t rc;
191
192 /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
193 if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
194 goto fail1;
195
196#if EFSYS_OPT_PHY_STATS
197 /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
198 siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask,
199 NULL, &encp->enc_phy_stat_mask, NULL);
200#endif /* EFSYS_OPT_PHY_STATS */
201
202 return (0);
203
204fail1:
205 EFSYS_PROBE1(fail1, efx_rc_t, rc);
206
207 return (rc);
208}
209
210 __checkReturn efx_rc_t
211siena_nic_probe(
212 __in efx_nic_t *enp)
213{
214 efx_port_t *epp = &(enp->en_port);
215 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
216 siena_link_state_t sls;
217 unsigned int mask;
218 efx_oword_t oword;
219 efx_rc_t rc;
220
221 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
222
223 /* Test BIU */
224 if ((rc = efx_nic_biu_test(enp)) != 0)
225 goto fail1;
226
227 /* Clear the region register */
228 EFX_POPULATE_OWORD_4(oword,
229 FRF_AZ_ADR_REGION0, 0,
230 FRF_AZ_ADR_REGION1, (1 << 16),
231 FRF_AZ_ADR_REGION2, (2 << 16),
232 FRF_AZ_ADR_REGION3, (3 << 16));
233 EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
234
235 /* Read clear any assertion state */
236 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
237 goto fail2;
238
239 /* Exit the assertion handler */
240 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
241 goto fail3;
242
243 /* Wrestle control from the BMC */
244 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
245 goto fail4;
246
247 if ((rc = siena_board_cfg(enp)) != 0)
248 goto fail5;
249
250 if ((rc = siena_phy_cfg(enp)) != 0)
251 goto fail6;
252
253 /* Obtain the default PHY advertised capabilities */
254 if ((rc = siena_nic_reset(enp)) != 0)
255 goto fail7;
256 if ((rc = siena_phy_get_link(enp, &sls)) != 0)
257 goto fail8;
258 epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
259 epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
260
261#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
262 if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
263 goto fail9;
264 enp->en_u.siena.enu_partn_mask = mask;
265#endif
266
267#if EFSYS_OPT_MAC_STATS
268 /* Wipe the MAC statistics */
269 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
270 goto fail10;
271#endif
272
273#if EFSYS_OPT_LOOPBACK
274 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
275 goto fail11;
276#endif
277
278#if EFSYS_OPT_MON_STATS
279 if ((rc = mcdi_mon_cfg_build(enp)) != 0)
280 goto fail12;
281#endif
282
283 encp->enc_features = enp->en_features;
284
285 return (0);
286
287#if EFSYS_OPT_MON_STATS
288fail12:
289 EFSYS_PROBE(fail12);
290#endif
291#if EFSYS_OPT_LOOPBACK
292fail11:
293 EFSYS_PROBE(fail11);
294#endif
295#if EFSYS_OPT_MAC_STATS
296fail10:
297 EFSYS_PROBE(fail10);
298#endif
299#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
300fail9:
301 EFSYS_PROBE(fail9);
302#endif
303fail8:
304 EFSYS_PROBE(fail8);
305fail7:
306 EFSYS_PROBE(fail7);
307fail6:
308 EFSYS_PROBE(fail6);
309fail5:
310 EFSYS_PROBE(fail5);
311fail4:
312 EFSYS_PROBE(fail4);
313fail3:
314 EFSYS_PROBE(fail3);
315fail2:
316 EFSYS_PROBE(fail2);
317fail1:
318 EFSYS_PROBE1(fail1, efx_rc_t, rc);
319
320 return (rc);
321}
322
323 __checkReturn efx_rc_t
324siena_nic_reset(
325 __in efx_nic_t *enp)
326{
327 efx_mcdi_req_t req;
328 efx_rc_t rc;
329
330 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
331
332 /* siena_nic_reset() is called to recover from BADASSERT failures. */
333 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
334 goto fail1;
335 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
336 goto fail2;
337
338 /*
339 * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied
340 * for backwards compatibility with PORT_RESET_IN_LEN.
341 */
342 EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0);
343
344 req.emr_cmd = MC_CMD_ENTITY_RESET;
345 req.emr_in_buf = NULL;
346 req.emr_in_length = 0;
347 req.emr_out_buf = NULL;
348 req.emr_out_length = 0;
349
350 efx_mcdi_execute(enp, &req);
351
352 if (req.emr_rc != 0) {
353 rc = req.emr_rc;
354 goto fail3;
355 }
356
357 return (0);
358
359fail3:
360 EFSYS_PROBE(fail3);
361fail2:
362 EFSYS_PROBE(fail2);
363fail1:
364 EFSYS_PROBE1(fail1, efx_rc_t, rc);
365
366 return (0);
367}
368
369static void
370siena_nic_rx_cfg(
371 __in efx_nic_t *enp)
372{
373 efx_oword_t oword;
374
375 /*
376 * RX_INGR_EN is always enabled on Siena, because we rely on
377 * the RX parser to be resiliant to missing SOP/EOP.
378 */
379 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
380 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
381 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
382
383 /* Disable parsing of additional 802.1Q in Q packets */
384 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
385 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
386 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
387}
388
389static void
390siena_nic_usrev_dis(
391 __in efx_nic_t *enp)
392{
393 efx_oword_t oword;
394
395 EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
396 EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
397}
398
399 __checkReturn efx_rc_t
400siena_nic_init(
401 __in efx_nic_t *enp)
402{
403 efx_rc_t rc;
404
405 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
406
407 /* Enable reporting of some events (e.g. link change) */
408 if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
409 goto fail1;
410
411 siena_sram_init(enp);
412
413 /* Configure Siena's RX block */
414 siena_nic_rx_cfg(enp);
415
416 /* Disable USR_EVents for now */
417 siena_nic_usrev_dis(enp);
418
419 /* bug17057: Ensure set_link is called */
420 if ((rc = siena_phy_reconfigure(enp)) != 0)
421 goto fail2;
422
423 enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V1;
424
425 return (0);
426
427fail2:
428 EFSYS_PROBE(fail2);
429fail1:
430 EFSYS_PROBE1(fail1, efx_rc_t, rc);
431
432 return (rc);
433}
434
435 void
436siena_nic_fini(
437 __in efx_nic_t *enp)
438{
439 _NOTE(ARGUNUSED(enp))
440}
441
442 void
443siena_nic_unprobe(
444 __in efx_nic_t *enp)
445{
446#if EFSYS_OPT_MON_STATS
447 mcdi_mon_cfg_free(enp);
448#endif /* EFSYS_OPT_MON_STATS */
449 (void) efx_mcdi_drv_attach(enp, B_FALSE);
450}
451
452#if EFSYS_OPT_DIAG
453
454static efx_register_set_t __siena_registers[] = {
455 { FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
456 { FR_CZ_USR_EV_CFG_OFST, 0, 1 },
457 { FR_AZ_RX_CFG_REG_OFST, 0, 1 },
458 { FR_AZ_TX_CFG_REG_OFST, 0, 1 },
459 { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
460 { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
461 { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
462 { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
463 { FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
464 { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
465 { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
466 { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
467 { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
468};
469
470static const uint32_t __siena_register_masks[] = {
471 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
472 0x000103FF, 0x00000000, 0x00000000, 0x00000000,
473 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
474 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
475 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
476 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
477 0x00000003, 0x00000000, 0x00000000, 0x00000000,
478 0x000003FF, 0x00000000, 0x00000000, 0x00000000,
479 0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
480 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
481 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
482 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
483 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
484};
485
486static efx_register_set_t __siena_tables[] = {
487 { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
488 FR_AZ_RX_FILTER_TBL0_ROWS },
489 { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
490 FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
491 { FR_AZ_RX_DESC_PTR_TBL_OFST,
492 FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
493 { FR_AZ_TX_DESC_PTR_TBL_OFST,
494 FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
495 { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
496 { FR_CZ_TX_FILTER_TBL0_OFST,
497 FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
498 { FR_CZ_TX_MAC_FILTER_TBL0_OFST,
499 FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
500};
501
502static const uint32_t __siena_table_masks[] = {
503 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
504 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
505 0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
506 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
507 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
508 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
509 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
510};
511
512 __checkReturn efx_rc_t
513siena_nic_register_test(
514 __in efx_nic_t *enp)
515{
516 efx_register_set_t *rsp;
517 const uint32_t *dwordp;
518 unsigned int nitems;
519 unsigned int count;
520 efx_rc_t rc;
521
522 /* Fill out the register mask entries */
523 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
524 == EFX_ARRAY_SIZE(__siena_registers) * 4);
525
526 nitems = EFX_ARRAY_SIZE(__siena_registers);
527 dwordp = __siena_register_masks;
528 for (count = 0; count < nitems; ++count) {
529 rsp = __siena_registers + count;
530 rsp->mask.eo_u32[0] = *dwordp++;
531 rsp->mask.eo_u32[1] = *dwordp++;
532 rsp->mask.eo_u32[2] = *dwordp++;
533 rsp->mask.eo_u32[3] = *dwordp++;
534 }
535
536 /* Fill out the register table entries */
537 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
538 == EFX_ARRAY_SIZE(__siena_tables) * 4);
539
540 nitems = EFX_ARRAY_SIZE(__siena_tables);
541 dwordp = __siena_table_masks;
542 for (count = 0; count < nitems; ++count) {
543 rsp = __siena_tables + count;
544 rsp->mask.eo_u32[0] = *dwordp++;
545 rsp->mask.eo_u32[1] = *dwordp++;
546 rsp->mask.eo_u32[2] = *dwordp++;
547 rsp->mask.eo_u32[3] = *dwordp++;
548 }
549
550 if ((rc = efx_nic_test_registers(enp, __siena_registers,
551 EFX_ARRAY_SIZE(__siena_registers))) != 0)
552 goto fail1;
553
554 if ((rc = efx_nic_test_tables(enp, __siena_tables,
555 EFX_PATTERN_BYTE_ALTERNATE,
556 EFX_ARRAY_SIZE(__siena_tables))) != 0)
557 goto fail2;
558
559 if ((rc = efx_nic_test_tables(enp, __siena_tables,
560 EFX_PATTERN_BYTE_CHANGING,
561 EFX_ARRAY_SIZE(__siena_tables))) != 0)
562 goto fail3;
563
564 if ((rc = efx_nic_test_tables(enp, __siena_tables,
565 EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
566 goto fail4;
567
568 return (0);
569
570fail4:
571 EFSYS_PROBE(fail4);
572fail3:
573 EFSYS_PROBE(fail3);
574fail2:
575 EFSYS_PROBE(fail2);
576fail1:
577 EFSYS_PROBE1(fail1, efx_rc_t, rc);
578
579 return (rc);
580}
581
582#endif /* EFSYS_OPT_DIAG */
583
584#endif /* EFSYS_OPT_SIENA */