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