1 // SPDX-License-Identifier: GPL-2.0-only
2 /****************************************************************************
3 * Driver for Solarflare network controllers and boards
4 * Copyright 2009-2013 Solarflare Communications Inc.
8 * Driver for PHY related operations via MCDI.
11 #include <linux/slab.h>
14 #include "mcdi_pcol.h"
17 #include "mcdi_port_common.h"
19 static int efx_mcdi_mdio_read(struct net_device
*net_dev
,
20 int prtad
, int devad
, u16 addr
)
22 struct efx_nic
*efx
= netdev_priv(net_dev
);
23 MCDI_DECLARE_BUF(inbuf
, MC_CMD_MDIO_READ_IN_LEN
);
24 MCDI_DECLARE_BUF(outbuf
, MC_CMD_MDIO_READ_OUT_LEN
);
28 MCDI_SET_DWORD(inbuf
, MDIO_READ_IN_BUS
, efx
->mdio_bus
);
29 MCDI_SET_DWORD(inbuf
, MDIO_READ_IN_PRTAD
, prtad
);
30 MCDI_SET_DWORD(inbuf
, MDIO_READ_IN_DEVAD
, devad
);
31 MCDI_SET_DWORD(inbuf
, MDIO_READ_IN_ADDR
, addr
);
33 rc
= efx_mcdi_rpc(efx
, MC_CMD_MDIO_READ
, inbuf
, sizeof(inbuf
),
34 outbuf
, sizeof(outbuf
), &outlen
);
38 if (MCDI_DWORD(outbuf
, MDIO_READ_OUT_STATUS
) !=
39 MC_CMD_MDIO_STATUS_GOOD
)
42 return (u16
)MCDI_DWORD(outbuf
, MDIO_READ_OUT_VALUE
);
45 static int efx_mcdi_mdio_write(struct net_device
*net_dev
,
46 int prtad
, int devad
, u16 addr
, u16 value
)
48 struct efx_nic
*efx
= netdev_priv(net_dev
);
49 MCDI_DECLARE_BUF(inbuf
, MC_CMD_MDIO_WRITE_IN_LEN
);
50 MCDI_DECLARE_BUF(outbuf
, MC_CMD_MDIO_WRITE_OUT_LEN
);
54 MCDI_SET_DWORD(inbuf
, MDIO_WRITE_IN_BUS
, efx
->mdio_bus
);
55 MCDI_SET_DWORD(inbuf
, MDIO_WRITE_IN_PRTAD
, prtad
);
56 MCDI_SET_DWORD(inbuf
, MDIO_WRITE_IN_DEVAD
, devad
);
57 MCDI_SET_DWORD(inbuf
, MDIO_WRITE_IN_ADDR
, addr
);
58 MCDI_SET_DWORD(inbuf
, MDIO_WRITE_IN_VALUE
, value
);
60 rc
= efx_mcdi_rpc(efx
, MC_CMD_MDIO_WRITE
, inbuf
, sizeof(inbuf
),
61 outbuf
, sizeof(outbuf
), &outlen
);
65 if (MCDI_DWORD(outbuf
, MDIO_WRITE_OUT_STATUS
) !=
66 MC_CMD_MDIO_STATUS_GOOD
)
72 static int efx_mcdi_phy_probe(struct efx_nic
*efx
)
74 struct efx_mcdi_phy_data
*phy_data
;
75 MCDI_DECLARE_BUF(outbuf
, MC_CMD_GET_LINK_OUT_LEN
);
79 /* Initialise and populate phy_data */
80 phy_data
= kzalloc(sizeof(*phy_data
), GFP_KERNEL
);
84 rc
= efx_mcdi_get_phy_cfg(efx
, phy_data
);
88 /* Read initial link advertisement */
89 BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN
!= 0);
90 rc
= efx_mcdi_rpc(efx
, MC_CMD_GET_LINK
, NULL
, 0,
91 outbuf
, sizeof(outbuf
), NULL
);
95 /* Fill out nic state */
96 efx
->phy_data
= phy_data
;
97 efx
->phy_type
= phy_data
->type
;
99 efx
->mdio_bus
= phy_data
->channel
;
100 efx
->mdio
.prtad
= phy_data
->port
;
101 efx
->mdio
.mmds
= phy_data
->mmd_mask
& ~(1 << MC_CMD_MMD_CLAUSE22
);
102 efx
->mdio
.mode_support
= 0;
103 if (phy_data
->mmd_mask
& (1 << MC_CMD_MMD_CLAUSE22
))
104 efx
->mdio
.mode_support
|= MDIO_SUPPORTS_C22
;
105 if (phy_data
->mmd_mask
& ~(1 << MC_CMD_MMD_CLAUSE22
))
106 efx
->mdio
.mode_support
|= MDIO_SUPPORTS_C45
| MDIO_EMULATE_C22
;
108 caps
= MCDI_DWORD(outbuf
, GET_LINK_OUT_CAP
);
109 if (caps
& (1 << MC_CMD_PHY_CAP_AN_LBN
))
110 mcdi_to_ethtool_linkset(phy_data
->media
, caps
,
111 efx
->link_advertising
);
113 phy_data
->forced_cap
= caps
;
115 /* Assert that we can map efx -> mcdi loopback modes */
116 BUILD_BUG_ON(LOOPBACK_NONE
!= MC_CMD_LOOPBACK_NONE
);
117 BUILD_BUG_ON(LOOPBACK_DATA
!= MC_CMD_LOOPBACK_DATA
);
118 BUILD_BUG_ON(LOOPBACK_GMAC
!= MC_CMD_LOOPBACK_GMAC
);
119 BUILD_BUG_ON(LOOPBACK_XGMII
!= MC_CMD_LOOPBACK_XGMII
);
120 BUILD_BUG_ON(LOOPBACK_XGXS
!= MC_CMD_LOOPBACK_XGXS
);
121 BUILD_BUG_ON(LOOPBACK_XAUI
!= MC_CMD_LOOPBACK_XAUI
);
122 BUILD_BUG_ON(LOOPBACK_GMII
!= MC_CMD_LOOPBACK_GMII
);
123 BUILD_BUG_ON(LOOPBACK_SGMII
!= MC_CMD_LOOPBACK_SGMII
);
124 BUILD_BUG_ON(LOOPBACK_XGBR
!= MC_CMD_LOOPBACK_XGBR
);
125 BUILD_BUG_ON(LOOPBACK_XFI
!= MC_CMD_LOOPBACK_XFI
);
126 BUILD_BUG_ON(LOOPBACK_XAUI_FAR
!= MC_CMD_LOOPBACK_XAUI_FAR
);
127 BUILD_BUG_ON(LOOPBACK_GMII_FAR
!= MC_CMD_LOOPBACK_GMII_FAR
);
128 BUILD_BUG_ON(LOOPBACK_SGMII_FAR
!= MC_CMD_LOOPBACK_SGMII_FAR
);
129 BUILD_BUG_ON(LOOPBACK_XFI_FAR
!= MC_CMD_LOOPBACK_XFI_FAR
);
130 BUILD_BUG_ON(LOOPBACK_GPHY
!= MC_CMD_LOOPBACK_GPHY
);
131 BUILD_BUG_ON(LOOPBACK_PHYXS
!= MC_CMD_LOOPBACK_PHYXS
);
132 BUILD_BUG_ON(LOOPBACK_PCS
!= MC_CMD_LOOPBACK_PCS
);
133 BUILD_BUG_ON(LOOPBACK_PMAPMD
!= MC_CMD_LOOPBACK_PMAPMD
);
134 BUILD_BUG_ON(LOOPBACK_XPORT
!= MC_CMD_LOOPBACK_XPORT
);
135 BUILD_BUG_ON(LOOPBACK_XGMII_WS
!= MC_CMD_LOOPBACK_XGMII_WS
);
136 BUILD_BUG_ON(LOOPBACK_XAUI_WS
!= MC_CMD_LOOPBACK_XAUI_WS
);
137 BUILD_BUG_ON(LOOPBACK_XAUI_WS_FAR
!= MC_CMD_LOOPBACK_XAUI_WS_FAR
);
138 BUILD_BUG_ON(LOOPBACK_XAUI_WS_NEAR
!= MC_CMD_LOOPBACK_XAUI_WS_NEAR
);
139 BUILD_BUG_ON(LOOPBACK_GMII_WS
!= MC_CMD_LOOPBACK_GMII_WS
);
140 BUILD_BUG_ON(LOOPBACK_XFI_WS
!= MC_CMD_LOOPBACK_XFI_WS
);
141 BUILD_BUG_ON(LOOPBACK_XFI_WS_FAR
!= MC_CMD_LOOPBACK_XFI_WS_FAR
);
142 BUILD_BUG_ON(LOOPBACK_PHYXS_WS
!= MC_CMD_LOOPBACK_PHYXS_WS
);
144 rc
= efx_mcdi_loopback_modes(efx
, &efx
->loopback_modes
);
147 /* The MC indicates that LOOPBACK_NONE is a valid loopback mode,
148 * but by convention we don't */
149 efx
->loopback_modes
&= ~(1 << LOOPBACK_NONE
);
151 /* Set the initial link mode */
152 efx_mcdi_phy_decode_link(
153 efx
, &efx
->link_state
,
154 MCDI_DWORD(outbuf
, GET_LINK_OUT_LINK_SPEED
),
155 MCDI_DWORD(outbuf
, GET_LINK_OUT_FLAGS
),
156 MCDI_DWORD(outbuf
, GET_LINK_OUT_FCNTL
));
158 /* Record the initial FEC configuration (or nearest approximation
159 * representable in the ethtool configuration space)
161 efx
->fec_config
= mcdi_fec_caps_to_ethtool(caps
,
162 efx
->link_state
.speed
== 25000 ||
163 efx
->link_state
.speed
== 50000);
165 /* Default to Autonegotiated flow control if the PHY supports it */
166 efx
->wanted_fc
= EFX_FC_RX
| EFX_FC_TX
;
167 if (phy_data
->supported_cap
& (1 << MC_CMD_PHY_CAP_AN_LBN
))
168 efx
->wanted_fc
|= EFX_FC_AUTO
;
169 efx_link_set_wanted_fc(efx
, efx
->wanted_fc
);
178 int efx_mcdi_port_reconfigure(struct efx_nic
*efx
)
180 struct efx_mcdi_phy_data
*phy_cfg
= efx
->phy_data
;
181 u32 caps
= (efx
->link_advertising
[0] ?
182 ethtool_linkset_to_mcdi_cap(efx
->link_advertising
) :
183 phy_cfg
->forced_cap
);
185 caps
|= ethtool_fec_caps_to_mcdi(efx
->fec_config
);
187 return efx_mcdi_set_link(efx
, caps
, efx_get_mcdi_phy_flags(efx
),
188 efx
->loopback_mode
, 0);
191 static void efx_mcdi_phy_remove(struct efx_nic
*efx
)
193 struct efx_mcdi_phy_data
*phy_data
= efx
->phy_data
;
195 efx
->phy_data
= NULL
;
199 static void efx_mcdi_phy_get_link_ksettings(struct efx_nic
*efx
,
200 struct ethtool_link_ksettings
*cmd
)
202 struct efx_mcdi_phy_data
*phy_cfg
= efx
->phy_data
;
203 MCDI_DECLARE_BUF(outbuf
, MC_CMD_GET_LINK_OUT_LEN
);
206 cmd
->base
.speed
= efx
->link_state
.speed
;
207 cmd
->base
.duplex
= efx
->link_state
.fd
;
208 cmd
->base
.port
= mcdi_to_ethtool_media(phy_cfg
->media
);
209 cmd
->base
.phy_address
= phy_cfg
->port
;
210 cmd
->base
.autoneg
= !!(efx
->link_advertising
[0] & ADVERTISED_Autoneg
);
211 cmd
->base
.mdio_support
= (efx
->mdio
.mode_support
&
212 (MDIO_SUPPORTS_C45
| MDIO_SUPPORTS_C22
));
214 mcdi_to_ethtool_linkset(phy_cfg
->media
, phy_cfg
->supported_cap
,
215 cmd
->link_modes
.supported
);
216 memcpy(cmd
->link_modes
.advertising
, efx
->link_advertising
,
217 sizeof(__ETHTOOL_DECLARE_LINK_MODE_MASK()));
219 BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN
!= 0);
220 rc
= efx_mcdi_rpc(efx
, MC_CMD_GET_LINK
, NULL
, 0,
221 outbuf
, sizeof(outbuf
), NULL
);
224 mcdi_to_ethtool_linkset(phy_cfg
->media
,
225 MCDI_DWORD(outbuf
, GET_LINK_OUT_LP_CAP
),
226 cmd
->link_modes
.lp_advertising
);
230 efx_mcdi_phy_set_link_ksettings(struct efx_nic
*efx
,
231 const struct ethtool_link_ksettings
*cmd
)
233 struct efx_mcdi_phy_data
*phy_cfg
= efx
->phy_data
;
237 if (cmd
->base
.autoneg
) {
238 caps
= (ethtool_linkset_to_mcdi_cap(cmd
->link_modes
.advertising
) |
239 1 << MC_CMD_PHY_CAP_AN_LBN
);
240 } else if (cmd
->base
.duplex
) {
241 switch (cmd
->base
.speed
) {
242 case 10: caps
= 1 << MC_CMD_PHY_CAP_10FDX_LBN
; break;
243 case 100: caps
= 1 << MC_CMD_PHY_CAP_100FDX_LBN
; break;
244 case 1000: caps
= 1 << MC_CMD_PHY_CAP_1000FDX_LBN
; break;
245 case 10000: caps
= 1 << MC_CMD_PHY_CAP_10000FDX_LBN
; break;
246 case 40000: caps
= 1 << MC_CMD_PHY_CAP_40000FDX_LBN
; break;
247 case 100000: caps
= 1 << MC_CMD_PHY_CAP_100000FDX_LBN
; break;
248 case 25000: caps
= 1 << MC_CMD_PHY_CAP_25000FDX_LBN
; break;
249 case 50000: caps
= 1 << MC_CMD_PHY_CAP_50000FDX_LBN
; break;
250 default: return -EINVAL
;
253 switch (cmd
->base
.speed
) {
254 case 10: caps
= 1 << MC_CMD_PHY_CAP_10HDX_LBN
; break;
255 case 100: caps
= 1 << MC_CMD_PHY_CAP_100HDX_LBN
; break;
256 case 1000: caps
= 1 << MC_CMD_PHY_CAP_1000HDX_LBN
; break;
257 default: return -EINVAL
;
261 caps
|= ethtool_fec_caps_to_mcdi(efx
->fec_config
);
263 rc
= efx_mcdi_set_link(efx
, caps
, efx_get_mcdi_phy_flags(efx
),
264 efx
->loopback_mode
, 0);
268 if (cmd
->base
.autoneg
) {
269 efx_link_set_advertising(efx
, cmd
->link_modes
.advertising
);
270 phy_cfg
->forced_cap
= 0;
272 efx_link_clear_advertising(efx
);
273 phy_cfg
->forced_cap
= caps
;
278 static int efx_mcdi_phy_set_fecparam(struct efx_nic
*efx
,
279 const struct ethtool_fecparam
*fec
)
281 struct efx_mcdi_phy_data
*phy_cfg
= efx
->phy_data
;
285 /* Work out what efx_mcdi_phy_set_link_ksettings() would produce from
286 * saved advertising bits
288 if (test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT
, efx
->link_advertising
))
289 caps
= (ethtool_linkset_to_mcdi_cap(efx
->link_advertising
) |
290 1 << MC_CMD_PHY_CAP_AN_LBN
);
292 caps
= phy_cfg
->forced_cap
;
294 caps
|= ethtool_fec_caps_to_mcdi(fec
->fec
);
295 rc
= efx_mcdi_set_link(efx
, caps
, efx_get_mcdi_phy_flags(efx
),
296 efx
->loopback_mode
, 0);
300 /* Record the new FEC setting for subsequent set_link calls */
301 efx
->fec_config
= fec
->fec
;
305 static const char *const mcdi_sft9001_cable_diag_names
[] = {
306 "cable.pairA.length",
307 "cable.pairB.length",
308 "cable.pairC.length",
309 "cable.pairD.length",
310 "cable.pairA.status",
311 "cable.pairB.status",
312 "cable.pairC.status",
313 "cable.pairD.status",
316 static int efx_mcdi_bist(struct efx_nic
*efx
, unsigned int bist_mode
,
319 unsigned int retry
, i
, count
= 0;
322 MCDI_DECLARE_BUF(inbuf
, MC_CMD_START_BIST_IN_LEN
);
323 MCDI_DECLARE_BUF(outbuf
, MC_CMD_POLL_BIST_OUT_SFT9001_LEN
);
327 BUILD_BUG_ON(MC_CMD_START_BIST_OUT_LEN
!= 0);
328 MCDI_SET_DWORD(inbuf
, START_BIST_IN_TYPE
, bist_mode
);
329 rc
= efx_mcdi_rpc(efx
, MC_CMD_START_BIST
,
330 inbuf
, MC_CMD_START_BIST_IN_LEN
, NULL
, 0, NULL
);
334 /* Wait up to 10s for BIST to finish */
335 for (retry
= 0; retry
< 100; ++retry
) {
336 BUILD_BUG_ON(MC_CMD_POLL_BIST_IN_LEN
!= 0);
337 rc
= efx_mcdi_rpc(efx
, MC_CMD_POLL_BIST
, NULL
, 0,
338 outbuf
, sizeof(outbuf
), &outlen
);
342 status
= MCDI_DWORD(outbuf
, POLL_BIST_OUT_RESULT
);
343 if (status
!= MC_CMD_POLL_BIST_RUNNING
)
353 results
[count
++] = (status
== MC_CMD_POLL_BIST_PASSED
) ? 1 : -1;
355 /* SFT9001 specific cable diagnostics output */
356 if (efx
->phy_type
== PHY_TYPE_SFT9001B
&&
357 (bist_mode
== MC_CMD_PHY_BIST_CABLE_SHORT
||
358 bist_mode
== MC_CMD_PHY_BIST_CABLE_LONG
)) {
359 ptr
= MCDI_PTR(outbuf
, POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A
);
360 if (status
== MC_CMD_POLL_BIST_PASSED
&&
361 outlen
>= MC_CMD_POLL_BIST_OUT_SFT9001_LEN
) {
362 for (i
= 0; i
< 8; i
++) {
364 EFX_DWORD_FIELD(((efx_dword_t
*)ptr
)[i
],
376 static int efx_mcdi_phy_run_tests(struct efx_nic
*efx
, int *results
,
379 struct efx_mcdi_phy_data
*phy_cfg
= efx
->phy_data
;
383 if (phy_cfg
->flags
& (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_LBN
)) {
384 rc
= efx_mcdi_bist(efx
, MC_CMD_PHY_BIST
, results
);
391 /* If we support both LONG and SHORT, then run each in response to
392 * break or not. Otherwise, run the one we support */
394 if (phy_cfg
->flags
& (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN
)) {
395 if ((flags
& ETH_TEST_FL_OFFLINE
) &&
397 (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN
)))
398 mode
= MC_CMD_PHY_BIST_CABLE_LONG
;
400 mode
= MC_CMD_PHY_BIST_CABLE_SHORT
;
401 } else if (phy_cfg
->flags
&
402 (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN
))
403 mode
= MC_CMD_PHY_BIST_CABLE_LONG
;
406 rc
= efx_mcdi_bist(efx
, mode
, results
);
415 static const char *efx_mcdi_phy_test_name(struct efx_nic
*efx
,
418 struct efx_mcdi_phy_data
*phy_cfg
= efx
->phy_data
;
420 if (phy_cfg
->flags
& (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_LBN
)) {
426 if (phy_cfg
->flags
& ((1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN
) |
427 (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN
))) {
432 if (efx
->phy_type
== PHY_TYPE_SFT9001B
) {
433 if (index
< ARRAY_SIZE(mcdi_sft9001_cable_diag_names
))
434 return mcdi_sft9001_cable_diag_names
[index
];
435 index
-= ARRAY_SIZE(mcdi_sft9001_cable_diag_names
);
442 #define SFP_PAGE_SIZE 128
443 #define SFF_DIAG_TYPE_OFFSET 92
444 #define SFF_DIAG_ADDR_CHANGE BIT(2)
445 #define SFF_8079_NUM_PAGES 2
446 #define SFF_8472_NUM_PAGES 4
447 #define SFF_8436_NUM_PAGES 5
448 #define SFF_DMT_LEVEL_OFFSET 94
450 /** efx_mcdi_phy_get_module_eeprom_page() - Get a single page of module eeprom
452 * @page: EEPROM page number
453 * @data: Destination data pointer
454 * @offset: Offset in page to copy from in to data
455 * @space: Space available in data
458 * >=0 - amount of data copied
461 static int efx_mcdi_phy_get_module_eeprom_page(struct efx_nic
*efx
,
463 u8
*data
, ssize_t offset
,
466 MCDI_DECLARE_BUF(outbuf
, MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX
);
467 MCDI_DECLARE_BUF(inbuf
, MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN
);
469 unsigned int payload_len
;
470 unsigned int to_copy
;
473 if (offset
> SFP_PAGE_SIZE
)
476 to_copy
= min(space
, SFP_PAGE_SIZE
- offset
);
478 MCDI_SET_DWORD(inbuf
, GET_PHY_MEDIA_INFO_IN_PAGE
, page
);
479 rc
= efx_mcdi_rpc_quiet(efx
, MC_CMD_GET_PHY_MEDIA_INFO
,
480 inbuf
, sizeof(inbuf
),
481 outbuf
, sizeof(outbuf
),
487 if (outlen
< (MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST
+
491 payload_len
= MCDI_DWORD(outbuf
, GET_PHY_MEDIA_INFO_OUT_DATALEN
);
492 if (payload_len
!= SFP_PAGE_SIZE
)
495 memcpy(data
, MCDI_PTR(outbuf
, GET_PHY_MEDIA_INFO_OUT_DATA
) + offset
,
501 static int efx_mcdi_phy_get_module_eeprom_byte(struct efx_nic
*efx
,
508 rc
= efx_mcdi_phy_get_module_eeprom_page(efx
, page
, &data
, byte
, 1);
515 static int efx_mcdi_phy_diag_type(struct efx_nic
*efx
)
517 /* Page zero of the EEPROM includes the diagnostic type at byte 92. */
518 return efx_mcdi_phy_get_module_eeprom_byte(efx
, 0,
519 SFF_DIAG_TYPE_OFFSET
);
522 static int efx_mcdi_phy_sff_8472_level(struct efx_nic
*efx
)
524 /* Page zero of the EEPROM includes the DMT level at byte 94. */
525 return efx_mcdi_phy_get_module_eeprom_byte(efx
, 0,
526 SFF_DMT_LEVEL_OFFSET
);
529 static u32
efx_mcdi_phy_module_type(struct efx_nic
*efx
)
531 struct efx_mcdi_phy_data
*phy_data
= efx
->phy_data
;
533 if (phy_data
->media
!= MC_CMD_MEDIA_QSFP_PLUS
)
534 return phy_data
->media
;
536 /* A QSFP+ NIC may actually have an SFP+ module attached.
537 * The ID is page 0, byte 0.
539 switch (efx_mcdi_phy_get_module_eeprom_byte(efx
, 0, 0)) {
541 return MC_CMD_MEDIA_SFP_PLUS
;
544 return MC_CMD_MEDIA_QSFP_PLUS
;
550 static int efx_mcdi_phy_get_module_eeprom(struct efx_nic
*efx
,
551 struct ethtool_eeprom
*ee
, u8
*data
)
554 ssize_t space_remaining
= ee
->len
;
555 unsigned int page_off
;
560 switch (efx_mcdi_phy_module_type(efx
)) {
561 case MC_CMD_MEDIA_SFP_PLUS
:
562 num_pages
= efx_mcdi_phy_sff_8472_level(efx
) > 0 ?
563 SFF_8472_NUM_PAGES
: SFF_8079_NUM_PAGES
;
565 ignore_missing
= false;
567 case MC_CMD_MEDIA_QSFP_PLUS
:
568 num_pages
= SFF_8436_NUM_PAGES
;
569 page
= -1; /* We obtain the lower page by asking for -1. */
570 ignore_missing
= true; /* Ignore missing pages after page 0. */
576 page_off
= ee
->offset
% SFP_PAGE_SIZE
;
577 page
+= ee
->offset
/ SFP_PAGE_SIZE
;
579 while (space_remaining
&& (page
< num_pages
)) {
580 rc
= efx_mcdi_phy_get_module_eeprom_page(efx
, page
,
585 space_remaining
-= rc
;
589 } else if (rc
== 0) {
591 } else if (ignore_missing
&& (page
> 0)) {
592 int intended_size
= SFP_PAGE_SIZE
- page_off
;
594 space_remaining
-= intended_size
;
595 if (space_remaining
< 0) {
598 memset(data
, 0, intended_size
);
599 data
+= intended_size
;
612 static int efx_mcdi_phy_get_module_info(struct efx_nic
*efx
,
613 struct ethtool_modinfo
*modinfo
)
618 switch (efx_mcdi_phy_module_type(efx
)) {
619 case MC_CMD_MEDIA_SFP_PLUS
:
620 sff_8472_level
= efx_mcdi_phy_sff_8472_level(efx
);
622 /* If we can't read the diagnostics level we have none. */
623 if (sff_8472_level
< 0)
626 /* Check if this module requires the (unsupported) address
629 diag_type
= efx_mcdi_phy_diag_type(efx
);
631 if ((sff_8472_level
== 0) ||
632 (diag_type
& SFF_DIAG_ADDR_CHANGE
)) {
633 modinfo
->type
= ETH_MODULE_SFF_8079
;
634 modinfo
->eeprom_len
= ETH_MODULE_SFF_8079_LEN
;
636 modinfo
->type
= ETH_MODULE_SFF_8472
;
637 modinfo
->eeprom_len
= ETH_MODULE_SFF_8472_LEN
;
641 case MC_CMD_MEDIA_QSFP_PLUS
:
642 modinfo
->type
= ETH_MODULE_SFF_8436
;
643 modinfo
->eeprom_len
= ETH_MODULE_SFF_8436_LEN
;
653 static const struct efx_phy_operations efx_mcdi_phy_ops
= {
654 .probe
= efx_mcdi_phy_probe
,
655 .init
= efx_port_dummy_op_int
,
656 .reconfigure
= efx_mcdi_port_reconfigure
,
657 .poll
= efx_mcdi_phy_poll
,
658 .fini
= efx_port_dummy_op_void
,
659 .remove
= efx_mcdi_phy_remove
,
660 .get_link_ksettings
= efx_mcdi_phy_get_link_ksettings
,
661 .set_link_ksettings
= efx_mcdi_phy_set_link_ksettings
,
662 .get_fecparam
= efx_mcdi_phy_get_fecparam
,
663 .set_fecparam
= efx_mcdi_phy_set_fecparam
,
664 .test_alive
= efx_mcdi_phy_test_alive
,
665 .run_tests
= efx_mcdi_phy_run_tests
,
666 .test_name
= efx_mcdi_phy_test_name
,
667 .get_module_eeprom
= efx_mcdi_phy_get_module_eeprom
,
668 .get_module_info
= efx_mcdi_phy_get_module_info
,
671 u32
efx_mcdi_phy_get_caps(struct efx_nic
*efx
)
673 struct efx_mcdi_phy_data
*phy_data
= efx
->phy_data
;
675 return phy_data
->supported_cap
;
678 bool efx_mcdi_mac_check_fault(struct efx_nic
*efx
)
680 MCDI_DECLARE_BUF(outbuf
, MC_CMD_GET_LINK_OUT_LEN
);
684 BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN
!= 0);
686 rc
= efx_mcdi_rpc(efx
, MC_CMD_GET_LINK
, NULL
, 0,
687 outbuf
, sizeof(outbuf
), &outlength
);
691 return MCDI_DWORD(outbuf
, GET_LINK_OUT_MAC_FAULT
) != 0;
694 enum efx_stats_action
{
700 static int efx_mcdi_mac_stats(struct efx_nic
*efx
,
701 enum efx_stats_action action
, int clear
)
703 MCDI_DECLARE_BUF(inbuf
, MC_CMD_MAC_STATS_IN_LEN
);
705 int change
= action
== EFX_STATS_PULL
? 0 : 1;
706 int enable
= action
== EFX_STATS_ENABLE
? 1 : 0;
707 int period
= action
== EFX_STATS_ENABLE
? 1000 : 0;
708 dma_addr_t dma_addr
= efx
->stats_buffer
.dma_addr
;
709 u32 dma_len
= action
!= EFX_STATS_DISABLE
?
710 efx
->num_mac_stats
* sizeof(u64
) : 0;
712 BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN
!= 0);
714 MCDI_SET_QWORD(inbuf
, MAC_STATS_IN_DMA_ADDR
, dma_addr
);
715 MCDI_POPULATE_DWORD_7(inbuf
, MAC_STATS_IN_CMD
,
716 MAC_STATS_IN_DMA
, !!enable
,
717 MAC_STATS_IN_CLEAR
, clear
,
718 MAC_STATS_IN_PERIODIC_CHANGE
, change
,
719 MAC_STATS_IN_PERIODIC_ENABLE
, enable
,
720 MAC_STATS_IN_PERIODIC_CLEAR
, 0,
721 MAC_STATS_IN_PERIODIC_NOEVENT
, 1,
722 MAC_STATS_IN_PERIOD_MS
, period
);
723 MCDI_SET_DWORD(inbuf
, MAC_STATS_IN_DMA_LEN
, dma_len
);
725 if (efx_nic_rev(efx
) >= EFX_REV_HUNT_A0
) {
726 struct efx_ef10_nic_data
*nic_data
= efx
->nic_data
;
728 MCDI_SET_DWORD(inbuf
, MAC_STATS_IN_PORT_ID
, nic_data
->vport_id
);
731 rc
= efx_mcdi_rpc_quiet(efx
, MC_CMD_MAC_STATS
, inbuf
, sizeof(inbuf
),
733 /* Expect ENOENT if DMA queues have not been set up */
734 if (rc
&& (rc
!= -ENOENT
|| atomic_read(&efx
->active_queues
)))
735 efx_mcdi_display_error(efx
, MC_CMD_MAC_STATS
, sizeof(inbuf
),
740 void efx_mcdi_mac_start_stats(struct efx_nic
*efx
)
742 __le64
*dma_stats
= efx
->stats_buffer
.addr
;
744 dma_stats
[efx
->num_mac_stats
- 1] = EFX_MC_STATS_GENERATION_INVALID
;
746 efx_mcdi_mac_stats(efx
, EFX_STATS_ENABLE
, 0);
749 void efx_mcdi_mac_stop_stats(struct efx_nic
*efx
)
751 efx_mcdi_mac_stats(efx
, EFX_STATS_DISABLE
, 0);
754 #define EFX_MAC_STATS_WAIT_US 100
755 #define EFX_MAC_STATS_WAIT_ATTEMPTS 10
757 void efx_mcdi_mac_pull_stats(struct efx_nic
*efx
)
759 __le64
*dma_stats
= efx
->stats_buffer
.addr
;
760 int attempts
= EFX_MAC_STATS_WAIT_ATTEMPTS
;
762 dma_stats
[efx
->num_mac_stats
- 1] = EFX_MC_STATS_GENERATION_INVALID
;
763 efx_mcdi_mac_stats(efx
, EFX_STATS_PULL
, 0);
765 while (dma_stats
[efx
->num_mac_stats
- 1] ==
766 EFX_MC_STATS_GENERATION_INVALID
&&
768 udelay(EFX_MAC_STATS_WAIT_US
);
771 int efx_mcdi_port_probe(struct efx_nic
*efx
)
775 /* Hook in PHY operations table */
776 efx
->phy_op
= &efx_mcdi_phy_ops
;
778 /* Set up MDIO structure for PHY */
779 efx
->mdio
.mode_support
= MDIO_SUPPORTS_C45
| MDIO_EMULATE_C22
;
780 efx
->mdio
.mdio_read
= efx_mcdi_mdio_read
;
781 efx
->mdio
.mdio_write
= efx_mcdi_mdio_write
;
783 /* Fill out MDIO structure, loopback modes, and initial link state */
784 rc
= efx
->phy_op
->probe(efx
);
788 /* Allocate buffer for stats */
789 rc
= efx_nic_alloc_buffer(efx
, &efx
->stats_buffer
,
790 efx
->num_mac_stats
* sizeof(u64
), GFP_KERNEL
);
793 netif_dbg(efx
, probe
, efx
->net_dev
,
794 "stats buffer at %llx (virt %p phys %llx)\n",
795 (u64
)efx
->stats_buffer
.dma_addr
,
796 efx
->stats_buffer
.addr
,
797 (u64
)virt_to_phys(efx
->stats_buffer
.addr
));
799 efx_mcdi_mac_stats(efx
, EFX_STATS_DISABLE
, 1);
804 void efx_mcdi_port_remove(struct efx_nic
*efx
)
806 efx
->phy_op
->remove(efx
);
807 efx_nic_free_buffer(efx
, &efx
->stats_buffer
);