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$");
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
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
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 /* Siena has a fixed 8Kbyte VI window size */
98 EFX_STATIC_ASSERT(1U << EFX_VI_WINDOW_SHIFT_8K == 8192);
99 encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_8K;
100
101 /* External port identifier using one-based port numbering */
102 encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port;
103
104 /* Board configuration */
105 if ((rc = efx_mcdi_get_board_cfg(enp, &board_type,
106 &capabilities, mac_addr)) != 0)
107 goto fail1;
108
109 EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
110
111 encp->enc_board_type = board_type;
112
113 /*
114 * There is no possibility to determine the number of PFs on Siena
115 * by issuing MCDI request, and it is not an easy task to find the
116 * value based on the board type, so 'enc_hw_pf_count' is set to 1
117 */
118 encp->enc_hw_pf_count = 1;
119
120 /* Additional capabilities */
121 encp->enc_clk_mult = 1;
122 if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) {
123 enp->en_features |= EFX_FEATURE_TURBO;
124
125 if (EFX_DWORD_FIELD(capabilities,
126 MC_CMD_CAPABILITIES_TURBO_ACTIVE)) {
127 encp->enc_clk_mult = 2;
128 }
129 }
130
131 encp->enc_evq_timer_quantum_ns =
132 EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
133 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
134 FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
135
136 /* When hash header insertion is enabled, Siena inserts 16 bytes */
137 encp->enc_rx_prefix_size = 16;
138
139 /* Alignment for receive packet DMA buffers */
140 encp->enc_rx_buf_align_start = 1;
141 encp->enc_rx_buf_align_end = 1;
142
143 /* Alignment for WPTR updates */
144 encp->enc_rx_push_align = 1;
145
146 #if EFSYS_OPT_RX_SCALE
147 /* There is one RSS context per function */
148 encp->enc_rx_scale_max_exclusive_contexts = 1;
149
150 encp->enc_rx_scale_hash_alg_mask |= (1U << EFX_RX_HASHALG_LFSR);
151 encp->enc_rx_scale_hash_alg_mask |= (1U << EFX_RX_HASHALG_TOEPLITZ);
152
153 /*
154 * It is always possible to use port numbers
155 * as the input data for hash computation.
156 */
157 encp->enc_rx_scale_l4_hash_supported = B_TRUE;
158
159 /* There is no support for additional RSS modes */
160 encp->enc_rx_scale_additional_modes_supported = B_FALSE;
161 #endif /* EFSYS_OPT_RX_SCALE */
162
163 encp->enc_tx_dma_desc_size_max = EFX_MASK32(FSF_AZ_TX_KER_BYTE_COUNT);
164 /* Fragments must not span 4k boundaries. */
165 encp->enc_tx_dma_desc_boundary = 4096;
166
167 /* Resource limits */
168 rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq);
169 if (rc != 0) {
170 if (rc != ENOTSUP)
171 goto fail2;
172
173 nevq = 1024;
174 nrxq = EFX_RXQ_LIMIT_TARGET;
175 ntxq = EFX_TXQ_LIMIT_TARGET;
176 }
177 encp->enc_evq_limit = nevq;
178 encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq);
179 encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq);
180
181 encp->enc_txq_max_ndescs = 4096;
182
183 encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
184 (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) -
185 (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
186
187 encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
188 encp->enc_fw_assisted_tso_enabled = B_FALSE;
189 encp->enc_fw_assisted_tso_v2_enabled = B_FALSE;
190 encp->enc_fw_assisted_tso_v2_n_contexts = 0;
191 encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
192 encp->enc_rx_packed_stream_supported = B_FALSE;
193 encp->enc_rx_var_packed_stream_supported = B_FALSE;
194 encp->enc_rx_es_super_buffer_supported = B_FALSE;
195 encp->enc_fw_subvariant_no_tx_csum_supported = B_FALSE;
196
197 /* Siena supports two 10G ports, and 8 lanes of PCIe Gen2 */
198 encp->enc_required_pcie_bandwidth_mbps = 2 * 10000;
199 encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN2;
200
201 encp->enc_nvram_update_verify_result_supported = B_FALSE;
202
203 encp->enc_mac_stats_nstats = MC_CMD_MAC_NSTATS;
204
205 encp->enc_filter_action_flag_supported = B_FALSE;
206 encp->enc_filter_action_mark_supported = B_FALSE;
207 encp->enc_filter_action_mark_max = 0;
208
209 return (0);
210
211 fail2:
212 EFSYS_PROBE(fail2);
213 fail1:
214 EFSYS_PROBE1(fail1, efx_rc_t, rc);
215
216 return (rc);
217 }
218
219 static __checkReturn efx_rc_t
220 siena_phy_cfg(
221 __in efx_nic_t *enp)
222 {
223 #if EFSYS_OPT_PHY_STATS
224 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
225 #endif /* EFSYS_OPT_PHY_STATS */
226 efx_rc_t rc;
227
228 /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
229 if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
230 goto fail1;
231
232 #if EFSYS_OPT_PHY_STATS
233 /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
234 siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask,
235 NULL, &encp->enc_phy_stat_mask, NULL);
236 #endif /* EFSYS_OPT_PHY_STATS */
237
238 return (0);
239
240 fail1:
241 EFSYS_PROBE1(fail1, efx_rc_t, rc);
242
243 return (rc);
244 }
245
246 #define SIENA_BIU_MAGIC0 0x01234567
247 #define SIENA_BIU_MAGIC1 0xfedcba98
248
249 static __checkReturn efx_rc_t
250 siena_nic_biu_test(
251 __in efx_nic_t *enp)
252 {
253 efx_oword_t oword;
254 efx_rc_t rc;
255
256 /*
257 * Write magic values to scratch registers 0 and 1, then
258 * verify that the values were written correctly. Interleave
259 * the accesses to ensure that the BIU is not just reading
260 * back the cached value that was last written.
261 */
262 EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC0);
263 EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE);
264
265 EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC1);
266 EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE);
267
268 EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE);
269 if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC0) {
270 rc = EIO;
271 goto fail1;
272 }
273
274 EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE);
275 if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC1) {
276 rc = EIO;
277 goto fail2;
278 }
279
280 /*
281 * Perform the same test, with the values swapped. This
282 * ensures that subsequent tests don't start with the correct
283 * values already written into the scratch registers.
284 */
285 EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC1);
286 EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE);
287
288 EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC0);
289 EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE);
290
291 EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE);
292 if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC1) {
293 rc = EIO;
294 goto fail3;
295 }
296
297 EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE);
298 if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC0) {
299 rc = EIO;
300 goto fail4;
301 }
302
303 return (0);
304
305 fail4:
306 EFSYS_PROBE(fail4);
307 fail3:
308 EFSYS_PROBE(fail3);
309 fail2:
310 EFSYS_PROBE(fail2);
311 fail1:
312 EFSYS_PROBE1(fail1, efx_rc_t, rc);
313
314 return (rc);
315 }
316
317 __checkReturn efx_rc_t
318 siena_nic_probe(
319 __in efx_nic_t *enp)
320 {
321 efx_port_t *epp = &(enp->en_port);
322 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
323 siena_link_state_t sls;
324 unsigned int mask;
325 efx_oword_t oword;
326 efx_rc_t rc;
327
328 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
329
330 /* Test BIU */
331 if ((rc = siena_nic_biu_test(enp)) != 0)
332 goto fail1;
333
334 /* Clear the region register */
335 EFX_POPULATE_OWORD_4(oword,
336 FRF_AZ_ADR_REGION0, 0,
337 FRF_AZ_ADR_REGION1, (1 << 16),
338 FRF_AZ_ADR_REGION2, (2 << 16),
339 FRF_AZ_ADR_REGION3, (3 << 16));
340 EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
341
342 /* Read clear any assertion state */
343 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
344 goto fail2;
345
346 /* Exit the assertion handler */
347 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
348 goto fail3;
349
350 /* Wrestle control from the BMC */
351 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
352 goto fail4;
353
354 if ((rc = siena_board_cfg(enp)) != 0)
355 goto fail5;
356
357 if ((rc = siena_phy_cfg(enp)) != 0)
358 goto fail6;
359
360 /* Obtain the default PHY advertised capabilities */
361 if ((rc = siena_nic_reset(enp)) != 0)
362 goto fail7;
363 if ((rc = siena_phy_get_link(enp, &sls)) != 0)
364 goto fail8;
365 epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
366 epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
367
368 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
369 if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
370 goto fail9;
371 enp->en_u.siena.enu_partn_mask = mask;
372 #endif
373
374 #if EFSYS_OPT_MAC_STATS
375 /* Wipe the MAC statistics */
376 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
377 goto fail10;
378 #endif
379
380 #if EFSYS_OPT_LOOPBACK
381 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
382 goto fail11;
383 #endif
384
385 #if EFSYS_OPT_MON_STATS
386 if ((rc = mcdi_mon_cfg_build(enp)) != 0)
387 goto fail12;
388 #endif
389
390 encp->enc_features = enp->en_features;
391
392 return (0);
393
394 #if EFSYS_OPT_MON_STATS
395 fail12:
396 EFSYS_PROBE(fail12);
397 #endif
398 #if EFSYS_OPT_LOOPBACK
399 fail11:
400 EFSYS_PROBE(fail11);
401 #endif
402 #if EFSYS_OPT_MAC_STATS
403 fail10:
404 EFSYS_PROBE(fail10);
405 #endif
406 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
407 fail9:
408 EFSYS_PROBE(fail9);
409 #endif
410 fail8:
411 EFSYS_PROBE(fail8);
412 fail7:
413 EFSYS_PROBE(fail7);
414 fail6:
415 EFSYS_PROBE(fail6);
416 fail5:
417 EFSYS_PROBE(fail5);
418 fail4:
419 EFSYS_PROBE(fail4);
420 fail3:
421 EFSYS_PROBE(fail3);
422 fail2:
423 EFSYS_PROBE(fail2);
424 fail1:
425 EFSYS_PROBE1(fail1, efx_rc_t, rc);
426
427 return (rc);
428 }
429
430 __checkReturn efx_rc_t
431 siena_nic_reset(
432 __in efx_nic_t *enp)
433 {
434 efx_mcdi_req_t req;
435 efx_rc_t rc;
436
437 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
438
439 /* siena_nic_reset() is called to recover from BADASSERT failures. */
440 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
441 goto fail1;
442 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
443 goto fail2;
444
445 /*
446 * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied
447 * for backwards compatibility with PORT_RESET_IN_LEN.
448 */
449 EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0);
450
451 req.emr_cmd = MC_CMD_ENTITY_RESET;
452 req.emr_in_buf = NULL;
453 req.emr_in_length = 0;
454 req.emr_out_buf = NULL;
455 req.emr_out_length = 0;
456
457 efx_mcdi_execute(enp, &req);
458
459 if (req.emr_rc != 0) {
460 rc = req.emr_rc;
461 goto fail3;
462 }
463
464 return (0);
465
466 fail3:
467 EFSYS_PROBE(fail3);
468 fail2:
469 EFSYS_PROBE(fail2);
470 fail1:
471 EFSYS_PROBE1(fail1, efx_rc_t, rc);
472
473 return (0);
474 }
475
476 static void
477 siena_nic_rx_cfg(
478 __in efx_nic_t *enp)
479 {
480 efx_oword_t oword;
481
482 /*
483 * RX_INGR_EN is always enabled on Siena, because we rely on
484 * the RX parser to be resiliant to missing SOP/EOP.
485 */
486 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
487 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
488 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
489
490 /* Disable parsing of additional 802.1Q in Q packets */
491 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
492 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
493 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
494 }
495
496 static void
497 siena_nic_usrev_dis(
498 __in efx_nic_t *enp)
499 {
500 efx_oword_t oword;
501
502 EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
503 EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
504 }
505
506 __checkReturn efx_rc_t
507 siena_nic_init(
508 __in efx_nic_t *enp)
509 {
510 efx_rc_t rc;
511
512 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
513
514 /* Enable reporting of some events (e.g. link change) */
515 if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
516 goto fail1;
517
518 siena_sram_init(enp);
519
520 /* Configure Siena's RX block */
521 siena_nic_rx_cfg(enp);
522
523 /* Disable USR_EVents for now */
524 siena_nic_usrev_dis(enp);
525
526 /* bug17057: Ensure set_link is called */
527 if ((rc = siena_phy_reconfigure(enp)) != 0)
528 goto fail2;
529
530 enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V1;
531
532 return (0);
533
534 fail2:
535 EFSYS_PROBE(fail2);
536 fail1:
537 EFSYS_PROBE1(fail1, efx_rc_t, rc);
538
539 return (rc);
540 }
541
542 void
543 siena_nic_fini(
544 __in efx_nic_t *enp)
545 {
546 _NOTE(ARGUNUSED(enp))
547 }
548
549 void
550 siena_nic_unprobe(
551 __in efx_nic_t *enp)
552 {
553 #if EFSYS_OPT_MON_STATS
554 mcdi_mon_cfg_free(enp);
555 #endif /* EFSYS_OPT_MON_STATS */
556 (void) efx_mcdi_drv_attach(enp, B_FALSE);
557 }
558
559 #if EFSYS_OPT_DIAG
560
561 static siena_register_set_t __siena_registers[] = {
562 { FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
563 { FR_CZ_USR_EV_CFG_OFST, 0, 1 },
564 { FR_AZ_RX_CFG_REG_OFST, 0, 1 },
565 { FR_AZ_TX_CFG_REG_OFST, 0, 1 },
566 { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
567 { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
568 { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
569 { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
570 { FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
571 { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
572 { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
573 { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
574 { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
575 };
576
577 static const uint32_t __siena_register_masks[] = {
578 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
579 0x000103FF, 0x00000000, 0x00000000, 0x00000000,
580 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
581 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
582 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
583 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
584 0x00000003, 0x00000000, 0x00000000, 0x00000000,
585 0x000003FF, 0x00000000, 0x00000000, 0x00000000,
586 0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
587 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
588 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
589 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
590 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
591 };
592
593 static siena_register_set_t __siena_tables[] = {
594 { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
595 FR_AZ_RX_FILTER_TBL0_ROWS },
596 { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
597 FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
598 { FR_AZ_RX_DESC_PTR_TBL_OFST,
599 FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
600 { FR_AZ_TX_DESC_PTR_TBL_OFST,
601 FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
602 { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
603 { FR_CZ_TX_FILTER_TBL0_OFST,
604 FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
605 { FR_CZ_TX_MAC_FILTER_TBL0_OFST,
606 FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
607 };
608
609 static const uint32_t __siena_table_masks[] = {
610 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
611 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
612 0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
613 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
614 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
615 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
616 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
617 };
618
619 __checkReturn efx_rc_t
620 siena_nic_test_registers(
621 __in efx_nic_t *enp,
622 __in siena_register_set_t *rsp,
623 __in size_t count)
624 {
625 unsigned int bit;
626 efx_oword_t original;
627 efx_oword_t reg;
628 efx_oword_t buf;
629 efx_rc_t rc;
630
631 while (count > 0) {
632 /* This function is only suitable for registers */
633 EFSYS_ASSERT(rsp->rows == 1);
634
635 /* bit sweep on and off */
636 EFSYS_BAR_READO(enp->en_esbp, rsp->address, &original,
637 B_TRUE);
638 for (bit = 0; bit < 128; bit++) {
639 /* Is this bit in the mask? */
640 if (~(rsp->mask.eo_u32[bit >> 5]) & (1 << bit))
641 continue;
642
643 /* Test this bit can be set in isolation */
644 reg = original;
645 EFX_AND_OWORD(reg, rsp->mask);
646 EFX_SET_OWORD_BIT(reg, bit);
647
648 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®,
649 B_TRUE);
650 EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf,
651 B_TRUE);
652
653 EFX_AND_OWORD(buf, rsp->mask);
654 if (memcmp(®, &buf, sizeof (reg))) {
655 rc = EIO;
656 goto fail1;
657 }
658
659 /* Test this bit can be cleared in isolation */
660 EFX_OR_OWORD(reg, rsp->mask);
661 EFX_CLEAR_OWORD_BIT(reg, bit);
662
663 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®,
664 B_TRUE);
665 EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf,
666 B_TRUE);
667
668 EFX_AND_OWORD(buf, rsp->mask);
669 if (memcmp(®, &buf, sizeof (reg))) {
670 rc = EIO;
671 goto fail2;
672 }
673 }
674
675 /* Restore the old value */
676 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original,
677 B_TRUE);
678
679 --count;
680 ++rsp;
681 }
682
683 return (0);
684
685 fail2:
686 EFSYS_PROBE(fail2);
687 fail1:
688 EFSYS_PROBE1(fail1, efx_rc_t, rc);
689
690 /* Restore the old value */
691 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, B_TRUE);
692
693 return (rc);
694 }
695
696 __checkReturn efx_rc_t
697 siena_nic_test_tables(
698 __in efx_nic_t *enp,
699 __in siena_register_set_t *rsp,
700 __in efx_pattern_type_t pattern,
701 __in size_t count)
702 {
703 efx_sram_pattern_fn_t func;
704 unsigned int index;
705 unsigned int address;
706 efx_oword_t reg;
707 efx_oword_t buf;
708 efx_rc_t rc;
709
710 EFSYS_ASSERT(pattern < EFX_PATTERN_NTYPES);
711 func = __efx_sram_pattern_fns[pattern];
712
713 while (count > 0) {
714 /* Write */
715 address = rsp->address;
716 for (index = 0; index < rsp->rows; ++index) {
717 func(2 * index + 0, B_FALSE, ®.eo_qword[0]);
718 func(2 * index + 1, B_FALSE, ®.eo_qword[1]);
719 EFX_AND_OWORD(reg, rsp->mask);
720 EFSYS_BAR_WRITEO(enp->en_esbp, address, ®, B_TRUE);
721
722 address += rsp->step;
723 }
724
725 /* Read */
726 address = rsp->address;
727 for (index = 0; index < rsp->rows; ++index) {
728 func(2 * index + 0, B_FALSE, ®.eo_qword[0]);
729 func(2 * index + 1, B_FALSE, ®.eo_qword[1]);
730 EFX_AND_OWORD(reg, rsp->mask);
731 EFSYS_BAR_READO(enp->en_esbp, address, &buf, B_TRUE);
732 if (memcmp(®, &buf, sizeof (reg))) {
733 rc = EIO;
734 goto fail1;
735 }
736
737 address += rsp->step;
738 }
739
740 ++rsp;
741 --count;
742 }
743
744 return (0);
745
746 fail1:
747 EFSYS_PROBE1(fail1, efx_rc_t, rc);
748
749 return (rc);
750 }
751
752 __checkReturn efx_rc_t
753 siena_nic_register_test(
754 __in efx_nic_t *enp)
755 {
756 siena_register_set_t *rsp;
757 const uint32_t *dwordp;
758 unsigned int nitems;
759 unsigned int count;
760 efx_rc_t rc;
761
762 /* Fill out the register mask entries */
763 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
764 == EFX_ARRAY_SIZE(__siena_registers) * 4);
765
766 nitems = EFX_ARRAY_SIZE(__siena_registers);
767 dwordp = __siena_register_masks;
768 for (count = 0; count < nitems; ++count) {
769 rsp = __siena_registers + count;
770 rsp->mask.eo_u32[0] = *dwordp++;
771 rsp->mask.eo_u32[1] = *dwordp++;
772 rsp->mask.eo_u32[2] = *dwordp++;
773 rsp->mask.eo_u32[3] = *dwordp++;
774 }
775
776 /* Fill out the register table entries */
777 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
778 == EFX_ARRAY_SIZE(__siena_tables) * 4);
779
780 nitems = EFX_ARRAY_SIZE(__siena_tables);
781 dwordp = __siena_table_masks;
782 for (count = 0; count < nitems; ++count) {
783 rsp = __siena_tables + count;
784 rsp->mask.eo_u32[0] = *dwordp++;
785 rsp->mask.eo_u32[1] = *dwordp++;
786 rsp->mask.eo_u32[2] = *dwordp++;
787 rsp->mask.eo_u32[3] = *dwordp++;
788 }
789
790 if ((rc = siena_nic_test_registers(enp, __siena_registers,
791 EFX_ARRAY_SIZE(__siena_registers))) != 0)
792 goto fail1;
793
794 if ((rc = siena_nic_test_tables(enp, __siena_tables,
795 EFX_PATTERN_BYTE_ALTERNATE,
796 EFX_ARRAY_SIZE(__siena_tables))) != 0)
797 goto fail2;
798
799 if ((rc = siena_nic_test_tables(enp, __siena_tables,
800 EFX_PATTERN_BYTE_CHANGING,
801 EFX_ARRAY_SIZE(__siena_tables))) != 0)
802 goto fail3;
803
804 if ((rc = siena_nic_test_tables(enp, __siena_tables,
805 EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
806 goto fail4;
807
808 return (0);
809
810 fail4:
811 EFSYS_PROBE(fail4);
812 fail3:
813 EFSYS_PROBE(fail3);
814 fail2:
815 EFSYS_PROBE(fail2);
816 fail1:
817 EFSYS_PROBE1(fail1, efx_rc_t, rc);
818
819 return (rc);
820 }
821
822 #endif /* EFSYS_OPT_DIAG */
823
824 #endif /* EFSYS_OPT_SIENA */
Cache object: 88b7675d51d4cb0f2f37782860561a38
|