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