]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/net/ethernet/sfc/mcdi_port.c
sfc: support the ethtool ksettings API properly so that 25/50/100G works
[mirror_ubuntu-hirsute-kernel.git] / drivers / net / ethernet / sfc / mcdi_port.c
CommitLineData
afd4aea0 1/****************************************************************************
f7a6d2c4
BH
2 * Driver for Solarflare network controllers and boards
3 * Copyright 2009-2013 Solarflare Communications Inc.
afd4aea0
BH
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published
7 * by the Free Software Foundation, incorporated herein by reference.
8 */
9
10/*
11 * Driver for PHY related operations via MCDI.
12 */
13
5a0e3ad6 14#include <linux/slab.h>
afd4aea0 15#include "efx.h"
afd4aea0
BH
16#include "mcdi.h"
17#include "mcdi_pcol.h"
affaf485
SH
18#include "nic.h"
19#include "selftest.h"
afd4aea0 20
3bd93035 21struct efx_mcdi_phy_data {
afd4aea0
BH
22 u32 flags;
23 u32 type;
24 u32 supported_cap;
25 u32 channel;
26 u32 port;
27 u32 stats_mask;
28 u8 name[20];
29 u32 media;
30 u32 mmd_mask;
31 u8 revision[20];
32 u32 forced_cap;
33};
34
35static int
3bd93035 36efx_mcdi_get_phy_cfg(struct efx_nic *efx, struct efx_mcdi_phy_data *cfg)
afd4aea0 37{
59cfc479 38 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PHY_CFG_OUT_LEN);
afd4aea0
BH
39 size_t outlen;
40 int rc;
41
42 BUILD_BUG_ON(MC_CMD_GET_PHY_CFG_IN_LEN != 0);
43 BUILD_BUG_ON(MC_CMD_GET_PHY_CFG_OUT_NAME_LEN != sizeof(cfg->name));
44
45 rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_CFG, NULL, 0,
46 outbuf, sizeof(outbuf), &outlen);
47 if (rc)
48 goto fail;
49
50 if (outlen < MC_CMD_GET_PHY_CFG_OUT_LEN) {
00bbb4a5 51 rc = -EIO;
afd4aea0
BH
52 goto fail;
53 }
54
55 cfg->flags = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_FLAGS);
56 cfg->type = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_TYPE);
57 cfg->supported_cap =
58 MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_SUPPORTED_CAP);
59 cfg->channel = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_CHANNEL);
60 cfg->port = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_PRT);
61 cfg->stats_mask = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_STATS_MASK);
62 memcpy(cfg->name, MCDI_PTR(outbuf, GET_PHY_CFG_OUT_NAME),
63 sizeof(cfg->name));
64 cfg->media = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_MEDIA_TYPE);
65 cfg->mmd_mask = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_MMD_MASK);
66 memcpy(cfg->revision, MCDI_PTR(outbuf, GET_PHY_CFG_OUT_REVISION),
67 sizeof(cfg->revision));
68
69 return 0;
70
71fail:
62776d03 72 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
afd4aea0
BH
73 return rc;
74}
75
76static int efx_mcdi_set_link(struct efx_nic *efx, u32 capabilities,
77 u32 flags, u32 loopback_mode,
78 u32 loopback_speed)
79{
59cfc479 80 MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_LINK_IN_LEN);
afd4aea0
BH
81 int rc;
82
83 BUILD_BUG_ON(MC_CMD_SET_LINK_OUT_LEN != 0);
84
85 MCDI_SET_DWORD(inbuf, SET_LINK_IN_CAP, capabilities);
86 MCDI_SET_DWORD(inbuf, SET_LINK_IN_FLAGS, flags);
87 MCDI_SET_DWORD(inbuf, SET_LINK_IN_LOOPBACK_MODE, loopback_mode);
88 MCDI_SET_DWORD(inbuf, SET_LINK_IN_LOOPBACK_SPEED, loopback_speed);
89
90 rc = efx_mcdi_rpc(efx, MC_CMD_SET_LINK, inbuf, sizeof(inbuf),
91 NULL, 0, NULL);
afd4aea0
BH
92 return rc;
93}
94
95static int efx_mcdi_loopback_modes(struct efx_nic *efx, u64 *loopback_modes)
96{
59cfc479 97 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LOOPBACK_MODES_OUT_LEN);
afd4aea0
BH
98 size_t outlen;
99 int rc;
100
101 rc = efx_mcdi_rpc(efx, MC_CMD_GET_LOOPBACK_MODES, NULL, 0,
102 outbuf, sizeof(outbuf), &outlen);
103 if (rc)
104 goto fail;
105
f2b0befd
BH
106 if (outlen < (MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST +
107 MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN)) {
00bbb4a5 108 rc = -EIO;
afd4aea0
BH
109 goto fail;
110 }
111
05a9320f 112 *loopback_modes = MCDI_QWORD(outbuf, GET_LOOPBACK_MODES_OUT_SUGGESTED);
afd4aea0
BH
113
114 return 0;
115
116fail:
62776d03 117 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
afd4aea0
BH
118 return rc;
119}
120
43f775b2
BH
121static int efx_mcdi_mdio_read(struct net_device *net_dev,
122 int prtad, int devad, u16 addr)
afd4aea0 123{
43f775b2 124 struct efx_nic *efx = netdev_priv(net_dev);
59cfc479
BH
125 MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_READ_IN_LEN);
126 MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_READ_OUT_LEN);
afd4aea0
BH
127 size_t outlen;
128 int rc;
129
43f775b2 130 MCDI_SET_DWORD(inbuf, MDIO_READ_IN_BUS, efx->mdio_bus);
afd4aea0
BH
131 MCDI_SET_DWORD(inbuf, MDIO_READ_IN_PRTAD, prtad);
132 MCDI_SET_DWORD(inbuf, MDIO_READ_IN_DEVAD, devad);
133 MCDI_SET_DWORD(inbuf, MDIO_READ_IN_ADDR, addr);
134
135 rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_READ, inbuf, sizeof(inbuf),
136 outbuf, sizeof(outbuf), &outlen);
137 if (rc)
1e0b8120 138 return rc;
afd4aea0 139
43f775b2
BH
140 if (MCDI_DWORD(outbuf, MDIO_READ_OUT_STATUS) !=
141 MC_CMD_MDIO_STATUS_GOOD)
142 return -EIO;
143
144 return (u16)MCDI_DWORD(outbuf, MDIO_READ_OUT_VALUE);
afd4aea0
BH
145}
146
43f775b2
BH
147static int efx_mcdi_mdio_write(struct net_device *net_dev,
148 int prtad, int devad, u16 addr, u16 value)
afd4aea0 149{
43f775b2 150 struct efx_nic *efx = netdev_priv(net_dev);
59cfc479
BH
151 MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_WRITE_IN_LEN);
152 MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_WRITE_OUT_LEN);
afd4aea0
BH
153 size_t outlen;
154 int rc;
155
43f775b2 156 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_BUS, efx->mdio_bus);
afd4aea0
BH
157 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_PRTAD, prtad);
158 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_DEVAD, devad);
159 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_ADDR, addr);
160 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_VALUE, value);
161
162 rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_WRITE, inbuf, sizeof(inbuf),
163 outbuf, sizeof(outbuf), &outlen);
164 if (rc)
1e0b8120 165 return rc;
afd4aea0 166
43f775b2
BH
167 if (MCDI_DWORD(outbuf, MDIO_WRITE_OUT_STATUS) !=
168 MC_CMD_MDIO_STATUS_GOOD)
169 return -EIO;
170
afd4aea0 171 return 0;
afd4aea0
BH
172}
173
c2ab85d2 174static void mcdi_to_ethtool_linkset(u32 media, u32 cap, unsigned long *linkset)
afd4aea0 175{
c2ab85d2
EC
176 #define SET_BIT(name) __set_bit(ETHTOOL_LINK_MODE_ ## name ## _BIT, \
177 linkset)
afd4aea0 178
c2ab85d2 179 bitmap_zero(linkset, __ETHTOOL_LINK_MODE_MASK_NBITS);
afd4aea0
BH
180 switch (media) {
181 case MC_CMD_MEDIA_KX4:
c2ab85d2 182 SET_BIT(Backplane);
afd4aea0 183 if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
c2ab85d2 184 SET_BIT(1000baseKX_Full);
afd4aea0 185 if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
c2ab85d2 186 SET_BIT(10000baseKX4_Full);
ac331e94 187 if (cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
c2ab85d2 188 SET_BIT(40000baseKR4_Full);
afd4aea0
BH
189 break;
190
191 case MC_CMD_MEDIA_XFP:
192 case MC_CMD_MEDIA_SFP_PLUS:
ac331e94 193 case MC_CMD_MEDIA_QSFP_PLUS:
c2ab85d2 194 SET_BIT(FIBRE);
3497ed8c 195 if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
c2ab85d2 196 SET_BIT(1000baseT_Full);
3497ed8c 197 if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
c2ab85d2 198 SET_BIT(10000baseT_Full);
ac331e94 199 if (cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
c2ab85d2 200 SET_BIT(40000baseCR4_Full);
ac331e94
EC
201 break;
202
afd4aea0 203 case MC_CMD_MEDIA_BASE_T:
c2ab85d2 204 SET_BIT(TP);
afd4aea0 205 if (cap & (1 << MC_CMD_PHY_CAP_10HDX_LBN))
c2ab85d2 206 SET_BIT(10baseT_Half);
afd4aea0 207 if (cap & (1 << MC_CMD_PHY_CAP_10FDX_LBN))
c2ab85d2 208 SET_BIT(10baseT_Full);
afd4aea0 209 if (cap & (1 << MC_CMD_PHY_CAP_100HDX_LBN))
c2ab85d2 210 SET_BIT(100baseT_Half);
afd4aea0 211 if (cap & (1 << MC_CMD_PHY_CAP_100FDX_LBN))
c2ab85d2 212 SET_BIT(100baseT_Full);
afd4aea0 213 if (cap & (1 << MC_CMD_PHY_CAP_1000HDX_LBN))
c2ab85d2 214 SET_BIT(1000baseT_Half);
afd4aea0 215 if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
c2ab85d2 216 SET_BIT(1000baseT_Full);
afd4aea0 217 if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
c2ab85d2 218 SET_BIT(10000baseT_Full);
afd4aea0
BH
219 break;
220 }
221
222 if (cap & (1 << MC_CMD_PHY_CAP_PAUSE_LBN))
c2ab85d2 223 SET_BIT(Pause);
afd4aea0 224 if (cap & (1 << MC_CMD_PHY_CAP_ASYM_LBN))
c2ab85d2 225 SET_BIT(Asym_Pause);
afd4aea0 226 if (cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
c2ab85d2 227 SET_BIT(Autoneg);
afd4aea0 228
c2ab85d2 229 #undef SET_BIT
afd4aea0
BH
230}
231
c2ab85d2 232static u32 ethtool_linkset_to_mcdi_cap(const unsigned long *linkset)
afd4aea0
BH
233{
234 u32 result = 0;
235
c2ab85d2
EC
236 #define TEST_BIT(name) test_bit(ETHTOOL_LINK_MODE_ ## name ## _BIT, \
237 linkset)
238
239 if (TEST_BIT(10baseT_Half))
afd4aea0 240 result |= (1 << MC_CMD_PHY_CAP_10HDX_LBN);
c2ab85d2 241 if (TEST_BIT(10baseT_Full))
afd4aea0 242 result |= (1 << MC_CMD_PHY_CAP_10FDX_LBN);
c2ab85d2 243 if (TEST_BIT(100baseT_Half))
afd4aea0 244 result |= (1 << MC_CMD_PHY_CAP_100HDX_LBN);
c2ab85d2 245 if (TEST_BIT(100baseT_Full))
afd4aea0 246 result |= (1 << MC_CMD_PHY_CAP_100FDX_LBN);
c2ab85d2 247 if (TEST_BIT(1000baseT_Half))
afd4aea0 248 result |= (1 << MC_CMD_PHY_CAP_1000HDX_LBN);
c2ab85d2 249 if (TEST_BIT(1000baseT_Full) || TEST_BIT(1000baseKX_Full))
afd4aea0 250 result |= (1 << MC_CMD_PHY_CAP_1000FDX_LBN);
c2ab85d2 251 if (TEST_BIT(10000baseT_Full) || TEST_BIT(10000baseKX4_Full))
afd4aea0 252 result |= (1 << MC_CMD_PHY_CAP_10000FDX_LBN);
c2ab85d2 253 if (TEST_BIT(40000baseCR4_Full) || TEST_BIT(40000baseKR4_Full))
ac331e94 254 result |= (1 << MC_CMD_PHY_CAP_40000FDX_LBN);
c2ab85d2 255 if (TEST_BIT(Pause))
afd4aea0 256 result |= (1 << MC_CMD_PHY_CAP_PAUSE_LBN);
c2ab85d2 257 if (TEST_BIT(Asym_Pause))
afd4aea0 258 result |= (1 << MC_CMD_PHY_CAP_ASYM_LBN);
c2ab85d2 259 if (TEST_BIT(Autoneg))
afd4aea0
BH
260 result |= (1 << MC_CMD_PHY_CAP_AN_LBN);
261
c2ab85d2
EC
262 #undef TEST_BIT
263
afd4aea0
BH
264 return result;
265}
266
267static u32 efx_get_mcdi_phy_flags(struct efx_nic *efx)
268{
3bd93035 269 struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
afd4aea0
BH
270 enum efx_phy_mode mode, supported;
271 u32 flags;
272
273 /* TODO: Advertise the capabilities supported by this PHY */
274 supported = 0;
05a9320f 275 if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_TXDIS_LBN))
afd4aea0 276 supported |= PHY_MODE_TX_DISABLED;
05a9320f 277 if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_LOWPOWER_LBN))
afd4aea0 278 supported |= PHY_MODE_LOW_POWER;
05a9320f 279 if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_POWEROFF_LBN))
afd4aea0
BH
280 supported |= PHY_MODE_OFF;
281
282 mode = efx->phy_mode & supported;
283
284 flags = 0;
285 if (mode & PHY_MODE_TX_DISABLED)
05a9320f 286 flags |= (1 << MC_CMD_SET_LINK_IN_TXDIS_LBN);
afd4aea0 287 if (mode & PHY_MODE_LOW_POWER)
05a9320f 288 flags |= (1 << MC_CMD_SET_LINK_IN_LOWPOWER_LBN);
afd4aea0 289 if (mode & PHY_MODE_OFF)
05a9320f 290 flags |= (1 << MC_CMD_SET_LINK_IN_POWEROFF_LBN);
afd4aea0
BH
291
292 return flags;
293}
294
c2ab85d2 295static u8 mcdi_to_ethtool_media(u32 media)
afd4aea0
BH
296{
297 switch (media) {
298 case MC_CMD_MEDIA_XAUI:
299 case MC_CMD_MEDIA_CX4:
300 case MC_CMD_MEDIA_KX4:
301 return PORT_OTHER;
302
303 case MC_CMD_MEDIA_XFP:
304 case MC_CMD_MEDIA_SFP_PLUS:
ac331e94 305 case MC_CMD_MEDIA_QSFP_PLUS:
afd4aea0
BH
306 return PORT_FIBRE;
307
308 case MC_CMD_MEDIA_BASE_T:
309 return PORT_TP;
310
311 default:
312 return PORT_OTHER;
313 }
314}
315
43f775b2
BH
316static void efx_mcdi_phy_decode_link(struct efx_nic *efx,
317 struct efx_link_state *link_state,
318 u32 speed, u32 flags, u32 fcntl)
319{
320 switch (fcntl) {
321 case MC_CMD_FCNTL_AUTO:
322 WARN_ON(1); /* This is not a link mode */
323 link_state->fc = EFX_FC_AUTO | EFX_FC_TX | EFX_FC_RX;
324 break;
325 case MC_CMD_FCNTL_BIDIR:
326 link_state->fc = EFX_FC_TX | EFX_FC_RX;
327 break;
328 case MC_CMD_FCNTL_RESPOND:
329 link_state->fc = EFX_FC_RX;
330 break;
331 default:
332 WARN_ON(1);
333 case MC_CMD_FCNTL_OFF:
334 link_state->fc = 0;
335 break;
336 }
337
338 link_state->up = !!(flags & (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN));
339 link_state->fd = !!(flags & (1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN));
340 link_state->speed = speed;
341}
342
afd4aea0
BH
343static int efx_mcdi_phy_probe(struct efx_nic *efx)
344{
3bd93035 345 struct efx_mcdi_phy_data *phy_data;
59cfc479 346 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
ff3b00a0 347 u32 caps;
afd4aea0
BH
348 int rc;
349
ff3b00a0
SH
350 /* Initialise and populate phy_data */
351 phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
352 if (phy_data == NULL)
353 return -ENOMEM;
354
355 rc = efx_mcdi_get_phy_cfg(efx, phy_data);
afd4aea0
BH
356 if (rc != 0)
357 goto fail;
358
ff3b00a0
SH
359 /* Read initial link advertisement */
360 BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
361 rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
362 outbuf, sizeof(outbuf), NULL);
363 if (rc)
364 goto fail;
365
366 /* Fill out nic state */
367 efx->phy_data = phy_data;
368 efx->phy_type = phy_data->type;
afd4aea0 369
ff3b00a0
SH
370 efx->mdio_bus = phy_data->channel;
371 efx->mdio.prtad = phy_data->port;
372 efx->mdio.mmds = phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22);
afd4aea0 373 efx->mdio.mode_support = 0;
ff3b00a0 374 if (phy_data->mmd_mask & (1 << MC_CMD_MMD_CLAUSE22))
afd4aea0 375 efx->mdio.mode_support |= MDIO_SUPPORTS_C22;
ff3b00a0 376 if (phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22))
afd4aea0
BH
377 efx->mdio.mode_support |= MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
378
ff3b00a0
SH
379 caps = MCDI_DWORD(outbuf, GET_LINK_OUT_CAP);
380 if (caps & (1 << MC_CMD_PHY_CAP_AN_LBN))
c2ab85d2
EC
381 mcdi_to_ethtool_linkset(phy_data->media, caps,
382 efx->link_advertising);
ff3b00a0
SH
383 else
384 phy_data->forced_cap = caps;
385
afd4aea0
BH
386 /* Assert that we can map efx -> mcdi loopback modes */
387 BUILD_BUG_ON(LOOPBACK_NONE != MC_CMD_LOOPBACK_NONE);
388 BUILD_BUG_ON(LOOPBACK_DATA != MC_CMD_LOOPBACK_DATA);
389 BUILD_BUG_ON(LOOPBACK_GMAC != MC_CMD_LOOPBACK_GMAC);
390 BUILD_BUG_ON(LOOPBACK_XGMII != MC_CMD_LOOPBACK_XGMII);
391 BUILD_BUG_ON(LOOPBACK_XGXS != MC_CMD_LOOPBACK_XGXS);
392 BUILD_BUG_ON(LOOPBACK_XAUI != MC_CMD_LOOPBACK_XAUI);
393 BUILD_BUG_ON(LOOPBACK_GMII != MC_CMD_LOOPBACK_GMII);
394 BUILD_BUG_ON(LOOPBACK_SGMII != MC_CMD_LOOPBACK_SGMII);
395 BUILD_BUG_ON(LOOPBACK_XGBR != MC_CMD_LOOPBACK_XGBR);
396 BUILD_BUG_ON(LOOPBACK_XFI != MC_CMD_LOOPBACK_XFI);
397 BUILD_BUG_ON(LOOPBACK_XAUI_FAR != MC_CMD_LOOPBACK_XAUI_FAR);
398 BUILD_BUG_ON(LOOPBACK_GMII_FAR != MC_CMD_LOOPBACK_GMII_FAR);
399 BUILD_BUG_ON(LOOPBACK_SGMII_FAR != MC_CMD_LOOPBACK_SGMII_FAR);
400 BUILD_BUG_ON(LOOPBACK_XFI_FAR != MC_CMD_LOOPBACK_XFI_FAR);
401 BUILD_BUG_ON(LOOPBACK_GPHY != MC_CMD_LOOPBACK_GPHY);
402 BUILD_BUG_ON(LOOPBACK_PHYXS != MC_CMD_LOOPBACK_PHYXS);
403 BUILD_BUG_ON(LOOPBACK_PCS != MC_CMD_LOOPBACK_PCS);
404 BUILD_BUG_ON(LOOPBACK_PMAPMD != MC_CMD_LOOPBACK_PMAPMD);
405 BUILD_BUG_ON(LOOPBACK_XPORT != MC_CMD_LOOPBACK_XPORT);
406 BUILD_BUG_ON(LOOPBACK_XGMII_WS != MC_CMD_LOOPBACK_XGMII_WS);
407 BUILD_BUG_ON(LOOPBACK_XAUI_WS != MC_CMD_LOOPBACK_XAUI_WS);
408 BUILD_BUG_ON(LOOPBACK_XAUI_WS_FAR != MC_CMD_LOOPBACK_XAUI_WS_FAR);
409 BUILD_BUG_ON(LOOPBACK_XAUI_WS_NEAR != MC_CMD_LOOPBACK_XAUI_WS_NEAR);
410 BUILD_BUG_ON(LOOPBACK_GMII_WS != MC_CMD_LOOPBACK_GMII_WS);
411 BUILD_BUG_ON(LOOPBACK_XFI_WS != MC_CMD_LOOPBACK_XFI_WS);
412 BUILD_BUG_ON(LOOPBACK_XFI_WS_FAR != MC_CMD_LOOPBACK_XFI_WS_FAR);
413 BUILD_BUG_ON(LOOPBACK_PHYXS_WS != MC_CMD_LOOPBACK_PHYXS_WS);
414
415 rc = efx_mcdi_loopback_modes(efx, &efx->loopback_modes);
416 if (rc != 0)
417 goto fail;
418 /* The MC indicates that LOOPBACK_NONE is a valid loopback mode,
419 * but by convention we don't */
420 efx->loopback_modes &= ~(1 << LOOPBACK_NONE);
421
7a6b8f6f
SH
422 /* Set the initial link mode */
423 efx_mcdi_phy_decode_link(
424 efx, &efx->link_state,
425 MCDI_DWORD(outbuf, GET_LINK_OUT_LINK_SPEED),
426 MCDI_DWORD(outbuf, GET_LINK_OUT_FLAGS),
427 MCDI_DWORD(outbuf, GET_LINK_OUT_FCNTL));
428
429 /* Default to Autonegotiated flow control if the PHY supports it */
430 efx->wanted_fc = EFX_FC_RX | EFX_FC_TX;
431 if (phy_data->supported_cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
432 efx->wanted_fc |= EFX_FC_AUTO;
cffe9d4c 433 efx_link_set_wanted_fc(efx, efx->wanted_fc);
7a6b8f6f 434
afd4aea0
BH
435 return 0;
436
437fail:
438 kfree(phy_data);
439 return rc;
440}
441
43f775b2 442int efx_mcdi_port_reconfigure(struct efx_nic *efx)
afd4aea0 443{
3bd93035 444 struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
c2ab85d2
EC
445 u32 caps = (efx->link_advertising[0] ?
446 ethtool_linkset_to_mcdi_cap(efx->link_advertising) :
afd4aea0
BH
447 phy_cfg->forced_cap);
448
449 return efx_mcdi_set_link(efx, caps, efx_get_mcdi_phy_flags(efx),
450 efx->loopback_mode, 0);
451}
452
afd4aea0
BH
453/* Verify that the forced flow control settings (!EFX_FC_AUTO) are
454 * supported by the link partner. Warn the user if this isn't the case
455 */
43f775b2 456static void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa)
afd4aea0 457{
3bd93035 458 struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
afd4aea0
BH
459 u32 rmtadv;
460
25985edc 461 /* The link partner capabilities are only relevant if the
afd4aea0 462 * link supports flow control autonegotiation */
7a6b8f6f 463 if (~phy_cfg->supported_cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
afd4aea0
BH
464 return;
465
466 /* If flow control autoneg is supported and enabled, then fine */
467 if (efx->wanted_fc & EFX_FC_AUTO)
468 return;
469
470 rmtadv = 0;
471 if (lpa & (1 << MC_CMD_PHY_CAP_PAUSE_LBN))
472 rmtadv |= ADVERTISED_Pause;
473 if (lpa & (1 << MC_CMD_PHY_CAP_ASYM_LBN))
474 rmtadv |= ADVERTISED_Asym_Pause;
475
476 if ((efx->wanted_fc & EFX_FC_TX) && rmtadv == ADVERTISED_Asym_Pause)
62776d03
BH
477 netif_err(efx, link, efx->net_dev,
478 "warning: link partner doesn't support pause frames");
afd4aea0
BH
479}
480
481static bool efx_mcdi_phy_poll(struct efx_nic *efx)
482{
483 struct efx_link_state old_state = efx->link_state;
59cfc479 484 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
afd4aea0
BH
485 int rc;
486
487 WARN_ON(!mutex_is_locked(&efx->mac_lock));
488
489 BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
490
491 rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
492 outbuf, sizeof(outbuf), NULL);
1e0b8120 493 if (rc)
afd4aea0 494 efx->link_state.up = false;
1e0b8120 495 else
afd4aea0
BH
496 efx_mcdi_phy_decode_link(
497 efx, &efx->link_state,
498 MCDI_DWORD(outbuf, GET_LINK_OUT_LINK_SPEED),
499 MCDI_DWORD(outbuf, GET_LINK_OUT_FLAGS),
500 MCDI_DWORD(outbuf, GET_LINK_OUT_FCNTL));
afd4aea0
BH
501
502 return !efx_link_state_equal(&efx->link_state, &old_state);
503}
504
ff3b00a0 505static void efx_mcdi_phy_remove(struct efx_nic *efx)
afd4aea0
BH
506{
507 struct efx_mcdi_phy_data *phy_data = efx->phy_data;
508
509 efx->phy_data = NULL;
510 kfree(phy_data);
511}
512
7cafe8f8
PR
513static void efx_mcdi_phy_get_link_ksettings(struct efx_nic *efx,
514 struct ethtool_link_ksettings *cmd)
afd4aea0 515{
3bd93035 516 struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
59cfc479 517 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
afd4aea0 518 int rc;
7cafe8f8 519
7cafe8f8
PR
520 cmd->base.speed = efx->link_state.speed;
521 cmd->base.duplex = efx->link_state.fd;
522 cmd->base.port = mcdi_to_ethtool_media(phy_cfg->media);
523 cmd->base.phy_address = phy_cfg->port;
c2ab85d2 524 cmd->base.autoneg = !!(efx->link_advertising[0] & ADVERTISED_Autoneg);
7cafe8f8 525 cmd->base.mdio_support = (efx->mdio.mode_support &
afd4aea0
BH
526 (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22));
527
c2ab85d2
EC
528 mcdi_to_ethtool_linkset(phy_cfg->media, phy_cfg->supported_cap,
529 cmd->link_modes.supported);
530 memcpy(cmd->link_modes.advertising, efx->link_advertising,
531 sizeof(__ETHTOOL_DECLARE_LINK_MODE_MASK()));
7cafe8f8 532
afd4aea0
BH
533 BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
534 rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
535 outbuf, sizeof(outbuf), NULL);
1e0b8120 536 if (rc)
afd4aea0 537 return;
c2ab85d2
EC
538 mcdi_to_ethtool_linkset(phy_cfg->media,
539 MCDI_DWORD(outbuf, GET_LINK_OUT_LP_CAP),
540 cmd->link_modes.lp_advertising);
afd4aea0
BH
541}
542
7cafe8f8
PR
543static int
544efx_mcdi_phy_set_link_ksettings(struct efx_nic *efx,
545 const struct ethtool_link_ksettings *cmd)
afd4aea0 546{
3bd93035 547 struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
afd4aea0
BH
548 u32 caps;
549 int rc;
550
7cafe8f8 551 if (cmd->base.autoneg) {
c2ab85d2
EC
552 caps = (ethtool_linkset_to_mcdi_cap(cmd->link_modes.advertising) |
553 1 << MC_CMD_PHY_CAP_AN_LBN);
7cafe8f8
PR
554 } else if (cmd->base.duplex) {
555 switch (cmd->base.speed) {
702b3d51
EC
556 case 10: caps = 1 << MC_CMD_PHY_CAP_10FDX_LBN; break;
557 case 100: caps = 1 << MC_CMD_PHY_CAP_100FDX_LBN; break;
558 case 1000: caps = 1 << MC_CMD_PHY_CAP_1000FDX_LBN; break;
559 case 10000: caps = 1 << MC_CMD_PHY_CAP_10000FDX_LBN; break;
560 case 40000: caps = 1 << MC_CMD_PHY_CAP_40000FDX_LBN; break;
561 case 100000: caps = 1 << MC_CMD_PHY_CAP_100000FDX_LBN; break;
562 case 25000: caps = 1 << MC_CMD_PHY_CAP_25000FDX_LBN; break;
563 case 50000: caps = 1 << MC_CMD_PHY_CAP_50000FDX_LBN; break;
564 default: return -EINVAL;
afd4aea0
BH
565 }
566 } else {
7cafe8f8 567 switch (cmd->base.speed) {
702b3d51
EC
568 case 10: caps = 1 << MC_CMD_PHY_CAP_10HDX_LBN; break;
569 case 100: caps = 1 << MC_CMD_PHY_CAP_100HDX_LBN; break;
570 case 1000: caps = 1 << MC_CMD_PHY_CAP_1000HDX_LBN; break;
571 default: return -EINVAL;
afd4aea0
BH
572 }
573 }
574
575 rc = efx_mcdi_set_link(efx, caps, efx_get_mcdi_phy_flags(efx),
576 efx->loopback_mode, 0);
577 if (rc)
578 return rc;
579
7cafe8f8 580 if (cmd->base.autoneg) {
c2ab85d2 581 efx_link_set_advertising(efx, cmd->link_modes.advertising);
afd4aea0
BH
582 phy_cfg->forced_cap = 0;
583 } else {
c2ab85d2 584 efx_link_clear_advertising(efx);
afd4aea0
BH
585 phy_cfg->forced_cap = caps;
586 }
587 return 0;
588}
589
4f16c073
BH
590static int efx_mcdi_phy_test_alive(struct efx_nic *efx)
591{
59cfc479 592 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PHY_STATE_OUT_LEN);
4f16c073
BH
593 size_t outlen;
594 int rc;
595
596 BUILD_BUG_ON(MC_CMD_GET_PHY_STATE_IN_LEN != 0);
597
598 rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_STATE, NULL, 0,
599 outbuf, sizeof(outbuf), &outlen);
600 if (rc)
601 return rc;
602
603 if (outlen < MC_CMD_GET_PHY_STATE_OUT_LEN)
00bbb4a5 604 return -EIO;
05a9320f 605 if (MCDI_DWORD(outbuf, GET_PHY_STATE_OUT_STATE) != MC_CMD_PHY_STATE_OK)
4f16c073
BH
606 return -EINVAL;
607
608 return 0;
609}
610
affaf485
SH
611static const char *const mcdi_sft9001_cable_diag_names[] = {
612 "cable.pairA.length",
613 "cable.pairB.length",
614 "cable.pairC.length",
615 "cable.pairD.length",
616 "cable.pairA.status",
617 "cable.pairB.status",
618 "cable.pairC.status",
619 "cable.pairD.status",
620};
621
622static int efx_mcdi_bist(struct efx_nic *efx, unsigned int bist_mode,
623 int *results)
624{
625 unsigned int retry, i, count = 0;
626 size_t outlen;
627 u32 status;
c5bb0e98
BH
628 MCDI_DECLARE_BUF(inbuf, MC_CMD_START_BIST_IN_LEN);
629 MCDI_DECLARE_BUF(outbuf, MC_CMD_POLL_BIST_OUT_SFT9001_LEN);
630 u8 *ptr;
affaf485
SH
631 int rc;
632
affaf485 633 BUILD_BUG_ON(MC_CMD_START_BIST_OUT_LEN != 0);
c5bb0e98
BH
634 MCDI_SET_DWORD(inbuf, START_BIST_IN_TYPE, bist_mode);
635 rc = efx_mcdi_rpc(efx, MC_CMD_START_BIST,
636 inbuf, MC_CMD_START_BIST_IN_LEN, NULL, 0, NULL);
affaf485
SH
637 if (rc)
638 goto out;
639
640 /* Wait up to 10s for BIST to finish */
641 for (retry = 0; retry < 100; ++retry) {
642 BUILD_BUG_ON(MC_CMD_POLL_BIST_IN_LEN != 0);
643 rc = efx_mcdi_rpc(efx, MC_CMD_POLL_BIST, NULL, 0,
c5bb0e98 644 outbuf, sizeof(outbuf), &outlen);
affaf485
SH
645 if (rc)
646 goto out;
647
c5bb0e98 648 status = MCDI_DWORD(outbuf, POLL_BIST_OUT_RESULT);
affaf485
SH
649 if (status != MC_CMD_POLL_BIST_RUNNING)
650 goto finished;
651
652 msleep(100);
653 }
654
655 rc = -ETIMEDOUT;
656 goto out;
657
658finished:
659 results[count++] = (status == MC_CMD_POLL_BIST_PASSED) ? 1 : -1;
660
661 /* SFT9001 specific cable diagnostics output */
662 if (efx->phy_type == PHY_TYPE_SFT9001B &&
663 (bist_mode == MC_CMD_PHY_BIST_CABLE_SHORT ||
664 bist_mode == MC_CMD_PHY_BIST_CABLE_LONG)) {
c5bb0e98 665 ptr = MCDI_PTR(outbuf, POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A);
affaf485
SH
666 if (status == MC_CMD_POLL_BIST_PASSED &&
667 outlen >= MC_CMD_POLL_BIST_OUT_SFT9001_LEN) {
668 for (i = 0; i < 8; i++) {
669 results[count + i] =
670 EFX_DWORD_FIELD(((efx_dword_t *)ptr)[i],
671 EFX_DWORD_0);
672 }
673 }
674 count += 8;
675 }
676 rc = count;
677
678out:
affaf485
SH
679 return rc;
680}
681
682static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results,
683 unsigned flags)
684{
3bd93035 685 struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
affaf485
SH
686 u32 mode;
687 int rc;
688
05a9320f 689 if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_LBN)) {
affaf485
SH
690 rc = efx_mcdi_bist(efx, MC_CMD_PHY_BIST, results);
691 if (rc < 0)
692 return rc;
693
694 results += rc;
695 }
696
697 /* If we support both LONG and SHORT, then run each in response to
698 * break or not. Otherwise, run the one we support */
699 mode = 0;
05a9320f 700 if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN)) {
affaf485
SH
701 if ((flags & ETH_TEST_FL_OFFLINE) &&
702 (phy_cfg->flags &
05a9320f 703 (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN)))
affaf485
SH
704 mode = MC_CMD_PHY_BIST_CABLE_LONG;
705 else
706 mode = MC_CMD_PHY_BIST_CABLE_SHORT;
707 } else if (phy_cfg->flags &
05a9320f 708 (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN))
affaf485
SH
709 mode = MC_CMD_PHY_BIST_CABLE_LONG;
710
711 if (mode != 0) {
712 rc = efx_mcdi_bist(efx, mode, results);
713 if (rc < 0)
714 return rc;
715 results += rc;
716 }
717
718 return 0;
719}
720
d215697f 721static const char *efx_mcdi_phy_test_name(struct efx_nic *efx,
722 unsigned int index)
affaf485 723{
3bd93035 724 struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
affaf485 725
05a9320f 726 if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_LBN)) {
affaf485
SH
727 if (index == 0)
728 return "bist";
729 --index;
730 }
731
05a9320f
BH
732 if (phy_cfg->flags & ((1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN) |
733 (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN))) {
affaf485
SH
734 if (index == 0)
735 return "cable";
736 --index;
737
738 if (efx->phy_type == PHY_TYPE_SFT9001B) {
739 if (index < ARRAY_SIZE(mcdi_sft9001_cable_diag_names))
740 return mcdi_sft9001_cable_diag_names[index];
741 index -= ARRAY_SIZE(mcdi_sft9001_cable_diag_names);
742 }
743 }
744
745 return NULL;
746}
747
9b17010d
MH
748#define SFP_PAGE_SIZE 128
749#define SFF_DIAG_TYPE_OFFSET 92
750#define SFF_DIAG_ADDR_CHANGE BIT(2)
751#define SFF_8079_NUM_PAGES 2
752#define SFF_8472_NUM_PAGES 4
753#define SFF_8436_NUM_PAGES 5
754#define SFF_DMT_LEVEL_OFFSET 94
755
756/** efx_mcdi_phy_get_module_eeprom_page() - Get a single page of module eeprom
757 * @efx: NIC context
758 * @page: EEPROM page number
759 * @data: Destination data pointer
760 * @offset: Offset in page to copy from in to data
761 * @space: Space available in data
762 *
763 * Return:
764 * >=0 - amount of data copied
765 * <0 - error
766 */
767static int efx_mcdi_phy_get_module_eeprom_page(struct efx_nic *efx,
768 unsigned int page,
769 u8 *data, ssize_t offset,
770 ssize_t space)
c087bd2c 771{
59cfc479
BH
772 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX);
773 MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN);
c087bd2c 774 size_t outlen;
c087bd2c 775 unsigned int payload_len;
c087bd2c 776 unsigned int to_copy;
9b17010d 777 int rc;
c087bd2c 778
9b17010d
MH
779 if (offset > SFP_PAGE_SIZE)
780 return -EINVAL;
c087bd2c 781
9b17010d 782 to_copy = min(space, SFP_PAGE_SIZE - offset);
c087bd2c 783
9b17010d
MH
784 MCDI_SET_DWORD(inbuf, GET_PHY_MEDIA_INFO_IN_PAGE, page);
785 rc = efx_mcdi_rpc_quiet(efx, MC_CMD_GET_PHY_MEDIA_INFO,
786 inbuf, sizeof(inbuf),
787 outbuf, sizeof(outbuf),
788 &outlen);
c087bd2c 789
9b17010d
MH
790 if (rc)
791 return rc;
c087bd2c 792
9b17010d
MH
793 if (outlen < (MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST +
794 SFP_PAGE_SIZE))
795 return -EIO;
c087bd2c 796
9b17010d
MH
797 payload_len = MCDI_DWORD(outbuf, GET_PHY_MEDIA_INFO_OUT_DATALEN);
798 if (payload_len != SFP_PAGE_SIZE)
799 return -EIO;
c087bd2c 800
9b17010d
MH
801 memcpy(data, MCDI_PTR(outbuf, GET_PHY_MEDIA_INFO_OUT_DATA) + offset,
802 to_copy);
c087bd2c 803
9b17010d
MH
804 return to_copy;
805}
c087bd2c 806
9b17010d
MH
807static int efx_mcdi_phy_get_module_eeprom_byte(struct efx_nic *efx,
808 unsigned int page,
809 u8 byte)
810{
811 int rc;
812 u8 data;
813
814 rc = efx_mcdi_phy_get_module_eeprom_page(efx, page, &data, byte, 1);
815 if (rc == 1)
816 return data;
817
818 return rc;
819}
820
821static int efx_mcdi_phy_diag_type(struct efx_nic *efx)
822{
823 /* Page zero of the EEPROM includes the diagnostic type at byte 92. */
824 return efx_mcdi_phy_get_module_eeprom_byte(efx, 0,
825 SFF_DIAG_TYPE_OFFSET);
826}
827
828static int efx_mcdi_phy_sff_8472_level(struct efx_nic *efx)
829{
830 /* Page zero of the EEPROM includes the DMT level at byte 94. */
831 return efx_mcdi_phy_get_module_eeprom_byte(efx, 0,
832 SFF_DMT_LEVEL_OFFSET);
833}
834
835static u32 efx_mcdi_phy_module_type(struct efx_nic *efx)
836{
837 struct efx_mcdi_phy_data *phy_data = efx->phy_data;
838
839 if (phy_data->media != MC_CMD_MEDIA_QSFP_PLUS)
840 return phy_data->media;
841
842 /* A QSFP+ NIC may actually have an SFP+ module attached.
843 * The ID is page 0, byte 0.
844 */
845 switch (efx_mcdi_phy_get_module_eeprom_byte(efx, 0, 0)) {
846 case 0x3:
847 return MC_CMD_MEDIA_SFP_PLUS;
848 case 0xc:
849 case 0xd:
850 return MC_CMD_MEDIA_QSFP_PLUS;
851 default:
852 return 0;
853 }
854}
855
856static int efx_mcdi_phy_get_module_eeprom(struct efx_nic *efx,
857 struct ethtool_eeprom *ee, u8 *data)
858{
859 int rc;
860 ssize_t space_remaining = ee->len;
861 unsigned int page_off;
862 bool ignore_missing;
863 int num_pages;
864 int page;
865
866 switch (efx_mcdi_phy_module_type(efx)) {
867 case MC_CMD_MEDIA_SFP_PLUS:
868 num_pages = efx_mcdi_phy_sff_8472_level(efx) > 0 ?
869 SFF_8472_NUM_PAGES : SFF_8079_NUM_PAGES;
870 page = 0;
871 ignore_missing = false;
872 break;
873 case MC_CMD_MEDIA_QSFP_PLUS:
874 num_pages = SFF_8436_NUM_PAGES;
875 page = -1; /* We obtain the lower page by asking for -1. */
876 ignore_missing = true; /* Ignore missing pages after page 0. */
877 break;
878 default:
879 return -EOPNOTSUPP;
880 }
881
882 page_off = ee->offset % SFP_PAGE_SIZE;
883 page += ee->offset / SFP_PAGE_SIZE;
884
885 while (space_remaining && (page < num_pages)) {
886 rc = efx_mcdi_phy_get_module_eeprom_page(efx, page,
887 data, page_off,
888 space_remaining);
889
890 if (rc > 0) {
891 space_remaining -= rc;
892 data += rc;
893 page_off = 0;
894 page++;
895 } else if (rc == 0) {
896 space_remaining = 0;
897 } else if (ignore_missing && (page > 0)) {
898 int intended_size = SFP_PAGE_SIZE - page_off;
899
900 space_remaining -= intended_size;
901 if (space_remaining < 0) {
902 space_remaining = 0;
903 } else {
904 memset(data, 0, intended_size);
905 data += intended_size;
906 page_off = 0;
907 page++;
908 rc = 0;
909 }
910 } else {
911 return rc;
912 }
c087bd2c
SH
913 }
914
915 return 0;
916}
917
918static int efx_mcdi_phy_get_module_info(struct efx_nic *efx,
919 struct ethtool_modinfo *modinfo)
920{
9b17010d
MH
921 int sff_8472_level;
922 int diag_type;
c087bd2c 923
9b17010d 924 switch (efx_mcdi_phy_module_type(efx)) {
c087bd2c 925 case MC_CMD_MEDIA_SFP_PLUS:
9b17010d
MH
926 sff_8472_level = efx_mcdi_phy_sff_8472_level(efx);
927
928 /* If we can't read the diagnostics level we have none. */
929 if (sff_8472_level < 0)
930 return -EOPNOTSUPP;
931
932 /* Check if this module requires the (unsupported) address
933 * change operation.
934 */
935 diag_type = efx_mcdi_phy_diag_type(efx);
936
937 if ((sff_8472_level == 0) ||
938 (diag_type & SFF_DIAG_ADDR_CHANGE)) {
939 modinfo->type = ETH_MODULE_SFF_8079;
940 modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
941 } else {
942 modinfo->type = ETH_MODULE_SFF_8472;
943 modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
944 }
945 break;
946
947 case MC_CMD_MEDIA_QSFP_PLUS:
948 modinfo->type = ETH_MODULE_SFF_8436;
949 modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
950 break;
951
c087bd2c
SH
952 default:
953 return -EOPNOTSUPP;
954 }
9b17010d
MH
955
956 return 0;
c087bd2c
SH
957}
958
43f775b2 959static const struct efx_phy_operations efx_mcdi_phy_ops = {
afd4aea0 960 .probe = efx_mcdi_phy_probe,
9c636baf 961 .init = efx_port_dummy_op_int,
43f775b2 962 .reconfigure = efx_mcdi_port_reconfigure,
afd4aea0 963 .poll = efx_mcdi_phy_poll,
ff3b00a0
SH
964 .fini = efx_port_dummy_op_void,
965 .remove = efx_mcdi_phy_remove,
7cafe8f8
PR
966 .get_link_ksettings = efx_mcdi_phy_get_link_ksettings,
967 .set_link_ksettings = efx_mcdi_phy_set_link_ksettings,
4f16c073 968 .test_alive = efx_mcdi_phy_test_alive,
affaf485
SH
969 .run_tests = efx_mcdi_phy_run_tests,
970 .test_name = efx_mcdi_phy_test_name,
c087bd2c
SH
971 .get_module_eeprom = efx_mcdi_phy_get_module_eeprom,
972 .get_module_info = efx_mcdi_phy_get_module_info,
afd4aea0 973};
43f775b2 974
8127d661
BH
975u32 efx_mcdi_phy_get_caps(struct efx_nic *efx)
976{
977 struct efx_mcdi_phy_data *phy_data = efx->phy_data;
978
979 return phy_data->supported_cap;
980}
981
43f775b2
BH
982static unsigned int efx_mcdi_event_link_speed[] = {
983 [MCDI_EVENT_LINKCHANGE_SPEED_100M] = 100,
984 [MCDI_EVENT_LINKCHANGE_SPEED_1G] = 1000,
985 [MCDI_EVENT_LINKCHANGE_SPEED_10G] = 10000,
9a12a306 986 [MCDI_EVENT_LINKCHANGE_SPEED_40G] = 40000,
702b3d51
EC
987 [MCDI_EVENT_LINKCHANGE_SPEED_25G] = 25000,
988 [MCDI_EVENT_LINKCHANGE_SPEED_50G] = 50000,
989 [MCDI_EVENT_LINKCHANGE_SPEED_100G] = 100000,
43f775b2
BH
990};
991
992void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev)
993{
994 u32 flags, fcntl, speed, lpa;
995
996 speed = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_SPEED);
e01b16a7 997 EFX_WARN_ON_PARANOID(speed >= ARRAY_SIZE(efx_mcdi_event_link_speed));
43f775b2
BH
998 speed = efx_mcdi_event_link_speed[speed];
999
1000 flags = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_LINK_FLAGS);
1001 fcntl = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_FCNTL);
1002 lpa = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_LP_CAP);
1003
1004 /* efx->link_state is only modified by efx_mcdi_phy_get_link(),
1005 * which is only run after flushing the event queues. Therefore, it
1006 * is safe to modify the link state outside of the mac_lock here.
1007 */
1008 efx_mcdi_phy_decode_link(efx, &efx->link_state, speed, flags, fcntl);
1009
1010 efx_mcdi_phy_check_fcntl(efx, lpa);
1011
1012 efx_link_status_changed(efx);
1013}
1014
1015int efx_mcdi_set_mac(struct efx_nic *efx)
1016{
964e6135 1017 u32 fcntl;
43f775b2
BH
1018 MCDI_DECLARE_BUF(cmdbytes, MC_CMD_SET_MAC_IN_LEN);
1019
1020 BUILD_BUG_ON(MC_CMD_SET_MAC_OUT_LEN != 0);
1021
910c8789 1022 /* This has no effect on EF10 */
cd84ff4d
EC
1023 ether_addr_copy(MCDI_PTR(cmdbytes, SET_MAC_IN_ADDR),
1024 efx->net_dev->dev_addr);
43f775b2
BH
1025
1026 MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_MTU,
1027 EFX_MAX_FRAME_LEN(efx->net_dev->mtu));
1028 MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_DRAIN, 0);
1029
964e6135
BH
1030 /* Set simple MAC filter for Siena */
1031 MCDI_POPULATE_DWORD_1(cmdbytes, SET_MAC_IN_REJECT,
1032 SET_MAC_IN_REJECT_UNCST, efx->unicast_filter);
43f775b2 1033
6978729f
EC
1034 MCDI_POPULATE_DWORD_1(cmdbytes, SET_MAC_IN_FLAGS,
1035 SET_MAC_IN_FLAG_INCLUDE_FCS,
1036 !!(efx->net_dev->features & NETIF_F_RXFCS));
1037
43f775b2
BH
1038 switch (efx->wanted_fc) {
1039 case EFX_FC_RX | EFX_FC_TX:
1040 fcntl = MC_CMD_FCNTL_BIDIR;
1041 break;
1042 case EFX_FC_RX:
1043 fcntl = MC_CMD_FCNTL_RESPOND;
1044 break;
1045 default:
1046 fcntl = MC_CMD_FCNTL_OFF;
1047 break;
1048 }
1049 if (efx->wanted_fc & EFX_FC_AUTO)
1050 fcntl = MC_CMD_FCNTL_AUTO;
1051 if (efx->fc_disable)
1052 fcntl = MC_CMD_FCNTL_OFF;
1053
1054 MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_FCNTL, fcntl);
1055
1056 return efx_mcdi_rpc(efx, MC_CMD_SET_MAC, cmdbytes, sizeof(cmdbytes),
1057 NULL, 0, NULL);
1058}
1059
1060bool efx_mcdi_mac_check_fault(struct efx_nic *efx)
1061{
1062 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
1063 size_t outlength;
1064 int rc;
1065
1066 BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
1067
1068 rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
1069 outbuf, sizeof(outbuf), &outlength);
1e0b8120 1070 if (rc)
43f775b2 1071 return true;
43f775b2
BH
1072
1073 return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0;
1074}
1075
f8f3b5ae
JC
1076enum efx_stats_action {
1077 EFX_STATS_ENABLE,
1078 EFX_STATS_DISABLE,
1079 EFX_STATS_PULL,
1080};
1081
1082static int efx_mcdi_mac_stats(struct efx_nic *efx,
1083 enum efx_stats_action action, int clear)
43f775b2
BH
1084{
1085 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAC_STATS_IN_LEN);
1086 int rc;
f8f3b5ae
JC
1087 int change = action == EFX_STATS_PULL ? 0 : 1;
1088 int enable = action == EFX_STATS_ENABLE ? 1 : 0;
1089 int period = action == EFX_STATS_ENABLE ? 1000 : 0;
1090 dma_addr_t dma_addr = efx->stats_buffer.dma_addr;
1091 u32 dma_len = action != EFX_STATS_DISABLE ?
c1be4821 1092 efx->num_mac_stats * sizeof(u64) : 0;
43f775b2
BH
1093
1094 BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0);
1095
1096 MCDI_SET_QWORD(inbuf, MAC_STATS_IN_DMA_ADDR, dma_addr);
f5253d92
BH
1097 MCDI_POPULATE_DWORD_7(inbuf, MAC_STATS_IN_CMD,
1098 MAC_STATS_IN_DMA, !!enable,
1099 MAC_STATS_IN_CLEAR, clear,
f8f3b5ae
JC
1100 MAC_STATS_IN_PERIODIC_CHANGE, change,
1101 MAC_STATS_IN_PERIODIC_ENABLE, enable,
f5253d92
BH
1102 MAC_STATS_IN_PERIODIC_CLEAR, 0,
1103 MAC_STATS_IN_PERIODIC_NOEVENT, 1,
1104 MAC_STATS_IN_PERIOD_MS, period);
43f775b2 1105 MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len);
61deee96
BK
1106
1107 if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0) {
1108 struct efx_ef10_nic_data *nic_data = efx->nic_data;
1109
1110 MCDI_SET_DWORD(inbuf, MAC_STATS_IN_PORT_ID, nic_data->vport_id);
1111 }
43f775b2 1112
6dd4859b
DP
1113 rc = efx_mcdi_rpc_quiet(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf),
1114 NULL, 0, NULL);
1115 /* Expect ENOENT if DMA queues have not been set up */
1116 if (rc && (rc != -ENOENT || atomic_read(&efx->active_queues)))
1117 efx_mcdi_display_error(efx, MC_CMD_MAC_STATS, sizeof(inbuf),
1118 NULL, 0, rc);
43f775b2
BH
1119 return rc;
1120}
1121
1122void efx_mcdi_mac_start_stats(struct efx_nic *efx)
1123{
1124 __le64 *dma_stats = efx->stats_buffer.addr;
1125
c1be4821 1126 dma_stats[efx->num_mac_stats - 1] = EFX_MC_STATS_GENERATION_INVALID;
43f775b2 1127
f8f3b5ae 1128 efx_mcdi_mac_stats(efx, EFX_STATS_ENABLE, 0);
43f775b2
BH
1129}
1130
1131void efx_mcdi_mac_stop_stats(struct efx_nic *efx)
1132{
f8f3b5ae
JC
1133 efx_mcdi_mac_stats(efx, EFX_STATS_DISABLE, 0);
1134}
1135
1136#define EFX_MAC_STATS_WAIT_US 100
1137#define EFX_MAC_STATS_WAIT_ATTEMPTS 10
1138
1139void efx_mcdi_mac_pull_stats(struct efx_nic *efx)
1140{
1141 __le64 *dma_stats = efx->stats_buffer.addr;
1142 int attempts = EFX_MAC_STATS_WAIT_ATTEMPTS;
1143
c1be4821 1144 dma_stats[efx->num_mac_stats - 1] = EFX_MC_STATS_GENERATION_INVALID;
f8f3b5ae
JC
1145 efx_mcdi_mac_stats(efx, EFX_STATS_PULL, 0);
1146
c1be4821 1147 while (dma_stats[efx->num_mac_stats - 1] ==
f8f3b5ae
JC
1148 EFX_MC_STATS_GENERATION_INVALID &&
1149 attempts-- != 0)
1150 udelay(EFX_MAC_STATS_WAIT_US);
43f775b2
BH
1151}
1152
1153int efx_mcdi_port_probe(struct efx_nic *efx)
1154{
1155 int rc;
1156
1157 /* Hook in PHY operations table */
1158 efx->phy_op = &efx_mcdi_phy_ops;
1159
1160 /* Set up MDIO structure for PHY */
1161 efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
1162 efx->mdio.mdio_read = efx_mcdi_mdio_read;
1163 efx->mdio.mdio_write = efx_mcdi_mdio_write;
1164
1165 /* Fill out MDIO structure, loopback modes, and initial link state */
1166 rc = efx->phy_op->probe(efx);
1167 if (rc != 0)
1168 return rc;
1169
1170 /* Allocate buffer for stats */
1171 rc = efx_nic_alloc_buffer(efx, &efx->stats_buffer,
c1be4821 1172 efx->num_mac_stats * sizeof(u64), GFP_KERNEL);
43f775b2
BH
1173 if (rc)
1174 return rc;
1175 netif_dbg(efx, probe, efx->net_dev,
1176 "stats buffer at %llx (virt %p phys %llx)\n",
1177 (u64)efx->stats_buffer.dma_addr,
1178 efx->stats_buffer.addr,
1179 (u64)virt_to_phys(efx->stats_buffer.addr));
1180
f8f3b5ae 1181 efx_mcdi_mac_stats(efx, EFX_STATS_DISABLE, 1);
43f775b2
BH
1182
1183 return 0;
1184}
1185
1186void efx_mcdi_port_remove(struct efx_nic *efx)
1187{
1188 efx->phy_op->remove(efx);
1189 efx_nic_free_buffer(efx, &efx->stats_buffer);
1190}
8127d661
BH
1191
1192/* Get physical port number (EF10 only; on Siena it is same as PF number) */
1193int efx_mcdi_port_get_number(struct efx_nic *efx)
1194{
1195 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN);
1196 int rc;
1197
1198 rc = efx_mcdi_rpc(efx, MC_CMD_GET_PORT_ASSIGNMENT, NULL, 0,
1199 outbuf, sizeof(outbuf), NULL);
1200 if (rc)
1201 return rc;
1202
1203 return MCDI_DWORD(outbuf, GET_PORT_ASSIGNMENT_OUT_PORT);
1204}