1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2009-2016 Solarflare Communications Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * The views and conclusions contained in the software and documentation are
29 * those of the authors and should not be interpreted as representing official
30 * policies, either expressed or implied, of the FreeBSD Project.
31 */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD: stable/12/sys/dev/sfxge/common/siena_nic.c 342344 2018-12-21 16:57:59Z arybchik $");
35
36 #include "efx.h"
37 #include "efx_impl.h"
38 #include "mcdi_mon.h"
39
40 #if EFSYS_OPT_SIENA
41
42 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
43
44 static __checkReturn efx_rc_t
siena_nic_get_partn_mask(__in efx_nic_t * enp,__out unsigned int * maskp)45 siena_nic_get_partn_mask(
46 __in efx_nic_t *enp,
47 __out unsigned int *maskp)
48 {
49 efx_mcdi_req_t req;
50 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_TYPES_IN_LEN,
51 MC_CMD_NVRAM_TYPES_OUT_LEN);
52 efx_rc_t rc;
53
54 req.emr_cmd = MC_CMD_NVRAM_TYPES;
55 req.emr_in_buf = payload;
56 req.emr_in_length = MC_CMD_NVRAM_TYPES_IN_LEN;
57 req.emr_out_buf = payload;
58 req.emr_out_length = MC_CMD_NVRAM_TYPES_OUT_LEN;
59
60 efx_mcdi_execute(enp, &req);
61
62 if (req.emr_rc != 0) {
63 rc = req.emr_rc;
64 goto fail1;
65 }
66
67 if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
68 rc = EMSGSIZE;
69 goto fail2;
70 }
71
72 *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
73
74 return (0);
75
76 fail2:
77 EFSYS_PROBE(fail2);
78 fail1:
79 EFSYS_PROBE1(fail1, efx_rc_t, rc);
80
81 return (rc);
82 }
83
84 #endif /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */
85
86 static __checkReturn efx_rc_t
siena_board_cfg(__in efx_nic_t * enp)87 siena_board_cfg(
88 __in efx_nic_t *enp)
89 {
90 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
91 uint8_t mac_addr[6];
92 efx_dword_t capabilities;
93 uint32_t board_type;
94 uint32_t nevq, nrxq, ntxq;
95 efx_rc_t rc;
96
97 /* External port identifier using one-based port numbering */
98 encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port;
99
100 /* Board configuration */
101 if ((rc = efx_mcdi_get_board_cfg(enp, &board_type,
102 &capabilities, mac_addr)) != 0)
103 goto fail1;
104
105 EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
106
107 encp->enc_board_type = board_type;
108
109 /*
110 * There is no possibility to determine the number of PFs on Siena
111 * by issuing MCDI request, and it is not an easy task to find the
112 * value based on the board type, so 'enc_hw_pf_count' is set to 1
113 */
114 encp->enc_hw_pf_count = 1;
115
116 /* Additional capabilities */
117 encp->enc_clk_mult = 1;
118 if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) {
119 enp->en_features |= EFX_FEATURE_TURBO;
120
121 if (EFX_DWORD_FIELD(capabilities,
122 MC_CMD_CAPABILITIES_TURBO_ACTIVE)) {
123 encp->enc_clk_mult = 2;
124 }
125 }
126
127 encp->enc_evq_timer_quantum_ns =
128 EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
129 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
130 FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
131
132 /* When hash header insertion is enabled, Siena inserts 16 bytes */
133 encp->enc_rx_prefix_size = 16;
134
135 /* Alignment for receive packet DMA buffers */
136 encp->enc_rx_buf_align_start = 1;
137 encp->enc_rx_buf_align_end = 1;
138
139 /* Alignment for WPTR updates */
140 encp->enc_rx_push_align = 1;
141
142 encp->enc_tx_dma_desc_size_max = EFX_MASK32(FSF_AZ_TX_KER_BYTE_COUNT);
143 /* Fragments must not span 4k boundaries. */
144 encp->enc_tx_dma_desc_boundary = 4096;
145
146 /* Resource limits */
147 rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq);
148 if (rc != 0) {
149 if (rc != ENOTSUP)
150 goto fail2;
151
152 nevq = 1024;
153 nrxq = EFX_RXQ_LIMIT_TARGET;
154 ntxq = EFX_TXQ_LIMIT_TARGET;
155 }
156 encp->enc_evq_limit = nevq;
157 encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq);
158 encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq);
159
160 encp->enc_txq_max_ndescs = 4096;
161
162 encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
163 (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) -
164 (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
165
166 encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
167 encp->enc_fw_assisted_tso_enabled = B_FALSE;
168 encp->enc_fw_assisted_tso_v2_enabled = B_FALSE;
169 encp->enc_fw_assisted_tso_v2_n_contexts = 0;
170 encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
171
172 /* Siena supports two 10G ports, and 8 lanes of PCIe Gen2 */
173 encp->enc_required_pcie_bandwidth_mbps = 2 * 10000;
174 encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN2;
175
176 encp->enc_fw_verified_nvram_update_required = B_FALSE;
177
178 return (0);
179
180 fail2:
181 EFSYS_PROBE(fail2);
182 fail1:
183 EFSYS_PROBE1(fail1, efx_rc_t, rc);
184
185 return (rc);
186 }
187
188 static __checkReturn efx_rc_t
siena_phy_cfg(__in efx_nic_t * enp)189 siena_phy_cfg(
190 __in efx_nic_t *enp)
191 {
192 #if EFSYS_OPT_PHY_STATS
193 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
194 #endif /* EFSYS_OPT_PHY_STATS */
195 efx_rc_t rc;
196
197 /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
198 if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
199 goto fail1;
200
201 #if EFSYS_OPT_PHY_STATS
202 /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
203 siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask,
204 NULL, &encp->enc_phy_stat_mask, NULL);
205 #endif /* EFSYS_OPT_PHY_STATS */
206
207 return (0);
208
209 fail1:
210 EFSYS_PROBE1(fail1, efx_rc_t, rc);
211
212 return (rc);
213 }
214
215 #define SIENA_BIU_MAGIC0 0x01234567
216 #define SIENA_BIU_MAGIC1 0xfedcba98
217
218 static __checkReturn efx_rc_t
siena_nic_biu_test(__in efx_nic_t * enp)219 siena_nic_biu_test(
220 __in efx_nic_t *enp)
221 {
222 efx_oword_t oword;
223 efx_rc_t rc;
224
225 /*
226 * Write magic values to scratch registers 0 and 1, then
227 * verify that the values were written correctly. Interleave
228 * the accesses to ensure that the BIU is not just reading
229 * back the cached value that was last written.
230 */
231 EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC0);
232 EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE);
233
234 EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC1);
235 EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE);
236
237 EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE);
238 if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC0) {
239 rc = EIO;
240 goto fail1;
241 }
242
243 EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE);
244 if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC1) {
245 rc = EIO;
246 goto fail2;
247 }
248
249 /*
250 * Perform the same test, with the values swapped. This
251 * ensures that subsequent tests don't start with the correct
252 * values already written into the scratch registers.
253 */
254 EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC1);
255 EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE);
256
257 EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC0);
258 EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE);
259
260 EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE);
261 if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC1) {
262 rc = EIO;
263 goto fail3;
264 }
265
266 EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE);
267 if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC0) {
268 rc = EIO;
269 goto fail4;
270 }
271
272 return (0);
273
274 fail4:
275 EFSYS_PROBE(fail4);
276 fail3:
277 EFSYS_PROBE(fail3);
278 fail2:
279 EFSYS_PROBE(fail2);
280 fail1:
281 EFSYS_PROBE1(fail1, efx_rc_t, rc);
282
283 return (rc);
284 }
285
286 __checkReturn efx_rc_t
siena_nic_probe(__in efx_nic_t * enp)287 siena_nic_probe(
288 __in efx_nic_t *enp)
289 {
290 efx_port_t *epp = &(enp->en_port);
291 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
292 siena_link_state_t sls;
293 unsigned int mask;
294 efx_oword_t oword;
295 efx_rc_t rc;
296
297 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
298
299 /* Test BIU */
300 if ((rc = siena_nic_biu_test(enp)) != 0)
301 goto fail1;
302
303 /* Clear the region register */
304 EFX_POPULATE_OWORD_4(oword,
305 FRF_AZ_ADR_REGION0, 0,
306 FRF_AZ_ADR_REGION1, (1 << 16),
307 FRF_AZ_ADR_REGION2, (2 << 16),
308 FRF_AZ_ADR_REGION3, (3 << 16));
309 EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
310
311 /* Read clear any assertion state */
312 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
313 goto fail2;
314
315 /* Exit the assertion handler */
316 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
317 goto fail3;
318
319 /* Wrestle control from the BMC */
320 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
321 goto fail4;
322
323 if ((rc = siena_board_cfg(enp)) != 0)
324 goto fail5;
325
326 if ((rc = siena_phy_cfg(enp)) != 0)
327 goto fail6;
328
329 /* Obtain the default PHY advertised capabilities */
330 if ((rc = siena_nic_reset(enp)) != 0)
331 goto fail7;
332 if ((rc = siena_phy_get_link(enp, &sls)) != 0)
333 goto fail8;
334 epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
335 epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
336
337 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
338 if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
339 goto fail9;
340 enp->en_u.siena.enu_partn_mask = mask;
341 #endif
342
343 #if EFSYS_OPT_MAC_STATS
344 /* Wipe the MAC statistics */
345 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
346 goto fail10;
347 #endif
348
349 #if EFSYS_OPT_LOOPBACK
350 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
351 goto fail11;
352 #endif
353
354 #if EFSYS_OPT_MON_STATS
355 if ((rc = mcdi_mon_cfg_build(enp)) != 0)
356 goto fail12;
357 #endif
358
359 encp->enc_features = enp->en_features;
360
361 return (0);
362
363 #if EFSYS_OPT_MON_STATS
364 fail12:
365 EFSYS_PROBE(fail12);
366 #endif
367 #if EFSYS_OPT_LOOPBACK
368 fail11:
369 EFSYS_PROBE(fail11);
370 #endif
371 #if EFSYS_OPT_MAC_STATS
372 fail10:
373 EFSYS_PROBE(fail10);
374 #endif
375 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
376 fail9:
377 EFSYS_PROBE(fail9);
378 #endif
379 fail8:
380 EFSYS_PROBE(fail8);
381 fail7:
382 EFSYS_PROBE(fail7);
383 fail6:
384 EFSYS_PROBE(fail6);
385 fail5:
386 EFSYS_PROBE(fail5);
387 fail4:
388 EFSYS_PROBE(fail4);
389 fail3:
390 EFSYS_PROBE(fail3);
391 fail2:
392 EFSYS_PROBE(fail2);
393 fail1:
394 EFSYS_PROBE1(fail1, efx_rc_t, rc);
395
396 return (rc);
397 }
398
399 __checkReturn efx_rc_t
siena_nic_reset(__in efx_nic_t * enp)400 siena_nic_reset(
401 __in efx_nic_t *enp)
402 {
403 efx_mcdi_req_t req;
404 efx_rc_t rc;
405
406 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
407
408 /* siena_nic_reset() is called to recover from BADASSERT failures. */
409 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
410 goto fail1;
411 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
412 goto fail2;
413
414 /*
415 * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied
416 * for backwards compatibility with PORT_RESET_IN_LEN.
417 */
418 EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0);
419
420 req.emr_cmd = MC_CMD_ENTITY_RESET;
421 req.emr_in_buf = NULL;
422 req.emr_in_length = 0;
423 req.emr_out_buf = NULL;
424 req.emr_out_length = 0;
425
426 efx_mcdi_execute(enp, &req);
427
428 if (req.emr_rc != 0) {
429 rc = req.emr_rc;
430 goto fail3;
431 }
432
433 return (0);
434
435 fail3:
436 EFSYS_PROBE(fail3);
437 fail2:
438 EFSYS_PROBE(fail2);
439 fail1:
440 EFSYS_PROBE1(fail1, efx_rc_t, rc);
441
442 return (0);
443 }
444
445 static void
siena_nic_rx_cfg(__in efx_nic_t * enp)446 siena_nic_rx_cfg(
447 __in efx_nic_t *enp)
448 {
449 efx_oword_t oword;
450
451 /*
452 * RX_INGR_EN is always enabled on Siena, because we rely on
453 * the RX parser to be resiliant to missing SOP/EOP.
454 */
455 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
456 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
457 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
458
459 /* Disable parsing of additional 802.1Q in Q packets */
460 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
461 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
462 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
463 }
464
465 static void
siena_nic_usrev_dis(__in efx_nic_t * enp)466 siena_nic_usrev_dis(
467 __in efx_nic_t *enp)
468 {
469 efx_oword_t oword;
470
471 EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
472 EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
473 }
474
475 __checkReturn efx_rc_t
siena_nic_init(__in efx_nic_t * enp)476 siena_nic_init(
477 __in efx_nic_t *enp)
478 {
479 efx_rc_t rc;
480
481 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
482
483 /* Enable reporting of some events (e.g. link change) */
484 if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
485 goto fail1;
486
487 siena_sram_init(enp);
488
489 /* Configure Siena's RX block */
490 siena_nic_rx_cfg(enp);
491
492 /* Disable USR_EVents for now */
493 siena_nic_usrev_dis(enp);
494
495 /* bug17057: Ensure set_link is called */
496 if ((rc = siena_phy_reconfigure(enp)) != 0)
497 goto fail2;
498
499 enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V1;
500
501 return (0);
502
503 fail2:
504 EFSYS_PROBE(fail2);
505 fail1:
506 EFSYS_PROBE1(fail1, efx_rc_t, rc);
507
508 return (rc);
509 }
510
511 void
siena_nic_fini(__in efx_nic_t * enp)512 siena_nic_fini(
513 __in efx_nic_t *enp)
514 {
515 _NOTE(ARGUNUSED(enp))
516 }
517
518 void
siena_nic_unprobe(__in efx_nic_t * enp)519 siena_nic_unprobe(
520 __in efx_nic_t *enp)
521 {
522 #if EFSYS_OPT_MON_STATS
523 mcdi_mon_cfg_free(enp);
524 #endif /* EFSYS_OPT_MON_STATS */
525 (void) efx_mcdi_drv_attach(enp, B_FALSE);
526 }
527
528 #if EFSYS_OPT_DIAG
529
530 static siena_register_set_t __siena_registers[] = {
531 { FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
532 { FR_CZ_USR_EV_CFG_OFST, 0, 1 },
533 { FR_AZ_RX_CFG_REG_OFST, 0, 1 },
534 { FR_AZ_TX_CFG_REG_OFST, 0, 1 },
535 { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
536 { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
537 { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
538 { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
539 { FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
540 { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
541 { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
542 { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
543 { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
544 };
545
546 static const uint32_t __siena_register_masks[] = {
547 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
548 0x000103FF, 0x00000000, 0x00000000, 0x00000000,
549 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
550 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
551 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
552 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
553 0x00000003, 0x00000000, 0x00000000, 0x00000000,
554 0x000003FF, 0x00000000, 0x00000000, 0x00000000,
555 0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
556 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
557 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
558 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
559 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
560 };
561
562 static siena_register_set_t __siena_tables[] = {
563 { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
564 FR_AZ_RX_FILTER_TBL0_ROWS },
565 { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
566 FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
567 { FR_AZ_RX_DESC_PTR_TBL_OFST,
568 FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
569 { FR_AZ_TX_DESC_PTR_TBL_OFST,
570 FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
571 { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
572 { FR_CZ_TX_FILTER_TBL0_OFST,
573 FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
574 { FR_CZ_TX_MAC_FILTER_TBL0_OFST,
575 FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
576 };
577
578 static const uint32_t __siena_table_masks[] = {
579 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
580 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
581 0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
582 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
583 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
584 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
585 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
586 };
587
588 __checkReturn efx_rc_t
siena_nic_test_registers(__in efx_nic_t * enp,__in siena_register_set_t * rsp,__in size_t count)589 siena_nic_test_registers(
590 __in efx_nic_t *enp,
591 __in siena_register_set_t *rsp,
592 __in size_t count)
593 {
594 unsigned int bit;
595 efx_oword_t original;
596 efx_oword_t reg;
597 efx_oword_t buf;
598 efx_rc_t rc;
599
600 while (count > 0) {
601 /* This function is only suitable for registers */
602 EFSYS_ASSERT(rsp->rows == 1);
603
604 /* bit sweep on and off */
605 EFSYS_BAR_READO(enp->en_esbp, rsp->address, &original,
606 B_TRUE);
607 for (bit = 0; bit < 128; bit++) {
608 /* Is this bit in the mask? */
609 if (~(rsp->mask.eo_u32[bit >> 5]) & (1 << bit))
610 continue;
611
612 /* Test this bit can be set in isolation */
613 reg = original;
614 EFX_AND_OWORD(reg, rsp->mask);
615 EFX_SET_OWORD_BIT(reg, bit);
616
617 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®,
618 B_TRUE);
619 EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf,
620 B_TRUE);
621
622 EFX_AND_OWORD(buf, rsp->mask);
623 if (memcmp(®, &buf, sizeof (reg))) {
624 rc = EIO;
625 goto fail1;
626 }
627
628 /* Test this bit can be cleared in isolation */
629 EFX_OR_OWORD(reg, rsp->mask);
630 EFX_CLEAR_OWORD_BIT(reg, bit);
631
632 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®,
633 B_TRUE);
634 EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf,
635 B_TRUE);
636
637 EFX_AND_OWORD(buf, rsp->mask);
638 if (memcmp(®, &buf, sizeof (reg))) {
639 rc = EIO;
640 goto fail2;
641 }
642 }
643
644 /* Restore the old value */
645 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original,
646 B_TRUE);
647
648 --count;
649 ++rsp;
650 }
651
652 return (0);
653
654 fail2:
655 EFSYS_PROBE(fail2);
656 fail1:
657 EFSYS_PROBE1(fail1, efx_rc_t, rc);
658
659 /* Restore the old value */
660 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, B_TRUE);
661
662 return (rc);
663 }
664
665 __checkReturn efx_rc_t
siena_nic_test_tables(__in efx_nic_t * enp,__in siena_register_set_t * rsp,__in efx_pattern_type_t pattern,__in size_t count)666 siena_nic_test_tables(
667 __in efx_nic_t *enp,
668 __in siena_register_set_t *rsp,
669 __in efx_pattern_type_t pattern,
670 __in size_t count)
671 {
672 efx_sram_pattern_fn_t func;
673 unsigned int index;
674 unsigned int address;
675 efx_oword_t reg;
676 efx_oword_t buf;
677 efx_rc_t rc;
678
679 EFSYS_ASSERT(pattern < EFX_PATTERN_NTYPES);
680 func = __efx_sram_pattern_fns[pattern];
681
682 while (count > 0) {
683 /* Write */
684 address = rsp->address;
685 for (index = 0; index < rsp->rows; ++index) {
686 func(2 * index + 0, B_FALSE, ®.eo_qword[0]);
687 func(2 * index + 1, B_FALSE, ®.eo_qword[1]);
688 EFX_AND_OWORD(reg, rsp->mask);
689 EFSYS_BAR_WRITEO(enp->en_esbp, address, ®, B_TRUE);
690
691 address += rsp->step;
692 }
693
694 /* Read */
695 address = rsp->address;
696 for (index = 0; index < rsp->rows; ++index) {
697 func(2 * index + 0, B_FALSE, ®.eo_qword[0]);
698 func(2 * index + 1, B_FALSE, ®.eo_qword[1]);
699 EFX_AND_OWORD(reg, rsp->mask);
700 EFSYS_BAR_READO(enp->en_esbp, address, &buf, B_TRUE);
701 if (memcmp(®, &buf, sizeof (reg))) {
702 rc = EIO;
703 goto fail1;
704 }
705
706 address += rsp->step;
707 }
708
709 ++rsp;
710 --count;
711 }
712
713 return (0);
714
715 fail1:
716 EFSYS_PROBE1(fail1, efx_rc_t, rc);
717
718 return (rc);
719 }
720
721
722 __checkReturn efx_rc_t
siena_nic_register_test(__in efx_nic_t * enp)723 siena_nic_register_test(
724 __in efx_nic_t *enp)
725 {
726 siena_register_set_t *rsp;
727 const uint32_t *dwordp;
728 unsigned int nitems;
729 unsigned int count;
730 efx_rc_t rc;
731
732 /* Fill out the register mask entries */
733 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
734 == EFX_ARRAY_SIZE(__siena_registers) * 4);
735
736 nitems = EFX_ARRAY_SIZE(__siena_registers);
737 dwordp = __siena_register_masks;
738 for (count = 0; count < nitems; ++count) {
739 rsp = __siena_registers + count;
740 rsp->mask.eo_u32[0] = *dwordp++;
741 rsp->mask.eo_u32[1] = *dwordp++;
742 rsp->mask.eo_u32[2] = *dwordp++;
743 rsp->mask.eo_u32[3] = *dwordp++;
744 }
745
746 /* Fill out the register table entries */
747 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
748 == EFX_ARRAY_SIZE(__siena_tables) * 4);
749
750 nitems = EFX_ARRAY_SIZE(__siena_tables);
751 dwordp = __siena_table_masks;
752 for (count = 0; count < nitems; ++count) {
753 rsp = __siena_tables + count;
754 rsp->mask.eo_u32[0] = *dwordp++;
755 rsp->mask.eo_u32[1] = *dwordp++;
756 rsp->mask.eo_u32[2] = *dwordp++;
757 rsp->mask.eo_u32[3] = *dwordp++;
758 }
759
760 if ((rc = siena_nic_test_registers(enp, __siena_registers,
761 EFX_ARRAY_SIZE(__siena_registers))) != 0)
762 goto fail1;
763
764 if ((rc = siena_nic_test_tables(enp, __siena_tables,
765 EFX_PATTERN_BYTE_ALTERNATE,
766 EFX_ARRAY_SIZE(__siena_tables))) != 0)
767 goto fail2;
768
769 if ((rc = siena_nic_test_tables(enp, __siena_tables,
770 EFX_PATTERN_BYTE_CHANGING,
771 EFX_ARRAY_SIZE(__siena_tables))) != 0)
772 goto fail3;
773
774 if ((rc = siena_nic_test_tables(enp, __siena_tables,
775 EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
776 goto fail4;
777
778 return (0);
779
780 fail4:
781 EFSYS_PROBE(fail4);
782 fail3:
783 EFSYS_PROBE(fail3);
784 fail2:
785 EFSYS_PROBE(fail2);
786 fail1:
787 EFSYS_PROBE1(fail1, efx_rc_t, rc);
788
789 return (rc);
790 }
791
792 #endif /* EFSYS_OPT_DIAG */
793
794 #endif /* EFSYS_OPT_SIENA */
795