1 // SPDX-License-Identifier: GPL-2.0-only
2 /****************************************************************************
3 * Driver for Solarflare network controllers and boards
4 * Copyright 2018 Solarflare Communications Inc.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation, incorporated herein by reference.
11 #include "mcdi_port_common.h"
12 #include "efx_common.h"
14 int efx_mcdi_get_phy_cfg(struct efx_nic
*efx
, struct efx_mcdi_phy_data
*cfg
)
16 MCDI_DECLARE_BUF(outbuf
, MC_CMD_GET_PHY_CFG_OUT_LEN
);
20 BUILD_BUG_ON(MC_CMD_GET_PHY_CFG_IN_LEN
!= 0);
21 BUILD_BUG_ON(MC_CMD_GET_PHY_CFG_OUT_NAME_LEN
!= sizeof(cfg
->name
));
23 rc
= efx_mcdi_rpc(efx
, MC_CMD_GET_PHY_CFG
, NULL
, 0,
24 outbuf
, sizeof(outbuf
), &outlen
);
28 if (outlen
< MC_CMD_GET_PHY_CFG_OUT_LEN
) {
33 cfg
->flags
= MCDI_DWORD(outbuf
, GET_PHY_CFG_OUT_FLAGS
);
34 cfg
->type
= MCDI_DWORD(outbuf
, GET_PHY_CFG_OUT_TYPE
);
36 MCDI_DWORD(outbuf
, GET_PHY_CFG_OUT_SUPPORTED_CAP
);
37 cfg
->channel
= MCDI_DWORD(outbuf
, GET_PHY_CFG_OUT_CHANNEL
);
38 cfg
->port
= MCDI_DWORD(outbuf
, GET_PHY_CFG_OUT_PRT
);
39 cfg
->stats_mask
= MCDI_DWORD(outbuf
, GET_PHY_CFG_OUT_STATS_MASK
);
40 memcpy(cfg
->name
, MCDI_PTR(outbuf
, GET_PHY_CFG_OUT_NAME
),
42 cfg
->media
= MCDI_DWORD(outbuf
, GET_PHY_CFG_OUT_MEDIA_TYPE
);
43 cfg
->mmd_mask
= MCDI_DWORD(outbuf
, GET_PHY_CFG_OUT_MMD_MASK
);
44 memcpy(cfg
->revision
, MCDI_PTR(outbuf
, GET_PHY_CFG_OUT_REVISION
),
45 sizeof(cfg
->revision
));
50 netif_err(efx
, hw
, efx
->net_dev
, "%s: failed rc=%d\n", __func__
, rc
);
54 void efx_link_set_advertising(struct efx_nic
*efx
,
55 const unsigned long *advertising
)
57 memcpy(efx
->link_advertising
, advertising
,
58 sizeof(__ETHTOOL_DECLARE_LINK_MODE_MASK()));
60 efx
->link_advertising
[0] |= ADVERTISED_Autoneg
;
61 if (advertising
[0] & ADVERTISED_Pause
)
62 efx
->wanted_fc
|= (EFX_FC_TX
| EFX_FC_RX
);
64 efx
->wanted_fc
&= ~(EFX_FC_TX
| EFX_FC_RX
);
65 if (advertising
[0] & ADVERTISED_Asym_Pause
)
66 efx
->wanted_fc
^= EFX_FC_TX
;
69 int efx_mcdi_set_link(struct efx_nic
*efx
, u32 capabilities
,
70 u32 flags
, u32 loopback_mode
, u32 loopback_speed
)
72 MCDI_DECLARE_BUF(inbuf
, MC_CMD_SET_LINK_IN_LEN
);
75 BUILD_BUG_ON(MC_CMD_SET_LINK_OUT_LEN
!= 0);
77 MCDI_SET_DWORD(inbuf
, SET_LINK_IN_CAP
, capabilities
);
78 MCDI_SET_DWORD(inbuf
, SET_LINK_IN_FLAGS
, flags
);
79 MCDI_SET_DWORD(inbuf
, SET_LINK_IN_LOOPBACK_MODE
, loopback_mode
);
80 MCDI_SET_DWORD(inbuf
, SET_LINK_IN_LOOPBACK_SPEED
, loopback_speed
);
82 rc
= efx_mcdi_rpc(efx
, MC_CMD_SET_LINK
, inbuf
, sizeof(inbuf
),
87 int efx_mcdi_loopback_modes(struct efx_nic
*efx
, u64
*loopback_modes
)
89 MCDI_DECLARE_BUF(outbuf
, MC_CMD_GET_LOOPBACK_MODES_OUT_LEN
);
93 rc
= efx_mcdi_rpc(efx
, MC_CMD_GET_LOOPBACK_MODES
, NULL
, 0,
94 outbuf
, sizeof(outbuf
), &outlen
);
98 if (outlen
< (MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST
+
99 MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN
)) {
104 *loopback_modes
= MCDI_QWORD(outbuf
, GET_LOOPBACK_MODES_OUT_SUGGESTED
);
109 netif_err(efx
, hw
, efx
->net_dev
, "%s: failed rc=%d\n", __func__
, rc
);
113 void mcdi_to_ethtool_linkset(u32 media
, u32 cap
, unsigned long *linkset
)
115 #define SET_BIT(name) __set_bit(ETHTOOL_LINK_MODE_ ## name ## _BIT, \
118 bitmap_zero(linkset
, __ETHTOOL_LINK_MODE_MASK_NBITS
);
120 case MC_CMD_MEDIA_KX4
:
122 if (cap
& (1 << MC_CMD_PHY_CAP_1000FDX_LBN
))
123 SET_BIT(1000baseKX_Full
);
124 if (cap
& (1 << MC_CMD_PHY_CAP_10000FDX_LBN
))
125 SET_BIT(10000baseKX4_Full
);
126 if (cap
& (1 << MC_CMD_PHY_CAP_40000FDX_LBN
))
127 SET_BIT(40000baseKR4_Full
);
130 case MC_CMD_MEDIA_XFP
:
131 case MC_CMD_MEDIA_SFP_PLUS
:
132 case MC_CMD_MEDIA_QSFP_PLUS
:
134 if (cap
& (1 << MC_CMD_PHY_CAP_1000FDX_LBN
))
135 SET_BIT(1000baseT_Full
);
136 if (cap
& (1 << MC_CMD_PHY_CAP_10000FDX_LBN
))
137 SET_BIT(10000baseT_Full
);
138 if (cap
& (1 << MC_CMD_PHY_CAP_40000FDX_LBN
))
139 SET_BIT(40000baseCR4_Full
);
140 if (cap
& (1 << MC_CMD_PHY_CAP_100000FDX_LBN
))
141 SET_BIT(100000baseCR4_Full
);
142 if (cap
& (1 << MC_CMD_PHY_CAP_25000FDX_LBN
))
143 SET_BIT(25000baseCR_Full
);
144 if (cap
& (1 << MC_CMD_PHY_CAP_50000FDX_LBN
))
145 SET_BIT(50000baseCR2_Full
);
148 case MC_CMD_MEDIA_BASE_T
:
150 if (cap
& (1 << MC_CMD_PHY_CAP_10HDX_LBN
))
151 SET_BIT(10baseT_Half
);
152 if (cap
& (1 << MC_CMD_PHY_CAP_10FDX_LBN
))
153 SET_BIT(10baseT_Full
);
154 if (cap
& (1 << MC_CMD_PHY_CAP_100HDX_LBN
))
155 SET_BIT(100baseT_Half
);
156 if (cap
& (1 << MC_CMD_PHY_CAP_100FDX_LBN
))
157 SET_BIT(100baseT_Full
);
158 if (cap
& (1 << MC_CMD_PHY_CAP_1000HDX_LBN
))
159 SET_BIT(1000baseT_Half
);
160 if (cap
& (1 << MC_CMD_PHY_CAP_1000FDX_LBN
))
161 SET_BIT(1000baseT_Full
);
162 if (cap
& (1 << MC_CMD_PHY_CAP_10000FDX_LBN
))
163 SET_BIT(10000baseT_Full
);
167 if (cap
& (1 << MC_CMD_PHY_CAP_PAUSE_LBN
))
169 if (cap
& (1 << MC_CMD_PHY_CAP_ASYM_LBN
))
171 if (cap
& (1 << MC_CMD_PHY_CAP_AN_LBN
))
177 u32
ethtool_linkset_to_mcdi_cap(const unsigned long *linkset
)
181 #define TEST_BIT(name) test_bit(ETHTOOL_LINK_MODE_ ## name ## _BIT, \
184 if (TEST_BIT(10baseT_Half
))
185 result
|= (1 << MC_CMD_PHY_CAP_10HDX_LBN
);
186 if (TEST_BIT(10baseT_Full
))
187 result
|= (1 << MC_CMD_PHY_CAP_10FDX_LBN
);
188 if (TEST_BIT(100baseT_Half
))
189 result
|= (1 << MC_CMD_PHY_CAP_100HDX_LBN
);
190 if (TEST_BIT(100baseT_Full
))
191 result
|= (1 << MC_CMD_PHY_CAP_100FDX_LBN
);
192 if (TEST_BIT(1000baseT_Half
))
193 result
|= (1 << MC_CMD_PHY_CAP_1000HDX_LBN
);
194 if (TEST_BIT(1000baseT_Full
) || TEST_BIT(1000baseKX_Full
))
195 result
|= (1 << MC_CMD_PHY_CAP_1000FDX_LBN
);
196 if (TEST_BIT(10000baseT_Full
) || TEST_BIT(10000baseKX4_Full
))
197 result
|= (1 << MC_CMD_PHY_CAP_10000FDX_LBN
);
198 if (TEST_BIT(40000baseCR4_Full
) || TEST_BIT(40000baseKR4_Full
))
199 result
|= (1 << MC_CMD_PHY_CAP_40000FDX_LBN
);
200 if (TEST_BIT(100000baseCR4_Full
))
201 result
|= (1 << MC_CMD_PHY_CAP_100000FDX_LBN
);
202 if (TEST_BIT(25000baseCR_Full
))
203 result
|= (1 << MC_CMD_PHY_CAP_25000FDX_LBN
);
204 if (TEST_BIT(50000baseCR2_Full
))
205 result
|= (1 << MC_CMD_PHY_CAP_50000FDX_LBN
);
207 result
|= (1 << MC_CMD_PHY_CAP_PAUSE_LBN
);
208 if (TEST_BIT(Asym_Pause
))
209 result
|= (1 << MC_CMD_PHY_CAP_ASYM_LBN
);
210 if (TEST_BIT(Autoneg
))
211 result
|= (1 << MC_CMD_PHY_CAP_AN_LBN
);
218 u32
efx_get_mcdi_phy_flags(struct efx_nic
*efx
)
220 struct efx_mcdi_phy_data
*phy_cfg
= efx
->phy_data
;
221 enum efx_phy_mode mode
, supported
;
224 /* TODO: Advertise the capabilities supported by this PHY */
226 if (phy_cfg
->flags
& (1 << MC_CMD_GET_PHY_CFG_OUT_TXDIS_LBN
))
227 supported
|= PHY_MODE_TX_DISABLED
;
228 if (phy_cfg
->flags
& (1 << MC_CMD_GET_PHY_CFG_OUT_LOWPOWER_LBN
))
229 supported
|= PHY_MODE_LOW_POWER
;
230 if (phy_cfg
->flags
& (1 << MC_CMD_GET_PHY_CFG_OUT_POWEROFF_LBN
))
231 supported
|= PHY_MODE_OFF
;
233 mode
= efx
->phy_mode
& supported
;
236 if (mode
& PHY_MODE_TX_DISABLED
)
237 flags
|= (1 << MC_CMD_SET_LINK_IN_TXDIS_LBN
);
238 if (mode
& PHY_MODE_LOW_POWER
)
239 flags
|= (1 << MC_CMD_SET_LINK_IN_LOWPOWER_LBN
);
240 if (mode
& PHY_MODE_OFF
)
241 flags
|= (1 << MC_CMD_SET_LINK_IN_POWEROFF_LBN
);
246 u8
mcdi_to_ethtool_media(u32 media
)
249 case MC_CMD_MEDIA_XAUI
:
250 case MC_CMD_MEDIA_CX4
:
251 case MC_CMD_MEDIA_KX4
:
254 case MC_CMD_MEDIA_XFP
:
255 case MC_CMD_MEDIA_SFP_PLUS
:
256 case MC_CMD_MEDIA_QSFP_PLUS
:
259 case MC_CMD_MEDIA_BASE_T
:
267 void efx_mcdi_phy_decode_link(struct efx_nic
*efx
,
268 struct efx_link_state
*link_state
,
269 u32 speed
, u32 flags
, u32 fcntl
)
272 case MC_CMD_FCNTL_AUTO
:
273 WARN_ON(1); /* This is not a link mode */
274 link_state
->fc
= EFX_FC_AUTO
| EFX_FC_TX
| EFX_FC_RX
;
276 case MC_CMD_FCNTL_BIDIR
:
277 link_state
->fc
= EFX_FC_TX
| EFX_FC_RX
;
279 case MC_CMD_FCNTL_RESPOND
:
280 link_state
->fc
= EFX_FC_RX
;
285 case MC_CMD_FCNTL_OFF
:
290 link_state
->up
= !!(flags
& (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN
));
291 link_state
->fd
= !!(flags
& (1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN
));
292 link_state
->speed
= speed
;
295 /* The semantics of the ethtool FEC mode bitmask are not well defined,
296 * particularly the meaning of combinations of bits. Which means we get to
297 * define our own semantics, as follows:
298 * OFF overrides any other bits, and means "disable all FEC" (with the
299 * exception of 25G KR4/CR4, where it is not possible to reject it if AN
300 * partner requests it).
301 * AUTO on its own means use cable requirements and link partner autoneg with
302 * fw-default preferences for the cable type.
303 * AUTO and either RS or BASER means use the specified FEC type if cable and
304 * link partner support it, otherwise autoneg/fw-default.
305 * RS or BASER alone means use the specified FEC type if cable and link partner
306 * support it and either requests it, otherwise no FEC.
307 * Both RS and BASER (whether AUTO or not) means use FEC if cable and link
308 * partner support it, preferring RS to BASER.
310 u32
ethtool_fec_caps_to_mcdi(u32 ethtool_cap
)
314 if (ethtool_cap
& ETHTOOL_FEC_OFF
)
317 if (ethtool_cap
& ETHTOOL_FEC_AUTO
)
318 ret
|= (1 << MC_CMD_PHY_CAP_BASER_FEC_LBN
) |
319 (1 << MC_CMD_PHY_CAP_25G_BASER_FEC_LBN
) |
320 (1 << MC_CMD_PHY_CAP_RS_FEC_LBN
);
321 if (ethtool_cap
& ETHTOOL_FEC_RS
)
322 ret
|= (1 << MC_CMD_PHY_CAP_RS_FEC_LBN
) |
323 (1 << MC_CMD_PHY_CAP_RS_FEC_REQUESTED_LBN
);
324 if (ethtool_cap
& ETHTOOL_FEC_BASER
)
325 ret
|= (1 << MC_CMD_PHY_CAP_BASER_FEC_LBN
) |
326 (1 << MC_CMD_PHY_CAP_25G_BASER_FEC_LBN
) |
327 (1 << MC_CMD_PHY_CAP_BASER_FEC_REQUESTED_LBN
) |
328 (1 << MC_CMD_PHY_CAP_25G_BASER_FEC_REQUESTED_LBN
);
332 /* Invert ethtool_fec_caps_to_mcdi. There are two combinations that function
333 * can never produce, (baser xor rs) and neither req; the implementation below
334 * maps both of those to AUTO. This should never matter, and it's not clear
335 * what a better mapping would be anyway.
337 u32
mcdi_fec_caps_to_ethtool(u32 caps
, bool is_25g
)
339 bool rs
= caps
& (1 << MC_CMD_PHY_CAP_RS_FEC_LBN
),
340 rs_req
= caps
& (1 << MC_CMD_PHY_CAP_RS_FEC_REQUESTED_LBN
),
341 baser
= is_25g
? caps
& (1 << MC_CMD_PHY_CAP_25G_BASER_FEC_LBN
)
342 : caps
& (1 << MC_CMD_PHY_CAP_BASER_FEC_LBN
),
343 baser_req
= is_25g
? caps
& (1 << MC_CMD_PHY_CAP_25G_BASER_FEC_REQUESTED_LBN
)
344 : caps
& (1 << MC_CMD_PHY_CAP_BASER_FEC_REQUESTED_LBN
);
347 return ETHTOOL_FEC_OFF
;
348 return (rs_req
? ETHTOOL_FEC_RS
: 0) |
349 (baser_req
? ETHTOOL_FEC_BASER
: 0) |
350 (baser
== baser_req
&& rs
== rs_req
? 0 : ETHTOOL_FEC_AUTO
);
353 /* Verify that the forced flow control settings (!EFX_FC_AUTO) are
354 * supported by the link partner. Warn the user if this isn't the case
356 void efx_mcdi_phy_check_fcntl(struct efx_nic
*efx
, u32 lpa
)
358 struct efx_mcdi_phy_data
*phy_cfg
= efx
->phy_data
;
361 /* The link partner capabilities are only relevant if the
362 * link supports flow control autonegotiation
364 if (~phy_cfg
->supported_cap
& (1 << MC_CMD_PHY_CAP_AN_LBN
))
367 /* If flow control autoneg is supported and enabled, then fine */
368 if (efx
->wanted_fc
& EFX_FC_AUTO
)
372 if (lpa
& (1 << MC_CMD_PHY_CAP_PAUSE_LBN
))
373 rmtadv
|= ADVERTISED_Pause
;
374 if (lpa
& (1 << MC_CMD_PHY_CAP_ASYM_LBN
))
375 rmtadv
|= ADVERTISED_Asym_Pause
;
377 if ((efx
->wanted_fc
& EFX_FC_TX
) && rmtadv
== ADVERTISED_Asym_Pause
)
378 netif_err(efx
, link
, efx
->net_dev
,
379 "warning: link partner doesn't support pause frames");
382 bool efx_mcdi_phy_poll(struct efx_nic
*efx
)
384 struct efx_link_state old_state
= efx
->link_state
;
385 MCDI_DECLARE_BUF(outbuf
, MC_CMD_GET_LINK_OUT_LEN
);
388 WARN_ON(!mutex_is_locked(&efx
->mac_lock
));
390 BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN
!= 0);
392 rc
= efx_mcdi_rpc(efx
, MC_CMD_GET_LINK
, NULL
, 0,
393 outbuf
, sizeof(outbuf
), NULL
);
395 efx
->link_state
.up
= false;
397 efx_mcdi_phy_decode_link(
398 efx
, &efx
->link_state
,
399 MCDI_DWORD(outbuf
, GET_LINK_OUT_LINK_SPEED
),
400 MCDI_DWORD(outbuf
, GET_LINK_OUT_FLAGS
),
401 MCDI_DWORD(outbuf
, GET_LINK_OUT_FCNTL
));
403 return !efx_link_state_equal(&efx
->link_state
, &old_state
);
406 int efx_mcdi_phy_get_fecparam(struct efx_nic
*efx
, struct ethtool_fecparam
*fec
)
408 MCDI_DECLARE_BUF(outbuf
, MC_CMD_GET_LINK_OUT_V2_LEN
);
409 u32 caps
, active
, speed
; /* MCDI format */
414 BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN
!= 0);
415 rc
= efx_mcdi_rpc(efx
, MC_CMD_GET_LINK
, NULL
, 0,
416 outbuf
, sizeof(outbuf
), &outlen
);
419 if (outlen
< MC_CMD_GET_LINK_OUT_V2_LEN
)
422 /* behaviour for 25G/50G links depends on 25G BASER bit */
423 speed
= MCDI_DWORD(outbuf
, GET_LINK_OUT_V2_LINK_SPEED
);
424 is_25g
= speed
== 25000 || speed
== 50000;
426 caps
= MCDI_DWORD(outbuf
, GET_LINK_OUT_V2_CAP
);
427 fec
->fec
= mcdi_fec_caps_to_ethtool(caps
, is_25g
);
428 /* BASER is never supported on 100G */
430 fec
->fec
&= ~ETHTOOL_FEC_BASER
;
432 active
= MCDI_DWORD(outbuf
, GET_LINK_OUT_V2_FEC_TYPE
);
434 case MC_CMD_FEC_NONE
:
435 fec
->active_fec
= ETHTOOL_FEC_OFF
;
437 case MC_CMD_FEC_BASER
:
438 fec
->active_fec
= ETHTOOL_FEC_BASER
;
441 fec
->active_fec
= ETHTOOL_FEC_RS
;
444 netif_warn(efx
, hw
, efx
->net_dev
,
445 "Firmware reports unrecognised FEC_TYPE %u\n",
447 /* We don't know what firmware has picked. AUTO is as good a
448 * "can't happen" value as any other.
450 fec
->active_fec
= ETHTOOL_FEC_AUTO
;
457 int efx_mcdi_phy_test_alive(struct efx_nic
*efx
)
459 MCDI_DECLARE_BUF(outbuf
, MC_CMD_GET_PHY_STATE_OUT_LEN
);
463 BUILD_BUG_ON(MC_CMD_GET_PHY_STATE_IN_LEN
!= 0);
465 rc
= efx_mcdi_rpc(efx
, MC_CMD_GET_PHY_STATE
, NULL
, 0,
466 outbuf
, sizeof(outbuf
), &outlen
);
470 if (outlen
< MC_CMD_GET_PHY_STATE_OUT_LEN
)
472 if (MCDI_DWORD(outbuf
, GET_PHY_STATE_OUT_STATE
) != MC_CMD_PHY_STATE_OK
)
478 int efx_mcdi_set_mac(struct efx_nic
*efx
)
481 MCDI_DECLARE_BUF(cmdbytes
, MC_CMD_SET_MAC_IN_LEN
);
483 BUILD_BUG_ON(MC_CMD_SET_MAC_OUT_LEN
!= 0);
485 /* This has no effect on EF10 */
486 ether_addr_copy(MCDI_PTR(cmdbytes
, SET_MAC_IN_ADDR
),
487 efx
->net_dev
->dev_addr
);
489 MCDI_SET_DWORD(cmdbytes
, SET_MAC_IN_MTU
,
490 EFX_MAX_FRAME_LEN(efx
->net_dev
->mtu
));
491 MCDI_SET_DWORD(cmdbytes
, SET_MAC_IN_DRAIN
, 0);
493 /* Set simple MAC filter for Siena */
494 MCDI_POPULATE_DWORD_1(cmdbytes
, SET_MAC_IN_REJECT
,
495 SET_MAC_IN_REJECT_UNCST
, efx
->unicast_filter
);
497 MCDI_POPULATE_DWORD_1(cmdbytes
, SET_MAC_IN_FLAGS
,
498 SET_MAC_IN_FLAG_INCLUDE_FCS
,
499 !!(efx
->net_dev
->features
& NETIF_F_RXFCS
));
501 switch (efx
->wanted_fc
) {
502 case EFX_FC_RX
| EFX_FC_TX
:
503 fcntl
= MC_CMD_FCNTL_BIDIR
;
506 fcntl
= MC_CMD_FCNTL_RESPOND
;
509 fcntl
= MC_CMD_FCNTL_OFF
;
512 if (efx
->wanted_fc
& EFX_FC_AUTO
)
513 fcntl
= MC_CMD_FCNTL_AUTO
;
515 fcntl
= MC_CMD_FCNTL_OFF
;
517 MCDI_SET_DWORD(cmdbytes
, SET_MAC_IN_FCNTL
, fcntl
);
519 return efx_mcdi_rpc(efx
, MC_CMD_SET_MAC
, cmdbytes
, sizeof(cmdbytes
),
523 /* Get physical port number (EF10 only; on Siena it is same as PF number) */
524 int efx_mcdi_port_get_number(struct efx_nic
*efx
)
526 MCDI_DECLARE_BUF(outbuf
, MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN
);
529 rc
= efx_mcdi_rpc(efx
, MC_CMD_GET_PORT_ASSIGNMENT
, NULL
, 0,
530 outbuf
, sizeof(outbuf
), NULL
);
534 return MCDI_DWORD(outbuf
, GET_PORT_ASSIGNMENT_OUT_PORT
);
537 static unsigned int efx_mcdi_event_link_speed
[] = {
538 [MCDI_EVENT_LINKCHANGE_SPEED_100M
] = 100,
539 [MCDI_EVENT_LINKCHANGE_SPEED_1G
] = 1000,
540 [MCDI_EVENT_LINKCHANGE_SPEED_10G
] = 10000,
541 [MCDI_EVENT_LINKCHANGE_SPEED_40G
] = 40000,
542 [MCDI_EVENT_LINKCHANGE_SPEED_25G
] = 25000,
543 [MCDI_EVENT_LINKCHANGE_SPEED_50G
] = 50000,
544 [MCDI_EVENT_LINKCHANGE_SPEED_100G
] = 100000,
547 void efx_mcdi_process_link_change(struct efx_nic
*efx
, efx_qword_t
*ev
)
549 u32 flags
, fcntl
, speed
, lpa
;
551 speed
= EFX_QWORD_FIELD(*ev
, MCDI_EVENT_LINKCHANGE_SPEED
);
552 EFX_WARN_ON_PARANOID(speed
>= ARRAY_SIZE(efx_mcdi_event_link_speed
));
553 speed
= efx_mcdi_event_link_speed
[speed
];
555 flags
= EFX_QWORD_FIELD(*ev
, MCDI_EVENT_LINKCHANGE_LINK_FLAGS
);
556 fcntl
= EFX_QWORD_FIELD(*ev
, MCDI_EVENT_LINKCHANGE_FCNTL
);
557 lpa
= EFX_QWORD_FIELD(*ev
, MCDI_EVENT_LINKCHANGE_LP_CAP
);
559 /* efx->link_state is only modified by efx_mcdi_phy_get_link(),
560 * which is only run after flushing the event queues. Therefore, it
561 * is safe to modify the link state outside of the mac_lock here.
563 efx_mcdi_phy_decode_link(efx
, &efx
->link_state
, speed
, flags
, fcntl
);
565 efx_mcdi_phy_check_fcntl(efx
, lpa
);
567 efx_link_status_changed(efx
);