1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright (c) 2009-2018 Solarflare Communications Inc.
14 __in
uint32_t mcdi_cap
,
15 __out
uint32_t *maskp
)
20 if (mcdi_cap
& (1 << MC_CMD_PHY_CAP_10HDX_LBN
))
21 mask
|= (1 << EFX_PHY_CAP_10HDX
);
22 if (mcdi_cap
& (1 << MC_CMD_PHY_CAP_10FDX_LBN
))
23 mask
|= (1 << EFX_PHY_CAP_10FDX
);
24 if (mcdi_cap
& (1 << MC_CMD_PHY_CAP_100HDX_LBN
))
25 mask
|= (1 << EFX_PHY_CAP_100HDX
);
26 if (mcdi_cap
& (1 << MC_CMD_PHY_CAP_100FDX_LBN
))
27 mask
|= (1 << EFX_PHY_CAP_100FDX
);
28 if (mcdi_cap
& (1 << MC_CMD_PHY_CAP_1000HDX_LBN
))
29 mask
|= (1 << EFX_PHY_CAP_1000HDX
);
30 if (mcdi_cap
& (1 << MC_CMD_PHY_CAP_1000FDX_LBN
))
31 mask
|= (1 << EFX_PHY_CAP_1000FDX
);
32 if (mcdi_cap
& (1 << MC_CMD_PHY_CAP_10000FDX_LBN
))
33 mask
|= (1 << EFX_PHY_CAP_10000FDX
);
34 if (mcdi_cap
& (1 << MC_CMD_PHY_CAP_PAUSE_LBN
))
35 mask
|= (1 << EFX_PHY_CAP_PAUSE
);
36 if (mcdi_cap
& (1 << MC_CMD_PHY_CAP_ASYM_LBN
))
37 mask
|= (1 << EFX_PHY_CAP_ASYM
);
38 if (mcdi_cap
& (1 << MC_CMD_PHY_CAP_AN_LBN
))
39 mask
|= (1 << EFX_PHY_CAP_AN
);
45 siena_phy_decode_link_mode(
47 __in
uint32_t link_flags
,
48 __in
unsigned int speed
,
49 __in
unsigned int fcntl
,
50 __out efx_link_mode_t
*link_modep
,
51 __out
unsigned int *fcntlp
)
53 boolean_t fd
= !!(link_flags
&
54 (1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN
));
55 boolean_t up
= !!(link_flags
&
56 (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN
));
61 *link_modep
= EFX_LINK_DOWN
;
62 else if (speed
== 10000 && fd
)
63 *link_modep
= EFX_LINK_10000FDX
;
64 else if (speed
== 1000)
65 *link_modep
= fd
? EFX_LINK_1000FDX
: EFX_LINK_1000HDX
;
66 else if (speed
== 100)
67 *link_modep
= fd
? EFX_LINK_100FDX
: EFX_LINK_100HDX
;
69 *link_modep
= fd
? EFX_LINK_10FDX
: EFX_LINK_10HDX
;
71 *link_modep
= EFX_LINK_UNKNOWN
;
73 if (fcntl
== MC_CMD_FCNTL_OFF
)
75 else if (fcntl
== MC_CMD_FCNTL_RESPOND
)
76 *fcntlp
= EFX_FCNTL_RESPOND
;
77 else if (fcntl
== MC_CMD_FCNTL_BIDIR
)
78 *fcntlp
= EFX_FCNTL_RESPOND
| EFX_FCNTL_GENERATE
;
80 EFSYS_PROBE1(mc_pcol_error
, int, fcntl
);
88 __in efx_qword_t
*eqp
,
89 __out efx_link_mode_t
*link_modep
)
91 efx_port_t
*epp
= &(enp
->en_port
);
92 unsigned int link_flags
;
95 efx_link_mode_t link_mode
;
99 * Convert the LINKCHANGE speed enumeration into mbit/s, in the
100 * same way as GET_LINK encodes the speed
102 switch (MCDI_EV_FIELD(eqp
, LINKCHANGE_SPEED
)) {
103 case MCDI_EVENT_LINKCHANGE_SPEED_100M
:
106 case MCDI_EVENT_LINKCHANGE_SPEED_1G
:
109 case MCDI_EVENT_LINKCHANGE_SPEED_10G
:
117 link_flags
= MCDI_EV_FIELD(eqp
, LINKCHANGE_LINK_FLAGS
);
118 siena_phy_decode_link_mode(enp
, link_flags
, speed
,
119 MCDI_EV_FIELD(eqp
, LINKCHANGE_FCNTL
),
121 siena_phy_decode_cap(MCDI_EV_FIELD(eqp
, LINKCHANGE_LP_CAP
),
125 * It's safe to update ep_lp_cap_mask without the driver's port lock
126 * because presumably any concurrently running efx_port_poll() is
127 * only going to arrive at the same value.
129 * ep_fcntl has two meanings. It's either the link common fcntl
130 * (if the PHY supports AN), or it's the forced link state. If
131 * the former, it's safe to update the value for the same reason as
132 * for ep_lp_cap_mask. If the latter, then just ignore the value,
133 * because we can race with efx_mac_fcntl_set().
135 epp
->ep_lp_cap_mask
= lp_cap_mask
;
136 if (epp
->ep_phy_cap_mask
& (1 << EFX_PHY_CAP_AN
))
137 epp
->ep_fcntl
= fcntl
;
139 *link_modep
= link_mode
;
142 __checkReturn efx_rc_t
145 __in boolean_t power
)
152 /* Check if the PHY is a zombie */
153 if ((rc
= siena_phy_verify(enp
)) != 0)
156 enp
->en_reset_flags
|= EFX_RESET_PHY
;
161 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
166 __checkReturn efx_rc_t
169 __out siena_link_state_t
*slsp
)
172 EFX_MCDI_DECLARE_BUF(payload
, MC_CMD_GET_LINK_IN_LEN
,
173 MC_CMD_GET_LINK_OUT_LEN
);
176 req
.emr_cmd
= MC_CMD_GET_LINK
;
177 req
.emr_in_buf
= payload
;
178 req
.emr_in_length
= MC_CMD_GET_LINK_IN_LEN
;
179 req
.emr_out_buf
= payload
;
180 req
.emr_out_length
= MC_CMD_GET_LINK_OUT_LEN
;
182 efx_mcdi_execute(enp
, &req
);
184 if (req
.emr_rc
!= 0) {
189 if (req
.emr_out_length_used
< MC_CMD_GET_LINK_OUT_LEN
) {
194 siena_phy_decode_cap(MCDI_OUT_DWORD(req
, GET_LINK_OUT_CAP
),
195 &slsp
->sls_adv_cap_mask
);
196 siena_phy_decode_cap(MCDI_OUT_DWORD(req
, GET_LINK_OUT_LP_CAP
),
197 &slsp
->sls_lp_cap_mask
);
199 siena_phy_decode_link_mode(enp
, MCDI_OUT_DWORD(req
, GET_LINK_OUT_FLAGS
),
200 MCDI_OUT_DWORD(req
, GET_LINK_OUT_LINK_SPEED
),
201 MCDI_OUT_DWORD(req
, GET_LINK_OUT_FCNTL
),
202 &slsp
->sls_link_mode
, &slsp
->sls_fcntl
);
204 #if EFSYS_OPT_LOOPBACK
205 /* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespace agree */
206 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_NONE
== EFX_LOOPBACK_OFF
);
207 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_DATA
== EFX_LOOPBACK_DATA
);
208 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMAC
== EFX_LOOPBACK_GMAC
);
209 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII
== EFX_LOOPBACK_XGMII
);
210 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGXS
== EFX_LOOPBACK_XGXS
);
211 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI
== EFX_LOOPBACK_XAUI
);
212 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII
== EFX_LOOPBACK_GMII
);
213 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII
== EFX_LOOPBACK_SGMII
);
214 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGBR
== EFX_LOOPBACK_XGBR
);
215 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI
== EFX_LOOPBACK_XFI
);
216 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_FAR
== EFX_LOOPBACK_XAUI_FAR
);
217 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_FAR
== EFX_LOOPBACK_GMII_FAR
);
218 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII_FAR
== EFX_LOOPBACK_SGMII_FAR
);
219 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_FAR
== EFX_LOOPBACK_XFI_FAR
);
220 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GPHY
== EFX_LOOPBACK_GPHY
);
221 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS
== EFX_LOOPBACK_PHY_XS
);
222 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PCS
== EFX_LOOPBACK_PCS
);
223 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMAPMD
== EFX_LOOPBACK_PMA_PMD
);
225 slsp
->sls_loopback
= MCDI_OUT_DWORD(req
, GET_LINK_OUT_LOOPBACK_MODE
);
226 #endif /* EFSYS_OPT_LOOPBACK */
228 slsp
->sls_mac_up
= MCDI_OUT_DWORD(req
, GET_LINK_OUT_MAC_FAULT
) == 0;
235 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
240 __checkReturn efx_rc_t
241 siena_phy_reconfigure(
244 efx_port_t
*epp
= &(enp
->en_port
);
246 EFX_MCDI_DECLARE_BUF(payload
,
247 MAX(MC_CMD_SET_ID_LED_IN_LEN
, MC_CMD_SET_LINK_IN_LEN
),
248 MAX(MC_CMD_SET_ID_LED_OUT_LEN
, MC_CMD_SET_LINK_OUT_LEN
));
250 #if EFSYS_OPT_PHY_LED_CONTROL
251 unsigned int led_mode
;
256 req
.emr_cmd
= MC_CMD_SET_LINK
;
257 req
.emr_in_buf
= payload
;
258 req
.emr_in_length
= MC_CMD_SET_LINK_IN_LEN
;
259 req
.emr_out_buf
= payload
;
260 req
.emr_out_length
= MC_CMD_SET_LINK_OUT_LEN
;
262 cap_mask
= epp
->ep_adv_cap_mask
;
263 MCDI_IN_POPULATE_DWORD_10(req
, SET_LINK_IN_CAP
,
264 PHY_CAP_10HDX
, (cap_mask
>> EFX_PHY_CAP_10HDX
) & 0x1,
265 PHY_CAP_10FDX
, (cap_mask
>> EFX_PHY_CAP_10FDX
) & 0x1,
266 PHY_CAP_100HDX
, (cap_mask
>> EFX_PHY_CAP_100HDX
) & 0x1,
267 PHY_CAP_100FDX
, (cap_mask
>> EFX_PHY_CAP_100FDX
) & 0x1,
268 PHY_CAP_1000HDX
, (cap_mask
>> EFX_PHY_CAP_1000HDX
) & 0x1,
269 PHY_CAP_1000FDX
, (cap_mask
>> EFX_PHY_CAP_1000FDX
) & 0x1,
270 PHY_CAP_10000FDX
, (cap_mask
>> EFX_PHY_CAP_10000FDX
) & 0x1,
271 PHY_CAP_PAUSE
, (cap_mask
>> EFX_PHY_CAP_PAUSE
) & 0x1,
272 PHY_CAP_ASYM
, (cap_mask
>> EFX_PHY_CAP_ASYM
) & 0x1,
273 PHY_CAP_AN
, (cap_mask
>> EFX_PHY_CAP_AN
) & 0x1);
275 #if EFSYS_OPT_LOOPBACK
276 MCDI_IN_SET_DWORD(req
, SET_LINK_IN_LOOPBACK_MODE
,
277 epp
->ep_loopback_type
);
278 switch (epp
->ep_loopback_link_mode
) {
279 case EFX_LINK_100FDX
:
282 case EFX_LINK_1000FDX
:
285 case EFX_LINK_10000FDX
:
292 MCDI_IN_SET_DWORD(req
, SET_LINK_IN_LOOPBACK_MODE
, MC_CMD_LOOPBACK_NONE
);
294 #endif /* EFSYS_OPT_LOOPBACK */
295 MCDI_IN_SET_DWORD(req
, SET_LINK_IN_LOOPBACK_SPEED
, speed
);
297 #if EFSYS_OPT_PHY_FLAGS
298 MCDI_IN_SET_DWORD(req
, SET_LINK_IN_FLAGS
, epp
->ep_phy_flags
);
300 MCDI_IN_SET_DWORD(req
, SET_LINK_IN_FLAGS
, 0);
301 #endif /* EFSYS_OPT_PHY_FLAGS */
303 efx_mcdi_execute(enp
, &req
);
305 if (req
.emr_rc
!= 0) {
310 /* And set the blink mode */
311 (void) memset(payload
, 0, sizeof (payload
));
312 req
.emr_cmd
= MC_CMD_SET_ID_LED
;
313 req
.emr_in_buf
= payload
;
314 req
.emr_in_length
= MC_CMD_SET_ID_LED_IN_LEN
;
315 req
.emr_out_buf
= payload
;
316 req
.emr_out_length
= MC_CMD_SET_ID_LED_OUT_LEN
;
318 #if EFSYS_OPT_PHY_LED_CONTROL
319 switch (epp
->ep_phy_led_mode
) {
320 case EFX_PHY_LED_DEFAULT
:
321 led_mode
= MC_CMD_LED_DEFAULT
;
323 case EFX_PHY_LED_OFF
:
324 led_mode
= MC_CMD_LED_OFF
;
327 led_mode
= MC_CMD_LED_ON
;
331 led_mode
= MC_CMD_LED_DEFAULT
;
334 MCDI_IN_SET_DWORD(req
, SET_ID_LED_IN_STATE
, led_mode
);
336 MCDI_IN_SET_DWORD(req
, SET_ID_LED_IN_STATE
, MC_CMD_LED_DEFAULT
);
337 #endif /* EFSYS_OPT_PHY_LED_CONTROL */
339 efx_mcdi_execute(enp
, &req
);
341 if (req
.emr_rc
!= 0) {
351 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
356 __checkReturn efx_rc_t
361 EFX_MCDI_DECLARE_BUF(payload
, MC_CMD_GET_PHY_STATE_IN_LEN
,
362 MC_CMD_GET_PHY_STATE_OUT_LEN
);
366 req
.emr_cmd
= MC_CMD_GET_PHY_STATE
;
367 req
.emr_in_buf
= payload
;
368 req
.emr_in_length
= MC_CMD_GET_PHY_STATE_IN_LEN
;
369 req
.emr_out_buf
= payload
;
370 req
.emr_out_length
= MC_CMD_GET_PHY_STATE_OUT_LEN
;
372 efx_mcdi_execute(enp
, &req
);
374 if (req
.emr_rc
!= 0) {
379 if (req
.emr_out_length_used
< MC_CMD_GET_PHY_STATE_OUT_LEN
) {
384 state
= MCDI_OUT_DWORD(req
, GET_PHY_STATE_OUT_STATE
);
385 if (state
!= MC_CMD_PHY_STATE_OK
) {
386 if (state
!= MC_CMD_PHY_STATE_ZOMBIE
)
387 EFSYS_PROBE1(mc_pcol_error
, int, state
);
399 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
404 __checkReturn efx_rc_t
407 __out
uint32_t *ouip
)
409 _NOTE(ARGUNUSED(enp
, ouip
))
414 #if EFSYS_OPT_PHY_STATS
416 #define SIENA_SIMPLE_STAT_SET(_vmask, _esmp, _smask, _stat, \
417 _mc_record, _efx_record) \
418 if ((_vmask) & (1ULL << (_mc_record))) { \
419 (_smask) |= (1ULL << (_efx_record)); \
420 if ((_stat) != NULL && !EFSYS_MEM_IS_NULL(_esmp)) { \
422 EFSYS_MEM_READD(_esmp, (_mc_record) * 4, &dword);\
423 (_stat)[_efx_record] = \
424 EFX_DWORD_FIELD(dword, EFX_DWORD_0); \
428 #define SIENA_SIMPLE_STAT_SET2(_vmask, _esmp, _smask, _stat, _record) \
429 SIENA_SIMPLE_STAT_SET(_vmask, _esmp, _smask, _stat, \
430 MC_CMD_ ## _record, \
431 EFX_PHY_STAT_ ## _record)
434 siena_phy_decode_stats(
437 __in_opt efsys_mem_t
*esmp
,
438 __out_opt
uint64_t *smaskp
,
439 __inout_ecount_opt(EFX_PHY_NSTATS
) uint32_t *stat
)
443 _NOTE(ARGUNUSED(enp
))
445 SIENA_SIMPLE_STAT_SET2(vmask
, esmp
, smask
, stat
, OUI
);
446 SIENA_SIMPLE_STAT_SET2(vmask
, esmp
, smask
, stat
, PMA_PMD_LINK_UP
);
447 SIENA_SIMPLE_STAT_SET2(vmask
, esmp
, smask
, stat
, PMA_PMD_RX_FAULT
);
448 SIENA_SIMPLE_STAT_SET2(vmask
, esmp
, smask
, stat
, PMA_PMD_TX_FAULT
);
450 if (vmask
& (1 << MC_CMD_PMA_PMD_SIGNAL
)) {
451 smask
|= ((1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_A
) |
452 (1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_B
) |
453 (1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_C
) |
454 (1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_D
));
455 if (stat
!= NULL
&& esmp
!= NULL
&& !EFSYS_MEM_IS_NULL(esmp
)) {
458 EFSYS_MEM_READD(esmp
, 4 * MC_CMD_PMA_PMD_SIGNAL
,
460 sig
= EFX_DWORD_FIELD(dword
, EFX_DWORD_0
);
461 stat
[EFX_PHY_STAT_PMA_PMD_SIGNAL_A
] = (sig
>> 1) & 1;
462 stat
[EFX_PHY_STAT_PMA_PMD_SIGNAL_B
] = (sig
>> 2) & 1;
463 stat
[EFX_PHY_STAT_PMA_PMD_SIGNAL_C
] = (sig
>> 3) & 1;
464 stat
[EFX_PHY_STAT_PMA_PMD_SIGNAL_D
] = (sig
>> 4) & 1;
468 SIENA_SIMPLE_STAT_SET(vmask
, esmp
, smask
, stat
, MC_CMD_PMA_PMD_SNR_A
,
470 SIENA_SIMPLE_STAT_SET(vmask
, esmp
, smask
, stat
, MC_CMD_PMA_PMD_SNR_B
,
472 SIENA_SIMPLE_STAT_SET(vmask
, esmp
, smask
, stat
, MC_CMD_PMA_PMD_SNR_C
,
474 SIENA_SIMPLE_STAT_SET(vmask
, esmp
, smask
, stat
, MC_CMD_PMA_PMD_SNR_D
,
477 SIENA_SIMPLE_STAT_SET2(vmask
, esmp
, smask
, stat
, PCS_LINK_UP
);
478 SIENA_SIMPLE_STAT_SET2(vmask
, esmp
, smask
, stat
, PCS_RX_FAULT
);
479 SIENA_SIMPLE_STAT_SET2(vmask
, esmp
, smask
, stat
, PCS_TX_FAULT
);
480 SIENA_SIMPLE_STAT_SET2(vmask
, esmp
, smask
, stat
, PCS_BER
);
481 SIENA_SIMPLE_STAT_SET2(vmask
, esmp
, smask
, stat
, PCS_BLOCK_ERRORS
);
483 SIENA_SIMPLE_STAT_SET(vmask
, esmp
, smask
, stat
, MC_CMD_PHYXS_LINK_UP
,
484 EFX_PHY_STAT_PHY_XS_LINK_UP
);
485 SIENA_SIMPLE_STAT_SET(vmask
, esmp
, smask
, stat
, MC_CMD_PHYXS_RX_FAULT
,
486 EFX_PHY_STAT_PHY_XS_RX_FAULT
);
487 SIENA_SIMPLE_STAT_SET(vmask
, esmp
, smask
, stat
, MC_CMD_PHYXS_TX_FAULT
,
488 EFX_PHY_STAT_PHY_XS_TX_FAULT
);
489 SIENA_SIMPLE_STAT_SET(vmask
, esmp
, smask
, stat
, MC_CMD_PHYXS_ALIGN
,
490 EFX_PHY_STAT_PHY_XS_ALIGN
);
492 if (vmask
& (1 << MC_CMD_PHYXS_SYNC
)) {
493 smask
|= ((1 << EFX_PHY_STAT_PHY_XS_SYNC_A
) |
494 (1 << EFX_PHY_STAT_PHY_XS_SYNC_B
) |
495 (1 << EFX_PHY_STAT_PHY_XS_SYNC_C
) |
496 (1 << EFX_PHY_STAT_PHY_XS_SYNC_D
));
497 if (stat
!= NULL
&& !EFSYS_MEM_IS_NULL(esmp
)) {
500 EFSYS_MEM_READD(esmp
, 4 * MC_CMD_PHYXS_SYNC
, &dword
);
501 sync
= EFX_DWORD_FIELD(dword
, EFX_DWORD_0
);
502 stat
[EFX_PHY_STAT_PHY_XS_SYNC_A
] = (sync
>> 0) & 1;
503 stat
[EFX_PHY_STAT_PHY_XS_SYNC_B
] = (sync
>> 1) & 1;
504 stat
[EFX_PHY_STAT_PHY_XS_SYNC_C
] = (sync
>> 2) & 1;
505 stat
[EFX_PHY_STAT_PHY_XS_SYNC_D
] = (sync
>> 3) & 1;
509 SIENA_SIMPLE_STAT_SET2(vmask
, esmp
, smask
, stat
, AN_LINK_UP
);
510 SIENA_SIMPLE_STAT_SET2(vmask
, esmp
, smask
, stat
, AN_COMPLETE
);
512 SIENA_SIMPLE_STAT_SET(vmask
, esmp
, smask
, stat
, MC_CMD_CL22_LINK_UP
,
513 EFX_PHY_STAT_CL22EXT_LINK_UP
);
519 __checkReturn efx_rc_t
520 siena_phy_stats_update(
522 __in efsys_mem_t
*esmp
,
523 __inout_ecount(EFX_PHY_NSTATS
) uint32_t *stat
)
525 efx_nic_cfg_t
*encp
= &(enp
->en_nic_cfg
);
526 uint32_t vmask
= encp
->enc_mcdi_phy_stat_mask
;
529 EFX_MCDI_DECLARE_BUF(payload
, MC_CMD_PHY_STATS_IN_LEN
,
530 MC_CMD_PHY_STATS_OUT_DMA_LEN
);
533 if ((esmp
== NULL
) || (EFSYS_MEM_SIZE(esmp
) < EFX_PHY_STATS_SIZE
)) {
538 req
.emr_cmd
= MC_CMD_PHY_STATS
;
539 req
.emr_in_buf
= payload
;
540 req
.emr_in_length
= MC_CMD_PHY_STATS_IN_LEN
;
541 req
.emr_out_buf
= payload
;
542 req
.emr_out_length
= MC_CMD_PHY_STATS_OUT_DMA_LEN
;
544 MCDI_IN_SET_DWORD(req
, PHY_STATS_IN_DMA_ADDR_LO
,
545 EFSYS_MEM_ADDR(esmp
) & 0xffffffff);
546 MCDI_IN_SET_DWORD(req
, PHY_STATS_IN_DMA_ADDR_HI
,
547 EFSYS_MEM_ADDR(esmp
) >> 32);
549 efx_mcdi_execute(enp
, &req
);
551 if (req
.emr_rc
!= 0) {
555 EFSYS_ASSERT3U(req
.emr_out_length
, ==, MC_CMD_PHY_STATS_OUT_DMA_LEN
);
557 siena_phy_decode_stats(enp
, vmask
, esmp
, &smask
, stat
);
558 EFSYS_ASSERT(smask
== encp
->enc_phy_stat_mask
);
565 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
570 #endif /* EFSYS_OPT_PHY_STATS */
574 __checkReturn efx_rc_t
575 siena_phy_bist_start(
577 __in efx_bist_type_t type
)
581 if ((rc
= efx_mcdi_bist_start(enp
, type
)) != 0)
587 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
592 static __checkReturn
unsigned long
593 siena_phy_sft9001_bist_status(
597 case MC_CMD_POLL_BIST_SFT9001_PAIR_BUSY
:
598 return (EFX_PHY_CABLE_STATUS_BUSY
);
599 case MC_CMD_POLL_BIST_SFT9001_INTER_PAIR_SHORT
:
600 return (EFX_PHY_CABLE_STATUS_INTERPAIRSHORT
);
601 case MC_CMD_POLL_BIST_SFT9001_INTRA_PAIR_SHORT
:
602 return (EFX_PHY_CABLE_STATUS_INTRAPAIRSHORT
);
603 case MC_CMD_POLL_BIST_SFT9001_PAIR_OPEN
:
604 return (EFX_PHY_CABLE_STATUS_OPEN
);
605 case MC_CMD_POLL_BIST_SFT9001_PAIR_OK
:
606 return (EFX_PHY_CABLE_STATUS_OK
);
608 return (EFX_PHY_CABLE_STATUS_INVALID
);
612 __checkReturn efx_rc_t
615 __in efx_bist_type_t type
,
616 __out efx_bist_result_t
*resultp
,
617 __out_opt
__drv_when(count
> 0, __notnull
)
618 uint32_t *value_maskp
,
619 __out_ecount_opt(count
) __drv_when(count
> 0, __notnull
)
620 unsigned long *valuesp
,
623 efx_nic_cfg_t
*encp
= &(enp
->en_nic_cfg
);
624 EFX_MCDI_DECLARE_BUF(payload
, MC_CMD_POLL_BIST_IN_LEN
,
625 MCDI_CTL_SDU_LEN_MAX
);
626 uint32_t value_mask
= 0;
631 req
.emr_cmd
= MC_CMD_POLL_BIST
;
632 req
.emr_in_buf
= payload
;
633 req
.emr_in_length
= MC_CMD_POLL_BIST_IN_LEN
;
634 req
.emr_out_buf
= payload
;
635 req
.emr_out_length
= MCDI_CTL_SDU_LEN_MAX
;
637 efx_mcdi_execute(enp
, &req
);
639 if (req
.emr_rc
!= 0) {
644 if (req
.emr_out_length_used
< MC_CMD_POLL_BIST_OUT_RESULT_OFST
+ 4) {
650 (void) memset(valuesp
, '\0', count
* sizeof (unsigned long));
652 result
= MCDI_OUT_DWORD(req
, POLL_BIST_OUT_RESULT
);
654 /* Extract PHY specific results */
655 if (result
== MC_CMD_POLL_BIST_PASSED
&&
656 encp
->enc_phy_type
== EFX_PHY_SFT9001B
&&
657 req
.emr_out_length_used
>= MC_CMD_POLL_BIST_OUT_SFT9001_LEN
&&
658 (type
== EFX_BIST_TYPE_PHY_CABLE_SHORT
||
659 type
== EFX_BIST_TYPE_PHY_CABLE_LONG
)) {
662 if (count
> EFX_BIST_PHY_CABLE_LENGTH_A
) {
664 valuesp
[EFX_BIST_PHY_CABLE_LENGTH_A
] =
666 POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A
);
667 value_mask
|= (1 << EFX_BIST_PHY_CABLE_LENGTH_A
);
670 if (count
> EFX_BIST_PHY_CABLE_LENGTH_B
) {
672 valuesp
[EFX_BIST_PHY_CABLE_LENGTH_B
] =
674 POLL_BIST_OUT_SFT9001_CABLE_LENGTH_B
);
675 value_mask
|= (1 << EFX_BIST_PHY_CABLE_LENGTH_B
);
678 if (count
> EFX_BIST_PHY_CABLE_LENGTH_C
) {
680 valuesp
[EFX_BIST_PHY_CABLE_LENGTH_C
] =
682 POLL_BIST_OUT_SFT9001_CABLE_LENGTH_C
);
683 value_mask
|= (1 << EFX_BIST_PHY_CABLE_LENGTH_C
);
686 if (count
> EFX_BIST_PHY_CABLE_LENGTH_D
) {
688 valuesp
[EFX_BIST_PHY_CABLE_LENGTH_D
] =
690 POLL_BIST_OUT_SFT9001_CABLE_LENGTH_D
);
691 value_mask
|= (1 << EFX_BIST_PHY_CABLE_LENGTH_D
);
694 if (count
> EFX_BIST_PHY_CABLE_STATUS_A
) {
695 if (valuesp
!= NULL
) {
696 word
= MCDI_OUT_WORD(req
,
697 POLL_BIST_OUT_SFT9001_CABLE_STATUS_A
);
698 valuesp
[EFX_BIST_PHY_CABLE_STATUS_A
] =
699 siena_phy_sft9001_bist_status(word
);
701 value_mask
|= (1 << EFX_BIST_PHY_CABLE_STATUS_A
);
704 if (count
> EFX_BIST_PHY_CABLE_STATUS_B
) {
705 if (valuesp
!= NULL
) {
706 word
= MCDI_OUT_WORD(req
,
707 POLL_BIST_OUT_SFT9001_CABLE_STATUS_B
);
708 valuesp
[EFX_BIST_PHY_CABLE_STATUS_B
] =
709 siena_phy_sft9001_bist_status(word
);
711 value_mask
|= (1 << EFX_BIST_PHY_CABLE_STATUS_B
);
714 if (count
> EFX_BIST_PHY_CABLE_STATUS_C
) {
715 if (valuesp
!= NULL
) {
716 word
= MCDI_OUT_WORD(req
,
717 POLL_BIST_OUT_SFT9001_CABLE_STATUS_C
);
718 valuesp
[EFX_BIST_PHY_CABLE_STATUS_C
] =
719 siena_phy_sft9001_bist_status(word
);
721 value_mask
|= (1 << EFX_BIST_PHY_CABLE_STATUS_C
);
724 if (count
> EFX_BIST_PHY_CABLE_STATUS_D
) {
725 if (valuesp
!= NULL
) {
726 word
= MCDI_OUT_WORD(req
,
727 POLL_BIST_OUT_SFT9001_CABLE_STATUS_D
);
728 valuesp
[EFX_BIST_PHY_CABLE_STATUS_D
] =
729 siena_phy_sft9001_bist_status(word
);
731 value_mask
|= (1 << EFX_BIST_PHY_CABLE_STATUS_D
);
734 } else if (result
== MC_CMD_POLL_BIST_FAILED
&&
735 encp
->enc_phy_type
== EFX_PHY_QLX111V
&&
736 req
.emr_out_length
>= MC_CMD_POLL_BIST_OUT_MRSFP_LEN
&&
737 count
> EFX_BIST_FAULT_CODE
) {
739 valuesp
[EFX_BIST_FAULT_CODE
] =
740 MCDI_OUT_DWORD(req
, POLL_BIST_OUT_MRSFP_TEST
);
741 value_mask
|= 1 << EFX_BIST_FAULT_CODE
;
744 if (value_maskp
!= NULL
)
745 *value_maskp
= value_mask
;
747 EFSYS_ASSERT(resultp
!= NULL
);
748 if (result
== MC_CMD_POLL_BIST_RUNNING
)
749 *resultp
= EFX_BIST_RESULT_RUNNING
;
750 else if (result
== MC_CMD_POLL_BIST_PASSED
)
751 *resultp
= EFX_BIST_RESULT_PASSED
;
753 *resultp
= EFX_BIST_RESULT_FAILED
;
760 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
768 __in efx_bist_type_t type
)
770 /* There is no way to stop BIST on Siena */
771 _NOTE(ARGUNUSED(enp
, type
))
774 #endif /* EFSYS_OPT_BIST */
776 #endif /* EFSYS_OPT_SIENA */