1/*-
2 * Copyright (c) 2007-2015 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/efx_phy.c 295467 2016-02-10 12:14:56Z arybchik $");
33
34#include "efx.h"
35#include "efx_impl.h"
36#if EFSYS_OPT_FALCON
37#include "falcon_nvram.h"
38#endif
39
40#if EFSYS_OPT_MAC_FALCON_XMAC
41#include "falcon_xmac.h"
42#endif
43
44#if EFSYS_OPT_MAC_FALCON_GMAC
45#include "falcon_gmac.h"
46#endif
47
48#if EFSYS_OPT_PHY_NULL
49#include "nullphy.h"
50#endif
51
52#if EFSYS_OPT_PHY_QT2022C2
53#include "qt2022c2.h"
54#endif
55
56#if EFSYS_OPT_PHY_SFX7101
57#include "sfx7101.h"
58#endif
59
60#if EFSYS_OPT_PHY_TXC43128
61#include "txc43128.h"
62#endif
63
64#if EFSYS_OPT_PHY_SFT9001
65#include "sft9001.h"
66#endif
67
68#if EFSYS_OPT_PHY_QT2025C
69#include "qt2025c.h"
70#endif
71
72#if EFSYS_OPT_PHY_NULL
73static efx_phy_ops_t __efx_phy_null_ops = {
74 NULL, /* epo_power */
75 nullphy_reset, /* epo_reset */
76 nullphy_reconfigure, /* epo_reconfigure */
77 nullphy_verify, /* epo_verify */
78 NULL, /* epo_uplink_check */
79 nullphy_downlink_check, /* epo_downlink_check */
80 nullphy_oui_get, /* epo_oui_get */
81#if EFSYS_OPT_PHY_STATS
82 nullphy_stats_update, /* epo_stats_update */
83#endif /* EFSYS_OPT_PHY_STATS */
84#if EFSYS_OPT_PHY_PROPS
85#if EFSYS_OPT_NAMES
86 nullphy_prop_name, /* epo_prop_name */
87#endif
88 nullphy_prop_get, /* epo_prop_get */
89 nullphy_prop_set, /* epo_prop_set */
90#endif /* EFSYS_OPT_PHY_PROPS */
91#if EFSYS_OPT_BIST
92 NULL, /* epo_bist_enable_offline */
93 NULL, /* epo_bist_start */
94 NULL, /* epo_bist_poll */
95 NULL, /* epo_bist_stop */
96#endif /* EFSYS_OPT_BIST */
97};
98#endif /* EFSYS_OPT_PHY_NULL */
99
100#if EFSYS_OPT_PHY_QT2022C2
101static efx_phy_ops_t __efx_phy_qt2022c2_ops = {
102 NULL, /* epo_power */
103 qt2022c2_reset, /* epo_reset */
104 qt2022c2_reconfigure, /* epo_reconfigure */
105 qt2022c2_verify, /* epo_verify */
106 qt2022c2_uplink_check, /* epo_uplink_check */
107 qt2022c2_downlink_check, /* epo_downlink_check */
108 qt2022c2_oui_get, /* epo_oui_get */
109#if EFSYS_OPT_PHY_STATS
110 qt2022c2_stats_update, /* epo_stats_update */
111#endif /* EFSYS_OPT_PHY_STATS */
112#if EFSYS_OPT_PHY_PROPS
113#if EFSYS_OPT_NAMES
114 qt2022c2_prop_name, /* epo_prop_name */
115#endif
116 qt2022c2_prop_get, /* epo_prop_get */
117 qt2022c2_prop_set, /* epo_prop_set */
118#endif /* EFSYS_OPT_PHY_PROPS */
119#if EFSYS_OPT_BIST
120 NULL, /* epo_bist_enable_offline */
121 NULL, /* epo_bist_start */
122 NULL, /* epo_bist_poll */
123 NULL, /* epo_bist_stop */
124#endif /* EFSYS_OPT_BIST */
125};
126#endif /* EFSYS_OPT_PHY_QT2022C2 */
127
128#if EFSYS_OPT_PHY_SFX7101
129static efx_phy_ops_t __efx_phy_sfx7101_ops = {
130 sfx7101_power, /* epo_power */
131 sfx7101_reset, /* epo_reset */
132 sfx7101_reconfigure, /* epo_reconfigure */
133 sfx7101_verify, /* epo_verify */
134 sfx7101_uplink_check, /* epo_uplink_check */
135 sfx7101_downlink_check, /* epo_downlink_check */
136 sfx7101_oui_get, /* epo_oui_get */
137#if EFSYS_OPT_PHY_STATS
138 sfx7101_stats_update, /* epo_stats_update */
139#endif /* EFSYS_OPT_PHY_STATS */
140#if EFSYS_OPT_PHY_PROPS
141#if EFSYS_OPT_NAMES
142 sfx7101_prop_name, /* epo_prop_name */
143#endif
144 sfx7101_prop_get, /* epo_prop_get */
145 sfx7101_prop_set, /* epo_prop_set */
146#endif /* EFSYS_OPT_PHY_PROPS */
147#if EFSYS_OPT_BIST
148 NULL, /* epo_bist_enable_offline */
149 NULL, /* epo_bist_start */
150 NULL, /* epo_bist_poll */
151 NULL, /* epo_bist_stop */
152#endif /* EFSYS_OPT_BIST */
153};
154#endif /* EFSYS_OPT_PHY_SFX7101 */
155
156#if EFSYS_OPT_PHY_TXC43128
157static efx_phy_ops_t __efx_phy_txc43128_ops = {
158 NULL, /* epo_power */
159 txc43128_reset, /* epo_reset */
160 txc43128_reconfigure, /* epo_reconfigure */
161 txc43128_verify, /* epo_verify */
162 txc43128_uplink_check, /* epo_uplink_check */
163 txc43128_downlink_check, /* epo_downlink_check */
164 txc43128_oui_get, /* epo_oui_get */
165#if EFSYS_OPT_PHY_STATS
166 txc43128_stats_update, /* epo_stats_update */
167#endif /* EFSYS_OPT_PHY_STATS */
168#if EFSYS_OPT_PHY_PROPS
169#if EFSYS_OPT_NAMES
170 txc43128_prop_name, /* epo_prop_name */
171#endif
172 txc43128_prop_get, /* epo_prop_get */
173 txc43128_prop_set, /* epo_prop_set */
174#endif /* EFSYS_OPT_PHY_PROPS */
175#if EFSYS_OPT_BIST
176 NULL, /* epo_bist_enable_offline */
177 NULL, /* epo_bist_start */
178 NULL, /* epo_bist_poll */
179 NULL, /* epo_bist_stop */
180#endif /* EFSYS_OPT_BIST */
181};
182#endif /* EFSYS_OPT_PHY_TXC43128 */
183
184#if EFSYS_OPT_PHY_SFT9001
185static efx_phy_ops_t __efx_phy_sft9001_ops = {
186 NULL, /* epo_power */
187 sft9001_reset, /* epo_reset */
188 sft9001_reconfigure, /* epo_reconfigure */
189 sft9001_verify, /* epo_verify */
190 sft9001_uplink_check, /* epo_uplink_check */
191 sft9001_downlink_check, /* epo_downlink_check */
192 sft9001_oui_get, /* epo_oui_get */
193#if EFSYS_OPT_PHY_STATS
194 sft9001_stats_update, /* epo_stats_update */
195#endif /* EFSYS_OPT_PHY_STATS */
196#if EFSYS_OPT_PHY_PROPS
197#if EFSYS_OPT_NAMES
198 sft9001_prop_name, /* epo_prop_name */
199#endif
200 sft9001_prop_get, /* epo_prop_get */
201 sft9001_prop_set, /* epo_prop_set */
202#endif /* EFSYS_OPT_PHY_PROPS */
203#if EFSYS_OPT_BIST
204 NULL, /* epo_bist_enable_offline */
205 sft9001_bist_start, /* epo_bist_start */
206 sft9001_bist_poll, /* epo_bist_poll */
207 sft9001_bist_stop, /* epo_bist_stop */
208#endif /* EFSYS_OPT_BIST */
209};
210#endif /* EFSYS_OPT_PHY_SFT9001 */
211
212#if EFSYS_OPT_PHY_QT2025C
213static efx_phy_ops_t __efx_phy_qt2025c_ops = {
214 NULL, /* epo_power */
215 qt2025c_reset, /* epo_reset */
216 qt2025c_reconfigure, /* epo_reconfigure */
217 qt2025c_verify, /* epo_verify */
218 qt2025c_uplink_check, /* epo_uplink_check */
219 qt2025c_downlink_check, /* epo_downlink_check */
220 qt2025c_oui_get, /* epo_oui_get */
221#if EFSYS_OPT_PHY_STATS
222 qt2025c_stats_update, /* epo_stats_update */
223#endif /* EFSYS_OPT_PHY_STATS */
224#if EFSYS_OPT_PHY_PROPS
225#if EFSYS_OPT_NAMES
226 qt2025c_prop_name, /* epo_prop_name */
227#endif
228 qt2025c_prop_get, /* epo_prop_get */
229 qt2025c_prop_set, /* epo_prop_set */
230#endif /* EFSYS_OPT_PHY_PROPS */
231#if EFSYS_OPT_BIST
232 NULL, /* epo_bist_enable_offline */
233 NULL, /* epo_bist_start */
234 NULL, /* epo_bist_poll */
235 NULL, /* epo_bist_stop */
236#endif /* EFSYS_OPT_BIST */
237};
238#endif /* EFSYS_OPT_PHY_QT2025C */
239
240#if EFSYS_OPT_SIENA
241static efx_phy_ops_t __efx_phy_siena_ops = {
242 siena_phy_power, /* epo_power */
243 NULL, /* epo_reset */
244 siena_phy_reconfigure, /* epo_reconfigure */
245 siena_phy_verify, /* epo_verify */
246 NULL, /* epo_uplink_check */
247 NULL, /* epo_downlink_check */
248 siena_phy_oui_get, /* epo_oui_get */
249#if EFSYS_OPT_PHY_STATS
250 siena_phy_stats_update, /* epo_stats_update */
251#endif /* EFSYS_OPT_PHY_STATS */
252#if EFSYS_OPT_PHY_PROPS
253#if EFSYS_OPT_NAMES
254 siena_phy_prop_name, /* epo_prop_name */
255#endif
256 siena_phy_prop_get, /* epo_prop_get */
257 siena_phy_prop_set, /* epo_prop_set */
258#endif /* EFSYS_OPT_PHY_PROPS */
259#if EFSYS_OPT_BIST
260 NULL, /* epo_bist_enable_offline */
261 siena_phy_bist_start, /* epo_bist_start */
262 siena_phy_bist_poll, /* epo_bist_poll */
263 siena_phy_bist_stop, /* epo_bist_stop */
264#endif /* EFSYS_OPT_BIST */
265};
266#endif /* EFSYS_OPT_SIENA */
267
268#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
269static efx_phy_ops_t __efx_phy_ef10_ops = {
270 ef10_phy_power, /* epo_power */
271 NULL, /* epo_reset */
272 ef10_phy_reconfigure, /* epo_reconfigure */
273 ef10_phy_verify, /* epo_verify */
274 NULL, /* epo_uplink_check */
275 NULL, /* epo_downlink_check */
276 ef10_phy_oui_get, /* epo_oui_get */
277#if EFSYS_OPT_PHY_STATS
278 ef10_phy_stats_update, /* epo_stats_update */
279#endif /* EFSYS_OPT_PHY_STATS */
280#if EFSYS_OPT_PHY_PROPS
281#if EFSYS_OPT_NAMES
282 ef10_phy_prop_name, /* epo_prop_name */
283#endif
284 ef10_phy_prop_get, /* epo_prop_get */
285 ef10_phy_prop_set, /* epo_prop_set */
286#endif /* EFSYS_OPT_PHY_PROPS */
287#if EFSYS_OPT_BIST
288 /* FIXME: Are these BIST methods appropriate for Medford? */
289 hunt_bist_enable_offline, /* epo_bist_enable_offline */
290 hunt_bist_start, /* epo_bist_start */
291 hunt_bist_poll, /* epo_bist_poll */
292 hunt_bist_stop, /* epo_bist_stop */
293#endif /* EFSYS_OPT_BIST */
294};
295#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
296
297 __checkReturn efx_rc_t
298efx_phy_probe(
299 __in efx_nic_t *enp)
300{
301 efx_port_t *epp = &(enp->en_port);
302 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
303 efx_phy_ops_t *epop;
304 efx_rc_t rc;
305
306 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
307
308 epp->ep_port = encp->enc_port;
309 epp->ep_phy_type = encp->enc_phy_type;
310
311 /* Hook in operations structure */
312 switch (enp->en_family) {
313#if EFSYS_OPT_FALCON
314 case EFX_FAMILY_FALCON:
315 switch (epp->ep_phy_type) {
316#if EFSYS_OPT_PHY_NULL
317 case PHY_TYPE_NONE_DECODE:
318 epop = (efx_phy_ops_t *)&__efx_phy_null_ops;
319 break;
320#endif
321#if EFSYS_OPT_PHY_QT2022C2
322 case PHY_TYPE_QT2022C2_DECODE:
323 epop = (efx_phy_ops_t *)&__efx_phy_qt2022c2_ops;
324 break;
325#endif
326#if EFSYS_OPT_PHY_SFX7101
327 case PHY_TYPE_SFX7101_DECODE:
328 epop = (efx_phy_ops_t *)&__efx_phy_sfx7101_ops;
329 break;
330#endif
331#if EFSYS_OPT_PHY_TXC43128
332 case PHY_TYPE_TXC43128_DECODE:
333 epop = (efx_phy_ops_t *)&__efx_phy_txc43128_ops;
334 break;
335#endif
336#if EFSYS_OPT_PHY_SFT9001
337 case PHY_TYPE_SFT9001A_DECODE:
338 case PHY_TYPE_SFT9001B_DECODE:
339 epop = (efx_phy_ops_t *)&__efx_phy_sft9001_ops;
340 break;
341#endif
342#if EFSYS_OPT_PHY_QT2025C
343 case EFX_PHY_QT2025C:
344 epop = (efx_phy_ops_t *)&__efx_phy_qt2025c_ops;
345 break;
346#endif
347 default:
348 rc = ENOTSUP;
349 goto fail1;
350 }
351 break;
352#endif /* EFSYS_OPT_FALCON */
353#if EFSYS_OPT_SIENA
354 case EFX_FAMILY_SIENA:
355 epop = (efx_phy_ops_t *)&__efx_phy_siena_ops;
356 break;
357#endif /* EFSYS_OPT_SIENA */
358#if EFSYS_OPT_HUNTINGTON
359 case EFX_FAMILY_HUNTINGTON:
360 epop = (efx_phy_ops_t *)&__efx_phy_ef10_ops;
361 break;
362#endif /* EFSYS_OPT_HUNTINGTON */
363#if EFSYS_OPT_MEDFORD
364 case EFX_FAMILY_MEDFORD:
365 epop = (efx_phy_ops_t *)&__efx_phy_ef10_ops;
366 break;
367#endif /* EFSYS_OPT_MEDFORD */
368 default:
369 rc = ENOTSUP;
370 goto fail1;
371 }
372
373 epp->ep_epop = epop;
374
375 return (0);
376
377fail1:
378 EFSYS_PROBE1(fail1, efx_rc_t, rc);
379
380 epp->ep_port = 0;
381 epp->ep_phy_type = 0;
382
383 return (rc);
384}
385
386 __checkReturn efx_rc_t
387efx_phy_verify(
388 __in efx_nic_t *enp)
389{
390 efx_port_t *epp = &(enp->en_port);
391 efx_phy_ops_t *epop = epp->ep_epop;
392
393 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
394 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
395
396 return (epop->epo_verify(enp));
397}
398
399#if EFSYS_OPT_PHY_LED_CONTROL
400
401 __checkReturn efx_rc_t
402efx_phy_led_set(
403 __in efx_nic_t *enp,
404 __in efx_phy_led_mode_t mode)
405{
406 efx_nic_cfg_t *encp = (&enp->en_nic_cfg);
407 efx_port_t *epp = &(enp->en_port);
408 efx_phy_ops_t *epop = epp->ep_epop;
409 uint32_t mask;
410 efx_rc_t rc;
411
412 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
413 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
414
415 if (epp->ep_phy_led_mode == mode)
416 goto done;
417
418 mask = (1 << EFX_PHY_LED_DEFAULT);
419 mask |= encp->enc_led_mask;
420
421 if (!((1 << mode) & mask)) {
422 rc = ENOTSUP;
423 goto fail1;
424 }
425
426 EFSYS_ASSERT3U(mode, <, EFX_PHY_LED_NMODES);
427 epp->ep_phy_led_mode = mode;
428
429 if ((rc = epop->epo_reconfigure(enp)) != 0)
430 goto fail2;
431
432done:
433 return (0);
434
435fail2:
436 EFSYS_PROBE(fail2);
437fail1:
438 EFSYS_PROBE1(fail1, efx_rc_t, rc);
439
440 return (rc);
441}
442#endif /* EFSYS_OPT_PHY_LED_CONTROL */
443
444 void
445efx_phy_adv_cap_get(
446 __in efx_nic_t *enp,
447 __in uint32_t flag,
448 __out uint32_t *maskp)
449{
450 efx_port_t *epp = &(enp->en_port);
451
452 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
453 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
454
455 switch (flag) {
456 case EFX_PHY_CAP_CURRENT:
457 *maskp = epp->ep_adv_cap_mask;
458 break;
459 case EFX_PHY_CAP_DEFAULT:
460 *maskp = epp->ep_default_adv_cap_mask;
461 break;
462 case EFX_PHY_CAP_PERM:
463 *maskp = epp->ep_phy_cap_mask;
464 break;
465 default:
466 EFSYS_ASSERT(B_FALSE);
467 break;
468 }
469}
470
471 __checkReturn efx_rc_t
472efx_phy_adv_cap_set(
473 __in efx_nic_t *enp,
474 __in uint32_t mask)
475{
476 efx_port_t *epp = &(enp->en_port);
477 efx_phy_ops_t *epop = epp->ep_epop;
478 uint32_t old_mask;
479 efx_rc_t rc;
480
481 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
482 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
483
484 if ((mask & ~epp->ep_phy_cap_mask) != 0) {
485 rc = ENOTSUP;
486 goto fail1;
487 }
488
489 if (epp->ep_adv_cap_mask == mask)
490 goto done;
491
492 old_mask = epp->ep_adv_cap_mask;
493 epp->ep_adv_cap_mask = mask;
494
495 if ((rc = epop->epo_reconfigure(enp)) != 0)
496 goto fail2;
497
498done:
499 return (0);
500
501fail2:
502 EFSYS_PROBE(fail2);
503
504 epp->ep_adv_cap_mask = old_mask;
505 /* Reconfigure for robustness */
506 if (epop->epo_reconfigure(enp) != 0) {
507 /*
508 * We may have an inconsistent view of our advertised speed
509 * capabilities.
510 */
511 EFSYS_ASSERT(0);
512 }
513
514fail1:
515 EFSYS_PROBE1(fail1, efx_rc_t, rc);
516
517 return (rc);
518}
519
520 void
521efx_phy_lp_cap_get(
522 __in efx_nic_t *enp,
523 __out uint32_t *maskp)
524{
525 efx_port_t *epp = &(enp->en_port);
526
527 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
528 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
529
530 *maskp = epp->ep_lp_cap_mask;
531}
532
533 __checkReturn efx_rc_t
534efx_phy_oui_get(
535 __in efx_nic_t *enp,
536 __out uint32_t *ouip)
537{
538 efx_port_t *epp = &(enp->en_port);
539 efx_phy_ops_t *epop = epp->ep_epop;
540
541 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
542 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
543
544 return (epop->epo_oui_get(enp, ouip));
545}
546
547 void
548efx_phy_media_type_get(
549 __in efx_nic_t *enp,
550 __out efx_phy_media_type_t *typep)
551{
552 efx_port_t *epp = &(enp->en_port);
553
554 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
555 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
556
557 if (epp->ep_module_type != EFX_PHY_MEDIA_INVALID)
558 *typep = epp->ep_module_type;
559 else
560 *typep = epp->ep_fixed_port_type;
561}
562
563 __checkReturn efx_rc_t
564efx_phy_module_get_info(
565 __in efx_nic_t *enp,
566 __in uint8_t dev_addr,
567 __in uint8_t offset,
568 __in uint8_t len,
569 __out_bcount(len) uint8_t *data)
570{
571 efx_rc_t rc;
572
573 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
574 EFSYS_ASSERT(data != NULL);
575
576 if ((uint32_t)offset + len > 0xff) {
577 rc = EINVAL;
578 goto fail1;
579 }
580
581 if ((rc = efx_mcdi_phy_module_get_info(enp, dev_addr,
582 offset, len, data)) != 0)
583 goto fail2;
584
585 return (0);
586
587fail2:
588 EFSYS_PROBE(fail2);
589fail1:
590 EFSYS_PROBE1(fail1, efx_rc_t, rc);
591
592 return (rc);
593}
594
595#if EFSYS_OPT_PHY_STATS
596
597#if EFSYS_OPT_NAMES
598
599/* START MKCONFIG GENERATED PhyStatNamesBlock d5f79b4bc2c050fe */
600static const char *__efx_phy_stat_name[] = {
601 "oui",
602 "pma_pmd_link_up",
603 "pma_pmd_rx_fault",
604 "pma_pmd_tx_fault",
605 "pma_pmd_rev_a",
606 "pma_pmd_rev_b",
607 "pma_pmd_rev_c",
608 "pma_pmd_rev_d",
609 "pcs_link_up",
610 "pcs_rx_fault",
611 "pcs_tx_fault",
612 "pcs_ber",
613 "pcs_block_errors",
614 "phy_xs_link_up",
615 "phy_xs_rx_fault",
616 "phy_xs_tx_fault",
617 "phy_xs_align",
618 "phy_xs_sync_a",
619 "phy_xs_sync_b",
620 "phy_xs_sync_c",
621 "phy_xs_sync_d",
622 "an_link_up",
623 "an_master",
624 "an_local_rx_ok",
625 "an_remote_rx_ok",
626 "cl22ext_link_up",
627 "snr_a",
628 "snr_b",
629 "snr_c",
630 "snr_d",
631 "pma_pmd_signal_a",
632 "pma_pmd_signal_b",
633 "pma_pmd_signal_c",
634 "pma_pmd_signal_d",
635 "an_complete",
636 "pma_pmd_rev_major",
637 "pma_pmd_rev_minor",
638 "pma_pmd_rev_micro",
639 "pcs_fw_version_0",
640 "pcs_fw_version_1",
641 "pcs_fw_version_2",
642 "pcs_fw_version_3",
643 "pcs_fw_build_yy",
644 "pcs_fw_build_mm",
645 "pcs_fw_build_dd",
646 "pcs_op_mode",
647};
648
649/* END MKCONFIG GENERATED PhyStatNamesBlock */
650
651 const char *
652efx_phy_stat_name(
653 __in efx_nic_t *enp,
654 __in efx_phy_stat_t type)
655{
656 _NOTE(ARGUNUSED(enp))
657 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
658 EFSYS_ASSERT3U(type, <, EFX_PHY_NSTATS);
659
660 return (__efx_phy_stat_name[type]);
661}
662
663#endif /* EFSYS_OPT_NAMES */
664
665 __checkReturn efx_rc_t
666efx_phy_stats_update(
667 __in efx_nic_t *enp,
668 __in efsys_mem_t *esmp,
669 __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat)
670{
671 efx_port_t *epp = &(enp->en_port);
672 efx_phy_ops_t *epop = epp->ep_epop;
673
674 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
675 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
676
677 return (epop->epo_stats_update(enp, esmp, stat));
678}
679
680#endif /* EFSYS_OPT_PHY_STATS */
681
682#if EFSYS_OPT_PHY_PROPS
683
684#if EFSYS_OPT_NAMES
685 const char *
686efx_phy_prop_name(
687 __in efx_nic_t *enp,
688 __in unsigned int id)
689{
690 efx_port_t *epp = &(enp->en_port);
691 efx_phy_ops_t *epop = epp->ep_epop;
692
693 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
694 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
695
696 return (epop->epo_prop_name(enp, id));
697}
698#endif /* EFSYS_OPT_NAMES */
699
700 __checkReturn efx_rc_t
701efx_phy_prop_get(
702 __in efx_nic_t *enp,
703 __in unsigned int id,
704 __in uint32_t flags,
705 __out uint32_t *valp)
706{
707 efx_port_t *epp = &(enp->en_port);
708 efx_phy_ops_t *epop = epp->ep_epop;
709
710 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
711 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
712
713 return (epop->epo_prop_get(enp, id, flags, valp));
714}
715
716 __checkReturn efx_rc_t
717efx_phy_prop_set(
718 __in efx_nic_t *enp,
719 __in unsigned int id,
720 __in uint32_t val)
721{
722 efx_port_t *epp = &(enp->en_port);
723 efx_phy_ops_t *epop = epp->ep_epop;
724
725 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
726 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
727
728 return (epop->epo_prop_set(enp, id, val));
729}
730#endif /* EFSYS_OPT_PHY_STATS */
731
732#if EFSYS_OPT_BIST
733
734 __checkReturn efx_rc_t
735efx_bist_enable_offline(
736 __in efx_nic_t *enp)
737{
738 efx_port_t *epp = &(enp->en_port);
739 efx_phy_ops_t *epop = epp->ep_epop;
740 efx_rc_t rc;
741
742 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
743
744 if (epop->epo_bist_enable_offline == NULL) {
745 rc = ENOTSUP;
746 goto fail1;
747 }
748
749 if ((rc = epop->epo_bist_enable_offline(enp)) != 0)
750 goto fail2;
751
752 return (0);
753
754fail2:
755 EFSYS_PROBE(fail2);
756fail1:
757 EFSYS_PROBE1(fail1, efx_rc_t, rc);
758
759 return (rc);
760
761}
762
763 __checkReturn efx_rc_t
764efx_bist_start(
765 __in efx_nic_t *enp,
766 __in efx_bist_type_t type)
767{
768 efx_port_t *epp = &(enp->en_port);
769 efx_phy_ops_t *epop = epp->ep_epop;
770 efx_rc_t rc;
771
772 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
773
774 EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
775 EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
776 EFSYS_ASSERT3U(epp->ep_current_bist, ==, EFX_BIST_TYPE_UNKNOWN);
777
778 if (epop->epo_bist_start == NULL) {
779 rc = ENOTSUP;
780 goto fail1;
781 }
782
783 if ((rc = epop->epo_bist_start(enp, type)) != 0)
784 goto fail2;
785
786 epp->ep_current_bist = type;
787
788 return (0);
789
790fail2:
791 EFSYS_PROBE(fail2);
792fail1:
793 EFSYS_PROBE1(fail1, efx_rc_t, rc);
794
795 return (rc);
796}
797
798 __checkReturn efx_rc_t
799efx_bist_poll(
800 __in efx_nic_t *enp,
801 __in efx_bist_type_t type,
802 __out efx_bist_result_t *resultp,
803 __out_opt uint32_t *value_maskp,
804 __out_ecount_opt(count) unsigned long *valuesp,
805 __in size_t count)
806{
807 efx_port_t *epp = &(enp->en_port);
808 efx_phy_ops_t *epop = epp->ep_epop;
809 efx_rc_t rc;
810
811 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
812
813 EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
814 EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
815 EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
816
817 EFSYS_ASSERT(epop->epo_bist_poll != NULL);
818 if (epop->epo_bist_poll == NULL) {
819 rc = ENOTSUP;
820 goto fail1;
821 }
822
823 if ((rc = epop->epo_bist_poll(enp, type, resultp, value_maskp,
824 valuesp, count)) != 0)
825 goto fail2;
826
827 return (0);
828
829fail2:
830 EFSYS_PROBE(fail2);
831fail1:
832 EFSYS_PROBE1(fail1, efx_rc_t, rc);
833
834 return (rc);
835}
836
837 void
838efx_bist_stop(
839 __in efx_nic_t *enp,
840 __in efx_bist_type_t type)
841{
842 efx_port_t *epp = &(enp->en_port);
843 efx_phy_ops_t *epop = epp->ep_epop;
844
845 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
846
847 EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
848 EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
849 EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
850
851 EFSYS_ASSERT(epop->epo_bist_stop != NULL);
852
853 if (epop->epo_bist_stop != NULL)
854 epop->epo_bist_stop(enp, type);
855
856 epp->ep_current_bist = EFX_BIST_TYPE_UNKNOWN;
857}
858
859#endif /* EFSYS_OPT_BIST */
860 void
861efx_phy_unprobe(
862 __in efx_nic_t *enp)
863{
864 efx_port_t *epp = &(enp->en_port);
865
866 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
867
868 epp->ep_epop = NULL;
869
870 epp->ep_adv_cap_mask = 0;
871
872 epp->ep_port = 0;
873 epp->ep_phy_type = 0;
874}
2 * Copyright (c) 2007-2015 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/efx_phy.c 295467 2016-02-10 12:14:56Z arybchik $");
33
34#include "efx.h"
35#include "efx_impl.h"
36#if EFSYS_OPT_FALCON
37#include "falcon_nvram.h"
38#endif
39
40#if EFSYS_OPT_MAC_FALCON_XMAC
41#include "falcon_xmac.h"
42#endif
43
44#if EFSYS_OPT_MAC_FALCON_GMAC
45#include "falcon_gmac.h"
46#endif
47
48#if EFSYS_OPT_PHY_NULL
49#include "nullphy.h"
50#endif
51
52#if EFSYS_OPT_PHY_QT2022C2
53#include "qt2022c2.h"
54#endif
55
56#if EFSYS_OPT_PHY_SFX7101
57#include "sfx7101.h"
58#endif
59
60#if EFSYS_OPT_PHY_TXC43128
61#include "txc43128.h"
62#endif
63
64#if EFSYS_OPT_PHY_SFT9001
65#include "sft9001.h"
66#endif
67
68#if EFSYS_OPT_PHY_QT2025C
69#include "qt2025c.h"
70#endif
71
72#if EFSYS_OPT_PHY_NULL
73static efx_phy_ops_t __efx_phy_null_ops = {
74 NULL, /* epo_power */
75 nullphy_reset, /* epo_reset */
76 nullphy_reconfigure, /* epo_reconfigure */
77 nullphy_verify, /* epo_verify */
78 NULL, /* epo_uplink_check */
79 nullphy_downlink_check, /* epo_downlink_check */
80 nullphy_oui_get, /* epo_oui_get */
81#if EFSYS_OPT_PHY_STATS
82 nullphy_stats_update, /* epo_stats_update */
83#endif /* EFSYS_OPT_PHY_STATS */
84#if EFSYS_OPT_PHY_PROPS
85#if EFSYS_OPT_NAMES
86 nullphy_prop_name, /* epo_prop_name */
87#endif
88 nullphy_prop_get, /* epo_prop_get */
89 nullphy_prop_set, /* epo_prop_set */
90#endif /* EFSYS_OPT_PHY_PROPS */
91#if EFSYS_OPT_BIST
92 NULL, /* epo_bist_enable_offline */
93 NULL, /* epo_bist_start */
94 NULL, /* epo_bist_poll */
95 NULL, /* epo_bist_stop */
96#endif /* EFSYS_OPT_BIST */
97};
98#endif /* EFSYS_OPT_PHY_NULL */
99
100#if EFSYS_OPT_PHY_QT2022C2
101static efx_phy_ops_t __efx_phy_qt2022c2_ops = {
102 NULL, /* epo_power */
103 qt2022c2_reset, /* epo_reset */
104 qt2022c2_reconfigure, /* epo_reconfigure */
105 qt2022c2_verify, /* epo_verify */
106 qt2022c2_uplink_check, /* epo_uplink_check */
107 qt2022c2_downlink_check, /* epo_downlink_check */
108 qt2022c2_oui_get, /* epo_oui_get */
109#if EFSYS_OPT_PHY_STATS
110 qt2022c2_stats_update, /* epo_stats_update */
111#endif /* EFSYS_OPT_PHY_STATS */
112#if EFSYS_OPT_PHY_PROPS
113#if EFSYS_OPT_NAMES
114 qt2022c2_prop_name, /* epo_prop_name */
115#endif
116 qt2022c2_prop_get, /* epo_prop_get */
117 qt2022c2_prop_set, /* epo_prop_set */
118#endif /* EFSYS_OPT_PHY_PROPS */
119#if EFSYS_OPT_BIST
120 NULL, /* epo_bist_enable_offline */
121 NULL, /* epo_bist_start */
122 NULL, /* epo_bist_poll */
123 NULL, /* epo_bist_stop */
124#endif /* EFSYS_OPT_BIST */
125};
126#endif /* EFSYS_OPT_PHY_QT2022C2 */
127
128#if EFSYS_OPT_PHY_SFX7101
129static efx_phy_ops_t __efx_phy_sfx7101_ops = {
130 sfx7101_power, /* epo_power */
131 sfx7101_reset, /* epo_reset */
132 sfx7101_reconfigure, /* epo_reconfigure */
133 sfx7101_verify, /* epo_verify */
134 sfx7101_uplink_check, /* epo_uplink_check */
135 sfx7101_downlink_check, /* epo_downlink_check */
136 sfx7101_oui_get, /* epo_oui_get */
137#if EFSYS_OPT_PHY_STATS
138 sfx7101_stats_update, /* epo_stats_update */
139#endif /* EFSYS_OPT_PHY_STATS */
140#if EFSYS_OPT_PHY_PROPS
141#if EFSYS_OPT_NAMES
142 sfx7101_prop_name, /* epo_prop_name */
143#endif
144 sfx7101_prop_get, /* epo_prop_get */
145 sfx7101_prop_set, /* epo_prop_set */
146#endif /* EFSYS_OPT_PHY_PROPS */
147#if EFSYS_OPT_BIST
148 NULL, /* epo_bist_enable_offline */
149 NULL, /* epo_bist_start */
150 NULL, /* epo_bist_poll */
151 NULL, /* epo_bist_stop */
152#endif /* EFSYS_OPT_BIST */
153};
154#endif /* EFSYS_OPT_PHY_SFX7101 */
155
156#if EFSYS_OPT_PHY_TXC43128
157static efx_phy_ops_t __efx_phy_txc43128_ops = {
158 NULL, /* epo_power */
159 txc43128_reset, /* epo_reset */
160 txc43128_reconfigure, /* epo_reconfigure */
161 txc43128_verify, /* epo_verify */
162 txc43128_uplink_check, /* epo_uplink_check */
163 txc43128_downlink_check, /* epo_downlink_check */
164 txc43128_oui_get, /* epo_oui_get */
165#if EFSYS_OPT_PHY_STATS
166 txc43128_stats_update, /* epo_stats_update */
167#endif /* EFSYS_OPT_PHY_STATS */
168#if EFSYS_OPT_PHY_PROPS
169#if EFSYS_OPT_NAMES
170 txc43128_prop_name, /* epo_prop_name */
171#endif
172 txc43128_prop_get, /* epo_prop_get */
173 txc43128_prop_set, /* epo_prop_set */
174#endif /* EFSYS_OPT_PHY_PROPS */
175#if EFSYS_OPT_BIST
176 NULL, /* epo_bist_enable_offline */
177 NULL, /* epo_bist_start */
178 NULL, /* epo_bist_poll */
179 NULL, /* epo_bist_stop */
180#endif /* EFSYS_OPT_BIST */
181};
182#endif /* EFSYS_OPT_PHY_TXC43128 */
183
184#if EFSYS_OPT_PHY_SFT9001
185static efx_phy_ops_t __efx_phy_sft9001_ops = {
186 NULL, /* epo_power */
187 sft9001_reset, /* epo_reset */
188 sft9001_reconfigure, /* epo_reconfigure */
189 sft9001_verify, /* epo_verify */
190 sft9001_uplink_check, /* epo_uplink_check */
191 sft9001_downlink_check, /* epo_downlink_check */
192 sft9001_oui_get, /* epo_oui_get */
193#if EFSYS_OPT_PHY_STATS
194 sft9001_stats_update, /* epo_stats_update */
195#endif /* EFSYS_OPT_PHY_STATS */
196#if EFSYS_OPT_PHY_PROPS
197#if EFSYS_OPT_NAMES
198 sft9001_prop_name, /* epo_prop_name */
199#endif
200 sft9001_prop_get, /* epo_prop_get */
201 sft9001_prop_set, /* epo_prop_set */
202#endif /* EFSYS_OPT_PHY_PROPS */
203#if EFSYS_OPT_BIST
204 NULL, /* epo_bist_enable_offline */
205 sft9001_bist_start, /* epo_bist_start */
206 sft9001_bist_poll, /* epo_bist_poll */
207 sft9001_bist_stop, /* epo_bist_stop */
208#endif /* EFSYS_OPT_BIST */
209};
210#endif /* EFSYS_OPT_PHY_SFT9001 */
211
212#if EFSYS_OPT_PHY_QT2025C
213static efx_phy_ops_t __efx_phy_qt2025c_ops = {
214 NULL, /* epo_power */
215 qt2025c_reset, /* epo_reset */
216 qt2025c_reconfigure, /* epo_reconfigure */
217 qt2025c_verify, /* epo_verify */
218 qt2025c_uplink_check, /* epo_uplink_check */
219 qt2025c_downlink_check, /* epo_downlink_check */
220 qt2025c_oui_get, /* epo_oui_get */
221#if EFSYS_OPT_PHY_STATS
222 qt2025c_stats_update, /* epo_stats_update */
223#endif /* EFSYS_OPT_PHY_STATS */
224#if EFSYS_OPT_PHY_PROPS
225#if EFSYS_OPT_NAMES
226 qt2025c_prop_name, /* epo_prop_name */
227#endif
228 qt2025c_prop_get, /* epo_prop_get */
229 qt2025c_prop_set, /* epo_prop_set */
230#endif /* EFSYS_OPT_PHY_PROPS */
231#if EFSYS_OPT_BIST
232 NULL, /* epo_bist_enable_offline */
233 NULL, /* epo_bist_start */
234 NULL, /* epo_bist_poll */
235 NULL, /* epo_bist_stop */
236#endif /* EFSYS_OPT_BIST */
237};
238#endif /* EFSYS_OPT_PHY_QT2025C */
239
240#if EFSYS_OPT_SIENA
241static efx_phy_ops_t __efx_phy_siena_ops = {
242 siena_phy_power, /* epo_power */
243 NULL, /* epo_reset */
244 siena_phy_reconfigure, /* epo_reconfigure */
245 siena_phy_verify, /* epo_verify */
246 NULL, /* epo_uplink_check */
247 NULL, /* epo_downlink_check */
248 siena_phy_oui_get, /* epo_oui_get */
249#if EFSYS_OPT_PHY_STATS
250 siena_phy_stats_update, /* epo_stats_update */
251#endif /* EFSYS_OPT_PHY_STATS */
252#if EFSYS_OPT_PHY_PROPS
253#if EFSYS_OPT_NAMES
254 siena_phy_prop_name, /* epo_prop_name */
255#endif
256 siena_phy_prop_get, /* epo_prop_get */
257 siena_phy_prop_set, /* epo_prop_set */
258#endif /* EFSYS_OPT_PHY_PROPS */
259#if EFSYS_OPT_BIST
260 NULL, /* epo_bist_enable_offline */
261 siena_phy_bist_start, /* epo_bist_start */
262 siena_phy_bist_poll, /* epo_bist_poll */
263 siena_phy_bist_stop, /* epo_bist_stop */
264#endif /* EFSYS_OPT_BIST */
265};
266#endif /* EFSYS_OPT_SIENA */
267
268#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
269static efx_phy_ops_t __efx_phy_ef10_ops = {
270 ef10_phy_power, /* epo_power */
271 NULL, /* epo_reset */
272 ef10_phy_reconfigure, /* epo_reconfigure */
273 ef10_phy_verify, /* epo_verify */
274 NULL, /* epo_uplink_check */
275 NULL, /* epo_downlink_check */
276 ef10_phy_oui_get, /* epo_oui_get */
277#if EFSYS_OPT_PHY_STATS
278 ef10_phy_stats_update, /* epo_stats_update */
279#endif /* EFSYS_OPT_PHY_STATS */
280#if EFSYS_OPT_PHY_PROPS
281#if EFSYS_OPT_NAMES
282 ef10_phy_prop_name, /* epo_prop_name */
283#endif
284 ef10_phy_prop_get, /* epo_prop_get */
285 ef10_phy_prop_set, /* epo_prop_set */
286#endif /* EFSYS_OPT_PHY_PROPS */
287#if EFSYS_OPT_BIST
288 /* FIXME: Are these BIST methods appropriate for Medford? */
289 hunt_bist_enable_offline, /* epo_bist_enable_offline */
290 hunt_bist_start, /* epo_bist_start */
291 hunt_bist_poll, /* epo_bist_poll */
292 hunt_bist_stop, /* epo_bist_stop */
293#endif /* EFSYS_OPT_BIST */
294};
295#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
296
297 __checkReturn efx_rc_t
298efx_phy_probe(
299 __in efx_nic_t *enp)
300{
301 efx_port_t *epp = &(enp->en_port);
302 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
303 efx_phy_ops_t *epop;
304 efx_rc_t rc;
305
306 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
307
308 epp->ep_port = encp->enc_port;
309 epp->ep_phy_type = encp->enc_phy_type;
310
311 /* Hook in operations structure */
312 switch (enp->en_family) {
313#if EFSYS_OPT_FALCON
314 case EFX_FAMILY_FALCON:
315 switch (epp->ep_phy_type) {
316#if EFSYS_OPT_PHY_NULL
317 case PHY_TYPE_NONE_DECODE:
318 epop = (efx_phy_ops_t *)&__efx_phy_null_ops;
319 break;
320#endif
321#if EFSYS_OPT_PHY_QT2022C2
322 case PHY_TYPE_QT2022C2_DECODE:
323 epop = (efx_phy_ops_t *)&__efx_phy_qt2022c2_ops;
324 break;
325#endif
326#if EFSYS_OPT_PHY_SFX7101
327 case PHY_TYPE_SFX7101_DECODE:
328 epop = (efx_phy_ops_t *)&__efx_phy_sfx7101_ops;
329 break;
330#endif
331#if EFSYS_OPT_PHY_TXC43128
332 case PHY_TYPE_TXC43128_DECODE:
333 epop = (efx_phy_ops_t *)&__efx_phy_txc43128_ops;
334 break;
335#endif
336#if EFSYS_OPT_PHY_SFT9001
337 case PHY_TYPE_SFT9001A_DECODE:
338 case PHY_TYPE_SFT9001B_DECODE:
339 epop = (efx_phy_ops_t *)&__efx_phy_sft9001_ops;
340 break;
341#endif
342#if EFSYS_OPT_PHY_QT2025C
343 case EFX_PHY_QT2025C:
344 epop = (efx_phy_ops_t *)&__efx_phy_qt2025c_ops;
345 break;
346#endif
347 default:
348 rc = ENOTSUP;
349 goto fail1;
350 }
351 break;
352#endif /* EFSYS_OPT_FALCON */
353#if EFSYS_OPT_SIENA
354 case EFX_FAMILY_SIENA:
355 epop = (efx_phy_ops_t *)&__efx_phy_siena_ops;
356 break;
357#endif /* EFSYS_OPT_SIENA */
358#if EFSYS_OPT_HUNTINGTON
359 case EFX_FAMILY_HUNTINGTON:
360 epop = (efx_phy_ops_t *)&__efx_phy_ef10_ops;
361 break;
362#endif /* EFSYS_OPT_HUNTINGTON */
363#if EFSYS_OPT_MEDFORD
364 case EFX_FAMILY_MEDFORD:
365 epop = (efx_phy_ops_t *)&__efx_phy_ef10_ops;
366 break;
367#endif /* EFSYS_OPT_MEDFORD */
368 default:
369 rc = ENOTSUP;
370 goto fail1;
371 }
372
373 epp->ep_epop = epop;
374
375 return (0);
376
377fail1:
378 EFSYS_PROBE1(fail1, efx_rc_t, rc);
379
380 epp->ep_port = 0;
381 epp->ep_phy_type = 0;
382
383 return (rc);
384}
385
386 __checkReturn efx_rc_t
387efx_phy_verify(
388 __in efx_nic_t *enp)
389{
390 efx_port_t *epp = &(enp->en_port);
391 efx_phy_ops_t *epop = epp->ep_epop;
392
393 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
394 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
395
396 return (epop->epo_verify(enp));
397}
398
399#if EFSYS_OPT_PHY_LED_CONTROL
400
401 __checkReturn efx_rc_t
402efx_phy_led_set(
403 __in efx_nic_t *enp,
404 __in efx_phy_led_mode_t mode)
405{
406 efx_nic_cfg_t *encp = (&enp->en_nic_cfg);
407 efx_port_t *epp = &(enp->en_port);
408 efx_phy_ops_t *epop = epp->ep_epop;
409 uint32_t mask;
410 efx_rc_t rc;
411
412 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
413 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
414
415 if (epp->ep_phy_led_mode == mode)
416 goto done;
417
418 mask = (1 << EFX_PHY_LED_DEFAULT);
419 mask |= encp->enc_led_mask;
420
421 if (!((1 << mode) & mask)) {
422 rc = ENOTSUP;
423 goto fail1;
424 }
425
426 EFSYS_ASSERT3U(mode, <, EFX_PHY_LED_NMODES);
427 epp->ep_phy_led_mode = mode;
428
429 if ((rc = epop->epo_reconfigure(enp)) != 0)
430 goto fail2;
431
432done:
433 return (0);
434
435fail2:
436 EFSYS_PROBE(fail2);
437fail1:
438 EFSYS_PROBE1(fail1, efx_rc_t, rc);
439
440 return (rc);
441}
442#endif /* EFSYS_OPT_PHY_LED_CONTROL */
443
444 void
445efx_phy_adv_cap_get(
446 __in efx_nic_t *enp,
447 __in uint32_t flag,
448 __out uint32_t *maskp)
449{
450 efx_port_t *epp = &(enp->en_port);
451
452 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
453 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
454
455 switch (flag) {
456 case EFX_PHY_CAP_CURRENT:
457 *maskp = epp->ep_adv_cap_mask;
458 break;
459 case EFX_PHY_CAP_DEFAULT:
460 *maskp = epp->ep_default_adv_cap_mask;
461 break;
462 case EFX_PHY_CAP_PERM:
463 *maskp = epp->ep_phy_cap_mask;
464 break;
465 default:
466 EFSYS_ASSERT(B_FALSE);
467 break;
468 }
469}
470
471 __checkReturn efx_rc_t
472efx_phy_adv_cap_set(
473 __in efx_nic_t *enp,
474 __in uint32_t mask)
475{
476 efx_port_t *epp = &(enp->en_port);
477 efx_phy_ops_t *epop = epp->ep_epop;
478 uint32_t old_mask;
479 efx_rc_t rc;
480
481 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
482 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
483
484 if ((mask & ~epp->ep_phy_cap_mask) != 0) {
485 rc = ENOTSUP;
486 goto fail1;
487 }
488
489 if (epp->ep_adv_cap_mask == mask)
490 goto done;
491
492 old_mask = epp->ep_adv_cap_mask;
493 epp->ep_adv_cap_mask = mask;
494
495 if ((rc = epop->epo_reconfigure(enp)) != 0)
496 goto fail2;
497
498done:
499 return (0);
500
501fail2:
502 EFSYS_PROBE(fail2);
503
504 epp->ep_adv_cap_mask = old_mask;
505 /* Reconfigure for robustness */
506 if (epop->epo_reconfigure(enp) != 0) {
507 /*
508 * We may have an inconsistent view of our advertised speed
509 * capabilities.
510 */
511 EFSYS_ASSERT(0);
512 }
513
514fail1:
515 EFSYS_PROBE1(fail1, efx_rc_t, rc);
516
517 return (rc);
518}
519
520 void
521efx_phy_lp_cap_get(
522 __in efx_nic_t *enp,
523 __out uint32_t *maskp)
524{
525 efx_port_t *epp = &(enp->en_port);
526
527 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
528 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
529
530 *maskp = epp->ep_lp_cap_mask;
531}
532
533 __checkReturn efx_rc_t
534efx_phy_oui_get(
535 __in efx_nic_t *enp,
536 __out uint32_t *ouip)
537{
538 efx_port_t *epp = &(enp->en_port);
539 efx_phy_ops_t *epop = epp->ep_epop;
540
541 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
542 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
543
544 return (epop->epo_oui_get(enp, ouip));
545}
546
547 void
548efx_phy_media_type_get(
549 __in efx_nic_t *enp,
550 __out efx_phy_media_type_t *typep)
551{
552 efx_port_t *epp = &(enp->en_port);
553
554 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
555 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
556
557 if (epp->ep_module_type != EFX_PHY_MEDIA_INVALID)
558 *typep = epp->ep_module_type;
559 else
560 *typep = epp->ep_fixed_port_type;
561}
562
563 __checkReturn efx_rc_t
564efx_phy_module_get_info(
565 __in efx_nic_t *enp,
566 __in uint8_t dev_addr,
567 __in uint8_t offset,
568 __in uint8_t len,
569 __out_bcount(len) uint8_t *data)
570{
571 efx_rc_t rc;
572
573 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
574 EFSYS_ASSERT(data != NULL);
575
576 if ((uint32_t)offset + len > 0xff) {
577 rc = EINVAL;
578 goto fail1;
579 }
580
581 if ((rc = efx_mcdi_phy_module_get_info(enp, dev_addr,
582 offset, len, data)) != 0)
583 goto fail2;
584
585 return (0);
586
587fail2:
588 EFSYS_PROBE(fail2);
589fail1:
590 EFSYS_PROBE1(fail1, efx_rc_t, rc);
591
592 return (rc);
593}
594
595#if EFSYS_OPT_PHY_STATS
596
597#if EFSYS_OPT_NAMES
598
599/* START MKCONFIG GENERATED PhyStatNamesBlock d5f79b4bc2c050fe */
600static const char *__efx_phy_stat_name[] = {
601 "oui",
602 "pma_pmd_link_up",
603 "pma_pmd_rx_fault",
604 "pma_pmd_tx_fault",
605 "pma_pmd_rev_a",
606 "pma_pmd_rev_b",
607 "pma_pmd_rev_c",
608 "pma_pmd_rev_d",
609 "pcs_link_up",
610 "pcs_rx_fault",
611 "pcs_tx_fault",
612 "pcs_ber",
613 "pcs_block_errors",
614 "phy_xs_link_up",
615 "phy_xs_rx_fault",
616 "phy_xs_tx_fault",
617 "phy_xs_align",
618 "phy_xs_sync_a",
619 "phy_xs_sync_b",
620 "phy_xs_sync_c",
621 "phy_xs_sync_d",
622 "an_link_up",
623 "an_master",
624 "an_local_rx_ok",
625 "an_remote_rx_ok",
626 "cl22ext_link_up",
627 "snr_a",
628 "snr_b",
629 "snr_c",
630 "snr_d",
631 "pma_pmd_signal_a",
632 "pma_pmd_signal_b",
633 "pma_pmd_signal_c",
634 "pma_pmd_signal_d",
635 "an_complete",
636 "pma_pmd_rev_major",
637 "pma_pmd_rev_minor",
638 "pma_pmd_rev_micro",
639 "pcs_fw_version_0",
640 "pcs_fw_version_1",
641 "pcs_fw_version_2",
642 "pcs_fw_version_3",
643 "pcs_fw_build_yy",
644 "pcs_fw_build_mm",
645 "pcs_fw_build_dd",
646 "pcs_op_mode",
647};
648
649/* END MKCONFIG GENERATED PhyStatNamesBlock */
650
651 const char *
652efx_phy_stat_name(
653 __in efx_nic_t *enp,
654 __in efx_phy_stat_t type)
655{
656 _NOTE(ARGUNUSED(enp))
657 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
658 EFSYS_ASSERT3U(type, <, EFX_PHY_NSTATS);
659
660 return (__efx_phy_stat_name[type]);
661}
662
663#endif /* EFSYS_OPT_NAMES */
664
665 __checkReturn efx_rc_t
666efx_phy_stats_update(
667 __in efx_nic_t *enp,
668 __in efsys_mem_t *esmp,
669 __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat)
670{
671 efx_port_t *epp = &(enp->en_port);
672 efx_phy_ops_t *epop = epp->ep_epop;
673
674 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
675 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
676
677 return (epop->epo_stats_update(enp, esmp, stat));
678}
679
680#endif /* EFSYS_OPT_PHY_STATS */
681
682#if EFSYS_OPT_PHY_PROPS
683
684#if EFSYS_OPT_NAMES
685 const char *
686efx_phy_prop_name(
687 __in efx_nic_t *enp,
688 __in unsigned int id)
689{
690 efx_port_t *epp = &(enp->en_port);
691 efx_phy_ops_t *epop = epp->ep_epop;
692
693 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
694 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
695
696 return (epop->epo_prop_name(enp, id));
697}
698#endif /* EFSYS_OPT_NAMES */
699
700 __checkReturn efx_rc_t
701efx_phy_prop_get(
702 __in efx_nic_t *enp,
703 __in unsigned int id,
704 __in uint32_t flags,
705 __out uint32_t *valp)
706{
707 efx_port_t *epp = &(enp->en_port);
708 efx_phy_ops_t *epop = epp->ep_epop;
709
710 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
711 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
712
713 return (epop->epo_prop_get(enp, id, flags, valp));
714}
715
716 __checkReturn efx_rc_t
717efx_phy_prop_set(
718 __in efx_nic_t *enp,
719 __in unsigned int id,
720 __in uint32_t val)
721{
722 efx_port_t *epp = &(enp->en_port);
723 efx_phy_ops_t *epop = epp->ep_epop;
724
725 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
726 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
727
728 return (epop->epo_prop_set(enp, id, val));
729}
730#endif /* EFSYS_OPT_PHY_STATS */
731
732#if EFSYS_OPT_BIST
733
734 __checkReturn efx_rc_t
735efx_bist_enable_offline(
736 __in efx_nic_t *enp)
737{
738 efx_port_t *epp = &(enp->en_port);
739 efx_phy_ops_t *epop = epp->ep_epop;
740 efx_rc_t rc;
741
742 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
743
744 if (epop->epo_bist_enable_offline == NULL) {
745 rc = ENOTSUP;
746 goto fail1;
747 }
748
749 if ((rc = epop->epo_bist_enable_offline(enp)) != 0)
750 goto fail2;
751
752 return (0);
753
754fail2:
755 EFSYS_PROBE(fail2);
756fail1:
757 EFSYS_PROBE1(fail1, efx_rc_t, rc);
758
759 return (rc);
760
761}
762
763 __checkReturn efx_rc_t
764efx_bist_start(
765 __in efx_nic_t *enp,
766 __in efx_bist_type_t type)
767{
768 efx_port_t *epp = &(enp->en_port);
769 efx_phy_ops_t *epop = epp->ep_epop;
770 efx_rc_t rc;
771
772 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
773
774 EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
775 EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
776 EFSYS_ASSERT3U(epp->ep_current_bist, ==, EFX_BIST_TYPE_UNKNOWN);
777
778 if (epop->epo_bist_start == NULL) {
779 rc = ENOTSUP;
780 goto fail1;
781 }
782
783 if ((rc = epop->epo_bist_start(enp, type)) != 0)
784 goto fail2;
785
786 epp->ep_current_bist = type;
787
788 return (0);
789
790fail2:
791 EFSYS_PROBE(fail2);
792fail1:
793 EFSYS_PROBE1(fail1, efx_rc_t, rc);
794
795 return (rc);
796}
797
798 __checkReturn efx_rc_t
799efx_bist_poll(
800 __in efx_nic_t *enp,
801 __in efx_bist_type_t type,
802 __out efx_bist_result_t *resultp,
803 __out_opt uint32_t *value_maskp,
804 __out_ecount_opt(count) unsigned long *valuesp,
805 __in size_t count)
806{
807 efx_port_t *epp = &(enp->en_port);
808 efx_phy_ops_t *epop = epp->ep_epop;
809 efx_rc_t rc;
810
811 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
812
813 EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
814 EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
815 EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
816
817 EFSYS_ASSERT(epop->epo_bist_poll != NULL);
818 if (epop->epo_bist_poll == NULL) {
819 rc = ENOTSUP;
820 goto fail1;
821 }
822
823 if ((rc = epop->epo_bist_poll(enp, type, resultp, value_maskp,
824 valuesp, count)) != 0)
825 goto fail2;
826
827 return (0);
828
829fail2:
830 EFSYS_PROBE(fail2);
831fail1:
832 EFSYS_PROBE1(fail1, efx_rc_t, rc);
833
834 return (rc);
835}
836
837 void
838efx_bist_stop(
839 __in efx_nic_t *enp,
840 __in efx_bist_type_t type)
841{
842 efx_port_t *epp = &(enp->en_port);
843 efx_phy_ops_t *epop = epp->ep_epop;
844
845 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
846
847 EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
848 EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
849 EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
850
851 EFSYS_ASSERT(epop->epo_bist_stop != NULL);
852
853 if (epop->epo_bist_stop != NULL)
854 epop->epo_bist_stop(enp, type);
855
856 epp->ep_current_bist = EFX_BIST_TYPE_UNKNOWN;
857}
858
859#endif /* EFSYS_OPT_BIST */
860 void
861efx_phy_unprobe(
862 __in efx_nic_t *enp)
863{
864 efx_port_t *epp = &(enp->en_port);
865
866 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
867
868 epp->ep_epop = NULL;
869
870 epp->ep_adv_cap_mask = 0;
871
872 epp->ep_port = 0;
873 epp->ep_phy_type = 0;
874}