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