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