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