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