1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright(c) 2019-2020 Xilinx, Inc.
4 * Copyright(c) 2009-2019 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 */