Linux Audio

Check our new training course

Loading...
v6.8
  1// SPDX-License-Identifier: GPL-2.0-only
  2/****************************************************************************
  3 * Driver for Solarflare network controllers and boards
  4 * Copyright 2009-2013 Solarflare Communications Inc.
 
 
 
 
  5 */
  6
  7/*
  8 * Driver for PHY related operations via MCDI.
  9 */
 10
 11#include <linux/slab.h>
 12#include "efx.h"
 13#include "mcdi_port.h"
 14#include "mcdi.h"
 15#include "mcdi_pcol.h"
 16#include "nic.h"
 17#include "selftest.h"
 18#include "mcdi_port_common.h"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 19
 20static int efx_mcdi_mdio_read(struct net_device *net_dev,
 21			      int prtad, int devad, u16 addr)
 22{
 23	struct efx_nic *efx = efx_netdev_priv(net_dev);
 24	MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_READ_IN_LEN);
 25	MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_READ_OUT_LEN);
 26	size_t outlen;
 27	int rc;
 28
 29	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_BUS, efx->mdio_bus);
 30	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_PRTAD, prtad);
 31	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_DEVAD, devad);
 32	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_ADDR, addr);
 33
 34	rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_READ, inbuf, sizeof(inbuf),
 35			  outbuf, sizeof(outbuf), &outlen);
 36	if (rc)
 37		return rc;
 38
 39	if (MCDI_DWORD(outbuf, MDIO_READ_OUT_STATUS) !=
 40	    MC_CMD_MDIO_STATUS_GOOD)
 41		return -EIO;
 42
 43	return (u16)MCDI_DWORD(outbuf, MDIO_READ_OUT_VALUE);
 44}
 45
 46static int efx_mcdi_mdio_write(struct net_device *net_dev,
 47			       int prtad, int devad, u16 addr, u16 value)
 48{
 49	struct efx_nic *efx = efx_netdev_priv(net_dev);
 50	MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_WRITE_IN_LEN);
 51	MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_WRITE_OUT_LEN);
 52	size_t outlen;
 53	int rc;
 54
 55	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_BUS, efx->mdio_bus);
 56	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_PRTAD, prtad);
 57	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_DEVAD, devad);
 58	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_ADDR, addr);
 59	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_VALUE, value);
 60
 61	rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_WRITE, inbuf, sizeof(inbuf),
 62			  outbuf, sizeof(outbuf), &outlen);
 63	if (rc)
 64		return rc;
 65
 66	if (MCDI_DWORD(outbuf, MDIO_WRITE_OUT_STATUS) !=
 67	    MC_CMD_MDIO_STATUS_GOOD)
 68		return -EIO;
 69
 70	return 0;
 71}
 72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 73u32 efx_mcdi_phy_get_caps(struct efx_nic *efx)
 74{
 75	struct efx_mcdi_phy_data *phy_data = efx->phy_data;
 76
 77	return phy_data->supported_cap;
 78}
 79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 80bool efx_mcdi_mac_check_fault(struct efx_nic *efx)
 81{
 82	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
 83	size_t outlength;
 84	int rc;
 85
 86	BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
 87
 88	rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
 89			  outbuf, sizeof(outbuf), &outlength);
 90	if (rc)
 91		return true;
 92
 93	return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0;
 94}
 95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 96int efx_mcdi_port_probe(struct efx_nic *efx)
 97{
 98	int rc;
 99
 
 
 
100	/* Set up MDIO structure for PHY */
101	efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
102	efx->mdio.mdio_read = efx_mcdi_mdio_read;
103	efx->mdio.mdio_write = efx_mcdi_mdio_write;
104
105	/* Fill out MDIO structure, loopback modes, and initial link state */
106	rc = efx_mcdi_phy_probe(efx);
107	if (rc != 0)
108		return rc;
109
110	return efx_mcdi_mac_init_stats(efx);
 
 
 
 
 
 
 
 
 
 
 
 
 
111}
112
113void efx_mcdi_port_remove(struct efx_nic *efx)
114{
115	efx_mcdi_phy_remove(efx);
116	efx_mcdi_mac_fini_stats(efx);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117}
v3.15
 
   1/****************************************************************************
   2 * Driver for Solarflare network controllers and boards
   3 * Copyright 2009-2013 Solarflare Communications Inc.
   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
  14#include <linux/slab.h>
  15#include "efx.h"
  16#include "phy.h"
  17#include "mcdi.h"
  18#include "mcdi_pcol.h"
  19#include "nic.h"
  20#include "selftest.h"
  21
  22struct efx_mcdi_phy_data {
  23	u32 flags;
  24	u32 type;
  25	u32 supported_cap;
  26	u32 channel;
  27	u32 port;
  28	u32 stats_mask;
  29	u8 name[20];
  30	u32 media;
  31	u32 mmd_mask;
  32	u8 revision[20];
  33	u32 forced_cap;
  34};
  35
  36static int
  37efx_mcdi_get_phy_cfg(struct efx_nic *efx, struct efx_mcdi_phy_data *cfg)
  38{
  39	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PHY_CFG_OUT_LEN);
  40	size_t outlen;
  41	int rc;
  42
  43	BUILD_BUG_ON(MC_CMD_GET_PHY_CFG_IN_LEN != 0);
  44	BUILD_BUG_ON(MC_CMD_GET_PHY_CFG_OUT_NAME_LEN != sizeof(cfg->name));
  45
  46	rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_CFG, NULL, 0,
  47			  outbuf, sizeof(outbuf), &outlen);
  48	if (rc)
  49		goto fail;
  50
  51	if (outlen < MC_CMD_GET_PHY_CFG_OUT_LEN) {
  52		rc = -EIO;
  53		goto fail;
  54	}
  55
  56	cfg->flags = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_FLAGS);
  57	cfg->type = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_TYPE);
  58	cfg->supported_cap =
  59		MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_SUPPORTED_CAP);
  60	cfg->channel = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_CHANNEL);
  61	cfg->port = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_PRT);
  62	cfg->stats_mask = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_STATS_MASK);
  63	memcpy(cfg->name, MCDI_PTR(outbuf, GET_PHY_CFG_OUT_NAME),
  64	       sizeof(cfg->name));
  65	cfg->media = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_MEDIA_TYPE);
  66	cfg->mmd_mask = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_MMD_MASK);
  67	memcpy(cfg->revision, MCDI_PTR(outbuf, GET_PHY_CFG_OUT_REVISION),
  68	       sizeof(cfg->revision));
  69
  70	return 0;
  71
  72fail:
  73	netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
  74	return rc;
  75}
  76
  77static int efx_mcdi_set_link(struct efx_nic *efx, u32 capabilities,
  78			     u32 flags, u32 loopback_mode,
  79			     u32 loopback_speed)
  80{
  81	MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_LINK_IN_LEN);
  82	int rc;
  83
  84	BUILD_BUG_ON(MC_CMD_SET_LINK_OUT_LEN != 0);
  85
  86	MCDI_SET_DWORD(inbuf, SET_LINK_IN_CAP, capabilities);
  87	MCDI_SET_DWORD(inbuf, SET_LINK_IN_FLAGS, flags);
  88	MCDI_SET_DWORD(inbuf, SET_LINK_IN_LOOPBACK_MODE, loopback_mode);
  89	MCDI_SET_DWORD(inbuf, SET_LINK_IN_LOOPBACK_SPEED, loopback_speed);
  90
  91	rc = efx_mcdi_rpc(efx, MC_CMD_SET_LINK, inbuf, sizeof(inbuf),
  92			  NULL, 0, NULL);
  93	return rc;
  94}
  95
  96static int efx_mcdi_loopback_modes(struct efx_nic *efx, u64 *loopback_modes)
  97{
  98	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LOOPBACK_MODES_OUT_LEN);
  99	size_t outlen;
 100	int rc;
 101
 102	rc = efx_mcdi_rpc(efx, MC_CMD_GET_LOOPBACK_MODES, NULL, 0,
 103			  outbuf, sizeof(outbuf), &outlen);
 104	if (rc)
 105		goto fail;
 106
 107	if (outlen < (MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST +
 108		      MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN)) {
 109		rc = -EIO;
 110		goto fail;
 111	}
 112
 113	*loopback_modes = MCDI_QWORD(outbuf, GET_LOOPBACK_MODES_OUT_SUGGESTED);
 114
 115	return 0;
 116
 117fail:
 118	netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
 119	return rc;
 120}
 121
 122static int efx_mcdi_mdio_read(struct net_device *net_dev,
 123			      int prtad, int devad, u16 addr)
 124{
 125	struct efx_nic *efx = netdev_priv(net_dev);
 126	MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_READ_IN_LEN);
 127	MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_READ_OUT_LEN);
 128	size_t outlen;
 129	int rc;
 130
 131	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_BUS, efx->mdio_bus);
 132	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_PRTAD, prtad);
 133	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_DEVAD, devad);
 134	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_ADDR, addr);
 135
 136	rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_READ, inbuf, sizeof(inbuf),
 137			  outbuf, sizeof(outbuf), &outlen);
 138	if (rc)
 139		return rc;
 140
 141	if (MCDI_DWORD(outbuf, MDIO_READ_OUT_STATUS) !=
 142	    MC_CMD_MDIO_STATUS_GOOD)
 143		return -EIO;
 144
 145	return (u16)MCDI_DWORD(outbuf, MDIO_READ_OUT_VALUE);
 146}
 147
 148static int efx_mcdi_mdio_write(struct net_device *net_dev,
 149			       int prtad, int devad, u16 addr, u16 value)
 150{
 151	struct efx_nic *efx = netdev_priv(net_dev);
 152	MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_WRITE_IN_LEN);
 153	MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_WRITE_OUT_LEN);
 154	size_t outlen;
 155	int rc;
 156
 157	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_BUS, efx->mdio_bus);
 158	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_PRTAD, prtad);
 159	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_DEVAD, devad);
 160	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_ADDR, addr);
 161	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_VALUE, value);
 162
 163	rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_WRITE, inbuf, sizeof(inbuf),
 164			  outbuf, sizeof(outbuf), &outlen);
 165	if (rc)
 166		return rc;
 167
 168	if (MCDI_DWORD(outbuf, MDIO_WRITE_OUT_STATUS) !=
 169	    MC_CMD_MDIO_STATUS_GOOD)
 170		return -EIO;
 171
 172	return 0;
 173}
 174
 175static u32 mcdi_to_ethtool_cap(u32 media, u32 cap)
 176{
 177	u32 result = 0;
 178
 179	switch (media) {
 180	case MC_CMD_MEDIA_KX4:
 181		result |= SUPPORTED_Backplane;
 182		if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
 183			result |= SUPPORTED_1000baseKX_Full;
 184		if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
 185			result |= SUPPORTED_10000baseKX4_Full;
 186		break;
 187
 188	case MC_CMD_MEDIA_XFP:
 189	case MC_CMD_MEDIA_SFP_PLUS:
 190		result |= SUPPORTED_FIBRE;
 191		break;
 192
 193	case MC_CMD_MEDIA_BASE_T:
 194		result |= SUPPORTED_TP;
 195		if (cap & (1 << MC_CMD_PHY_CAP_10HDX_LBN))
 196			result |= SUPPORTED_10baseT_Half;
 197		if (cap & (1 << MC_CMD_PHY_CAP_10FDX_LBN))
 198			result |= SUPPORTED_10baseT_Full;
 199		if (cap & (1 << MC_CMD_PHY_CAP_100HDX_LBN))
 200			result |= SUPPORTED_100baseT_Half;
 201		if (cap & (1 << MC_CMD_PHY_CAP_100FDX_LBN))
 202			result |= SUPPORTED_100baseT_Full;
 203		if (cap & (1 << MC_CMD_PHY_CAP_1000HDX_LBN))
 204			result |= SUPPORTED_1000baseT_Half;
 205		if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
 206			result |= SUPPORTED_1000baseT_Full;
 207		if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
 208			result |= SUPPORTED_10000baseT_Full;
 209		break;
 210	}
 211
 212	if (cap & (1 << MC_CMD_PHY_CAP_PAUSE_LBN))
 213		result |= SUPPORTED_Pause;
 214	if (cap & (1 << MC_CMD_PHY_CAP_ASYM_LBN))
 215		result |= SUPPORTED_Asym_Pause;
 216	if (cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
 217		result |= SUPPORTED_Autoneg;
 218
 219	return result;
 220}
 221
 222static u32 ethtool_to_mcdi_cap(u32 cap)
 223{
 224	u32 result = 0;
 225
 226	if (cap & SUPPORTED_10baseT_Half)
 227		result |= (1 << MC_CMD_PHY_CAP_10HDX_LBN);
 228	if (cap & SUPPORTED_10baseT_Full)
 229		result |= (1 << MC_CMD_PHY_CAP_10FDX_LBN);
 230	if (cap & SUPPORTED_100baseT_Half)
 231		result |= (1 << MC_CMD_PHY_CAP_100HDX_LBN);
 232	if (cap & SUPPORTED_100baseT_Full)
 233		result |= (1 << MC_CMD_PHY_CAP_100FDX_LBN);
 234	if (cap & SUPPORTED_1000baseT_Half)
 235		result |= (1 << MC_CMD_PHY_CAP_1000HDX_LBN);
 236	if (cap & (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseKX_Full))
 237		result |= (1 << MC_CMD_PHY_CAP_1000FDX_LBN);
 238	if (cap & (SUPPORTED_10000baseT_Full | SUPPORTED_10000baseKX4_Full))
 239		result |= (1 << MC_CMD_PHY_CAP_10000FDX_LBN);
 240	if (cap & SUPPORTED_Pause)
 241		result |= (1 << MC_CMD_PHY_CAP_PAUSE_LBN);
 242	if (cap & SUPPORTED_Asym_Pause)
 243		result |= (1 << MC_CMD_PHY_CAP_ASYM_LBN);
 244	if (cap & SUPPORTED_Autoneg)
 245		result |= (1 << MC_CMD_PHY_CAP_AN_LBN);
 246
 247	return result;
 248}
 249
 250static u32 efx_get_mcdi_phy_flags(struct efx_nic *efx)
 251{
 252	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 253	enum efx_phy_mode mode, supported;
 254	u32 flags;
 255
 256	/* TODO: Advertise the capabilities supported by this PHY */
 257	supported = 0;
 258	if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_TXDIS_LBN))
 259		supported |= PHY_MODE_TX_DISABLED;
 260	if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_LOWPOWER_LBN))
 261		supported |= PHY_MODE_LOW_POWER;
 262	if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_POWEROFF_LBN))
 263		supported |= PHY_MODE_OFF;
 264
 265	mode = efx->phy_mode & supported;
 266
 267	flags = 0;
 268	if (mode & PHY_MODE_TX_DISABLED)
 269		flags |= (1 << MC_CMD_SET_LINK_IN_TXDIS_LBN);
 270	if (mode & PHY_MODE_LOW_POWER)
 271		flags |= (1 << MC_CMD_SET_LINK_IN_LOWPOWER_LBN);
 272	if (mode & PHY_MODE_OFF)
 273		flags |= (1 << MC_CMD_SET_LINK_IN_POWEROFF_LBN);
 274
 275	return flags;
 276}
 277
 278static u32 mcdi_to_ethtool_media(u32 media)
 279{
 280	switch (media) {
 281	case MC_CMD_MEDIA_XAUI:
 282	case MC_CMD_MEDIA_CX4:
 283	case MC_CMD_MEDIA_KX4:
 284		return PORT_OTHER;
 285
 286	case MC_CMD_MEDIA_XFP:
 287	case MC_CMD_MEDIA_SFP_PLUS:
 288		return PORT_FIBRE;
 289
 290	case MC_CMD_MEDIA_BASE_T:
 291		return PORT_TP;
 292
 293	default:
 294		return PORT_OTHER;
 295	}
 296}
 297
 298static void efx_mcdi_phy_decode_link(struct efx_nic *efx,
 299			      struct efx_link_state *link_state,
 300			      u32 speed, u32 flags, u32 fcntl)
 301{
 302	switch (fcntl) {
 303	case MC_CMD_FCNTL_AUTO:
 304		WARN_ON(1);	/* This is not a link mode */
 305		link_state->fc = EFX_FC_AUTO | EFX_FC_TX | EFX_FC_RX;
 306		break;
 307	case MC_CMD_FCNTL_BIDIR:
 308		link_state->fc = EFX_FC_TX | EFX_FC_RX;
 309		break;
 310	case MC_CMD_FCNTL_RESPOND:
 311		link_state->fc = EFX_FC_RX;
 312		break;
 313	default:
 314		WARN_ON(1);
 315	case MC_CMD_FCNTL_OFF:
 316		link_state->fc = 0;
 317		break;
 318	}
 319
 320	link_state->up = !!(flags & (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN));
 321	link_state->fd = !!(flags & (1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN));
 322	link_state->speed = speed;
 323}
 324
 325static int efx_mcdi_phy_probe(struct efx_nic *efx)
 326{
 327	struct efx_mcdi_phy_data *phy_data;
 328	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
 329	u32 caps;
 330	int rc;
 331
 332	/* Initialise and populate phy_data */
 333	phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
 334	if (phy_data == NULL)
 335		return -ENOMEM;
 336
 337	rc = efx_mcdi_get_phy_cfg(efx, phy_data);
 338	if (rc != 0)
 339		goto fail;
 340
 341	/* Read initial link advertisement */
 342	BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
 343	rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
 344			  outbuf, sizeof(outbuf), NULL);
 345	if (rc)
 346		goto fail;
 347
 348	/* Fill out nic state */
 349	efx->phy_data = phy_data;
 350	efx->phy_type = phy_data->type;
 351
 352	efx->mdio_bus = phy_data->channel;
 353	efx->mdio.prtad = phy_data->port;
 354	efx->mdio.mmds = phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22);
 355	efx->mdio.mode_support = 0;
 356	if (phy_data->mmd_mask & (1 << MC_CMD_MMD_CLAUSE22))
 357		efx->mdio.mode_support |= MDIO_SUPPORTS_C22;
 358	if (phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22))
 359		efx->mdio.mode_support |= MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
 360
 361	caps = MCDI_DWORD(outbuf, GET_LINK_OUT_CAP);
 362	if (caps & (1 << MC_CMD_PHY_CAP_AN_LBN))
 363		efx->link_advertising =
 364			mcdi_to_ethtool_cap(phy_data->media, caps);
 365	else
 366		phy_data->forced_cap = caps;
 367
 368	/* Assert that we can map efx -> mcdi loopback modes */
 369	BUILD_BUG_ON(LOOPBACK_NONE != MC_CMD_LOOPBACK_NONE);
 370	BUILD_BUG_ON(LOOPBACK_DATA != MC_CMD_LOOPBACK_DATA);
 371	BUILD_BUG_ON(LOOPBACK_GMAC != MC_CMD_LOOPBACK_GMAC);
 372	BUILD_BUG_ON(LOOPBACK_XGMII != MC_CMD_LOOPBACK_XGMII);
 373	BUILD_BUG_ON(LOOPBACK_XGXS != MC_CMD_LOOPBACK_XGXS);
 374	BUILD_BUG_ON(LOOPBACK_XAUI != MC_CMD_LOOPBACK_XAUI);
 375	BUILD_BUG_ON(LOOPBACK_GMII != MC_CMD_LOOPBACK_GMII);
 376	BUILD_BUG_ON(LOOPBACK_SGMII != MC_CMD_LOOPBACK_SGMII);
 377	BUILD_BUG_ON(LOOPBACK_XGBR != MC_CMD_LOOPBACK_XGBR);
 378	BUILD_BUG_ON(LOOPBACK_XFI != MC_CMD_LOOPBACK_XFI);
 379	BUILD_BUG_ON(LOOPBACK_XAUI_FAR != MC_CMD_LOOPBACK_XAUI_FAR);
 380	BUILD_BUG_ON(LOOPBACK_GMII_FAR != MC_CMD_LOOPBACK_GMII_FAR);
 381	BUILD_BUG_ON(LOOPBACK_SGMII_FAR != MC_CMD_LOOPBACK_SGMII_FAR);
 382	BUILD_BUG_ON(LOOPBACK_XFI_FAR != MC_CMD_LOOPBACK_XFI_FAR);
 383	BUILD_BUG_ON(LOOPBACK_GPHY != MC_CMD_LOOPBACK_GPHY);
 384	BUILD_BUG_ON(LOOPBACK_PHYXS != MC_CMD_LOOPBACK_PHYXS);
 385	BUILD_BUG_ON(LOOPBACK_PCS != MC_CMD_LOOPBACK_PCS);
 386	BUILD_BUG_ON(LOOPBACK_PMAPMD != MC_CMD_LOOPBACK_PMAPMD);
 387	BUILD_BUG_ON(LOOPBACK_XPORT != MC_CMD_LOOPBACK_XPORT);
 388	BUILD_BUG_ON(LOOPBACK_XGMII_WS != MC_CMD_LOOPBACK_XGMII_WS);
 389	BUILD_BUG_ON(LOOPBACK_XAUI_WS != MC_CMD_LOOPBACK_XAUI_WS);
 390	BUILD_BUG_ON(LOOPBACK_XAUI_WS_FAR != MC_CMD_LOOPBACK_XAUI_WS_FAR);
 391	BUILD_BUG_ON(LOOPBACK_XAUI_WS_NEAR != MC_CMD_LOOPBACK_XAUI_WS_NEAR);
 392	BUILD_BUG_ON(LOOPBACK_GMII_WS != MC_CMD_LOOPBACK_GMII_WS);
 393	BUILD_BUG_ON(LOOPBACK_XFI_WS != MC_CMD_LOOPBACK_XFI_WS);
 394	BUILD_BUG_ON(LOOPBACK_XFI_WS_FAR != MC_CMD_LOOPBACK_XFI_WS_FAR);
 395	BUILD_BUG_ON(LOOPBACK_PHYXS_WS != MC_CMD_LOOPBACK_PHYXS_WS);
 396
 397	rc = efx_mcdi_loopback_modes(efx, &efx->loopback_modes);
 398	if (rc != 0)
 399		goto fail;
 400	/* The MC indicates that LOOPBACK_NONE is a valid loopback mode,
 401	 * but by convention we don't */
 402	efx->loopback_modes &= ~(1 << LOOPBACK_NONE);
 403
 404	/* Set the initial link mode */
 405	efx_mcdi_phy_decode_link(
 406		efx, &efx->link_state,
 407		MCDI_DWORD(outbuf, GET_LINK_OUT_LINK_SPEED),
 408		MCDI_DWORD(outbuf, GET_LINK_OUT_FLAGS),
 409		MCDI_DWORD(outbuf, GET_LINK_OUT_FCNTL));
 410
 411	/* Default to Autonegotiated flow control if the PHY supports it */
 412	efx->wanted_fc = EFX_FC_RX | EFX_FC_TX;
 413	if (phy_data->supported_cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
 414		efx->wanted_fc |= EFX_FC_AUTO;
 415	efx_link_set_wanted_fc(efx, efx->wanted_fc);
 416
 417	return 0;
 418
 419fail:
 420	kfree(phy_data);
 421	return rc;
 422}
 423
 424int efx_mcdi_port_reconfigure(struct efx_nic *efx)
 425{
 426	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 427	u32 caps = (efx->link_advertising ?
 428		    ethtool_to_mcdi_cap(efx->link_advertising) :
 429		    phy_cfg->forced_cap);
 430
 431	return efx_mcdi_set_link(efx, caps, efx_get_mcdi_phy_flags(efx),
 432				 efx->loopback_mode, 0);
 433}
 434
 435/* Verify that the forced flow control settings (!EFX_FC_AUTO) are
 436 * supported by the link partner. Warn the user if this isn't the case
 437 */
 438static void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa)
 439{
 440	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 441	u32 rmtadv;
 442
 443	/* The link partner capabilities are only relevant if the
 444	 * link supports flow control autonegotiation */
 445	if (~phy_cfg->supported_cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
 446		return;
 447
 448	/* If flow control autoneg is supported and enabled, then fine */
 449	if (efx->wanted_fc & EFX_FC_AUTO)
 450		return;
 451
 452	rmtadv = 0;
 453	if (lpa & (1 << MC_CMD_PHY_CAP_PAUSE_LBN))
 454		rmtadv |= ADVERTISED_Pause;
 455	if (lpa & (1 << MC_CMD_PHY_CAP_ASYM_LBN))
 456		rmtadv |=  ADVERTISED_Asym_Pause;
 457
 458	if ((efx->wanted_fc & EFX_FC_TX) && rmtadv == ADVERTISED_Asym_Pause)
 459		netif_err(efx, link, efx->net_dev,
 460			  "warning: link partner doesn't support pause frames");
 461}
 462
 463static bool efx_mcdi_phy_poll(struct efx_nic *efx)
 464{
 465	struct efx_link_state old_state = efx->link_state;
 466	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
 467	int rc;
 468
 469	WARN_ON(!mutex_is_locked(&efx->mac_lock));
 470
 471	BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
 472
 473	rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
 474			  outbuf, sizeof(outbuf), NULL);
 475	if (rc)
 476		efx->link_state.up = false;
 477	else
 478		efx_mcdi_phy_decode_link(
 479			efx, &efx->link_state,
 480			MCDI_DWORD(outbuf, GET_LINK_OUT_LINK_SPEED),
 481			MCDI_DWORD(outbuf, GET_LINK_OUT_FLAGS),
 482			MCDI_DWORD(outbuf, GET_LINK_OUT_FCNTL));
 483
 484	return !efx_link_state_equal(&efx->link_state, &old_state);
 485}
 486
 487static void efx_mcdi_phy_remove(struct efx_nic *efx)
 488{
 489	struct efx_mcdi_phy_data *phy_data = efx->phy_data;
 490
 491	efx->phy_data = NULL;
 492	kfree(phy_data);
 493}
 494
 495static void efx_mcdi_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
 496{
 497	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 498	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
 499	int rc;
 500
 501	ecmd->supported =
 502		mcdi_to_ethtool_cap(phy_cfg->media, phy_cfg->supported_cap);
 503	ecmd->advertising = efx->link_advertising;
 504	ethtool_cmd_speed_set(ecmd, efx->link_state.speed);
 505	ecmd->duplex = efx->link_state.fd;
 506	ecmd->port = mcdi_to_ethtool_media(phy_cfg->media);
 507	ecmd->phy_address = phy_cfg->port;
 508	ecmd->transceiver = XCVR_INTERNAL;
 509	ecmd->autoneg = !!(efx->link_advertising & ADVERTISED_Autoneg);
 510	ecmd->mdio_support = (efx->mdio.mode_support &
 511			      (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22));
 512
 513	BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
 514	rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
 515			  outbuf, sizeof(outbuf), NULL);
 516	if (rc)
 517		return;
 518	ecmd->lp_advertising =
 519		mcdi_to_ethtool_cap(phy_cfg->media,
 520				    MCDI_DWORD(outbuf, GET_LINK_OUT_LP_CAP));
 521}
 522
 523static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
 524{
 525	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 526	u32 caps;
 527	int rc;
 528
 529	if (ecmd->autoneg) {
 530		caps = (ethtool_to_mcdi_cap(ecmd->advertising) |
 531			 1 << MC_CMD_PHY_CAP_AN_LBN);
 532	} else if (ecmd->duplex) {
 533		switch (ethtool_cmd_speed(ecmd)) {
 534		case 10:    caps = 1 << MC_CMD_PHY_CAP_10FDX_LBN;    break;
 535		case 100:   caps = 1 << MC_CMD_PHY_CAP_100FDX_LBN;   break;
 536		case 1000:  caps = 1 << MC_CMD_PHY_CAP_1000FDX_LBN;  break;
 537		case 10000: caps = 1 << MC_CMD_PHY_CAP_10000FDX_LBN; break;
 538		case 40000: caps = 1 << MC_CMD_PHY_CAP_40000FDX_LBN; break;
 539		default:    return -EINVAL;
 540		}
 541	} else {
 542		switch (ethtool_cmd_speed(ecmd)) {
 543		case 10:    caps = 1 << MC_CMD_PHY_CAP_10HDX_LBN;    break;
 544		case 100:   caps = 1 << MC_CMD_PHY_CAP_100HDX_LBN;   break;
 545		case 1000:  caps = 1 << MC_CMD_PHY_CAP_1000HDX_LBN;  break;
 546		default:    return -EINVAL;
 547		}
 548	}
 549
 550	rc = efx_mcdi_set_link(efx, caps, efx_get_mcdi_phy_flags(efx),
 551			       efx->loopback_mode, 0);
 552	if (rc)
 553		return rc;
 554
 555	if (ecmd->autoneg) {
 556		efx_link_set_advertising(
 557			efx, ecmd->advertising | ADVERTISED_Autoneg);
 558		phy_cfg->forced_cap = 0;
 559	} else {
 560		efx_link_set_advertising(efx, 0);
 561		phy_cfg->forced_cap = caps;
 562	}
 563	return 0;
 564}
 565
 566static int efx_mcdi_phy_test_alive(struct efx_nic *efx)
 567{
 568	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PHY_STATE_OUT_LEN);
 569	size_t outlen;
 570	int rc;
 571
 572	BUILD_BUG_ON(MC_CMD_GET_PHY_STATE_IN_LEN != 0);
 573
 574	rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_STATE, NULL, 0,
 575			  outbuf, sizeof(outbuf), &outlen);
 576	if (rc)
 577		return rc;
 578
 579	if (outlen < MC_CMD_GET_PHY_STATE_OUT_LEN)
 580		return -EIO;
 581	if (MCDI_DWORD(outbuf, GET_PHY_STATE_OUT_STATE) != MC_CMD_PHY_STATE_OK)
 582		return -EINVAL;
 583
 584	return 0;
 585}
 586
 587static const char *const mcdi_sft9001_cable_diag_names[] = {
 588	"cable.pairA.length",
 589	"cable.pairB.length",
 590	"cable.pairC.length",
 591	"cable.pairD.length",
 592	"cable.pairA.status",
 593	"cable.pairB.status",
 594	"cable.pairC.status",
 595	"cable.pairD.status",
 596};
 597
 598static int efx_mcdi_bist(struct efx_nic *efx, unsigned int bist_mode,
 599			 int *results)
 600{
 601	unsigned int retry, i, count = 0;
 602	size_t outlen;
 603	u32 status;
 604	MCDI_DECLARE_BUF(inbuf, MC_CMD_START_BIST_IN_LEN);
 605	MCDI_DECLARE_BUF(outbuf, MC_CMD_POLL_BIST_OUT_SFT9001_LEN);
 606	u8 *ptr;
 607	int rc;
 608
 609	BUILD_BUG_ON(MC_CMD_START_BIST_OUT_LEN != 0);
 610	MCDI_SET_DWORD(inbuf, START_BIST_IN_TYPE, bist_mode);
 611	rc = efx_mcdi_rpc(efx, MC_CMD_START_BIST,
 612			  inbuf, MC_CMD_START_BIST_IN_LEN, NULL, 0, NULL);
 613	if (rc)
 614		goto out;
 615
 616	/* Wait up to 10s for BIST to finish */
 617	for (retry = 0; retry < 100; ++retry) {
 618		BUILD_BUG_ON(MC_CMD_POLL_BIST_IN_LEN != 0);
 619		rc = efx_mcdi_rpc(efx, MC_CMD_POLL_BIST, NULL, 0,
 620				  outbuf, sizeof(outbuf), &outlen);
 621		if (rc)
 622			goto out;
 623
 624		status = MCDI_DWORD(outbuf, POLL_BIST_OUT_RESULT);
 625		if (status != MC_CMD_POLL_BIST_RUNNING)
 626			goto finished;
 627
 628		msleep(100);
 629	}
 630
 631	rc = -ETIMEDOUT;
 632	goto out;
 633
 634finished:
 635	results[count++] = (status == MC_CMD_POLL_BIST_PASSED) ? 1 : -1;
 636
 637	/* SFT9001 specific cable diagnostics output */
 638	if (efx->phy_type == PHY_TYPE_SFT9001B &&
 639	    (bist_mode == MC_CMD_PHY_BIST_CABLE_SHORT ||
 640	     bist_mode == MC_CMD_PHY_BIST_CABLE_LONG)) {
 641		ptr = MCDI_PTR(outbuf, POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A);
 642		if (status == MC_CMD_POLL_BIST_PASSED &&
 643		    outlen >= MC_CMD_POLL_BIST_OUT_SFT9001_LEN) {
 644			for (i = 0; i < 8; i++) {
 645				results[count + i] =
 646					EFX_DWORD_FIELD(((efx_dword_t *)ptr)[i],
 647							EFX_DWORD_0);
 648			}
 649		}
 650		count += 8;
 651	}
 652	rc = count;
 653
 654out:
 655	return rc;
 656}
 657
 658static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results,
 659				  unsigned flags)
 660{
 661	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 662	u32 mode;
 663	int rc;
 664
 665	if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_LBN)) {
 666		rc = efx_mcdi_bist(efx, MC_CMD_PHY_BIST, results);
 667		if (rc < 0)
 668			return rc;
 669
 670		results += rc;
 671	}
 672
 673	/* If we support both LONG and SHORT, then run each in response to
 674	 * break or not. Otherwise, run the one we support */
 675	mode = 0;
 676	if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN)) {
 677		if ((flags & ETH_TEST_FL_OFFLINE) &&
 678		    (phy_cfg->flags &
 679		     (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN)))
 680			mode = MC_CMD_PHY_BIST_CABLE_LONG;
 681		else
 682			mode = MC_CMD_PHY_BIST_CABLE_SHORT;
 683	} else if (phy_cfg->flags &
 684		   (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN))
 685		mode = MC_CMD_PHY_BIST_CABLE_LONG;
 686
 687	if (mode != 0) {
 688		rc = efx_mcdi_bist(efx, mode, results);
 689		if (rc < 0)
 690			return rc;
 691		results += rc;
 692	}
 693
 694	return 0;
 695}
 696
 697static const char *efx_mcdi_phy_test_name(struct efx_nic *efx,
 698					  unsigned int index)
 699{
 700	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 701
 702	if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_LBN)) {
 703		if (index == 0)
 704			return "bist";
 705		--index;
 706	}
 707
 708	if (phy_cfg->flags & ((1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN) |
 709			      (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN))) {
 710		if (index == 0)
 711			return "cable";
 712		--index;
 713
 714		if (efx->phy_type == PHY_TYPE_SFT9001B) {
 715			if (index < ARRAY_SIZE(mcdi_sft9001_cable_diag_names))
 716				return mcdi_sft9001_cable_diag_names[index];
 717			index -= ARRAY_SIZE(mcdi_sft9001_cable_diag_names);
 718		}
 719	}
 720
 721	return NULL;
 722}
 723
 724#define SFP_PAGE_SIZE	128
 725#define SFP_NUM_PAGES	2
 726static int efx_mcdi_phy_get_module_eeprom(struct efx_nic *efx,
 727					  struct ethtool_eeprom *ee, u8 *data)
 728{
 729	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX);
 730	MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN);
 731	size_t outlen;
 732	int rc;
 733	unsigned int payload_len;
 734	unsigned int space_remaining = ee->len;
 735	unsigned int page;
 736	unsigned int page_off;
 737	unsigned int to_copy;
 738	u8 *user_data = data;
 739
 740	BUILD_BUG_ON(SFP_PAGE_SIZE * SFP_NUM_PAGES != ETH_MODULE_SFF_8079_LEN);
 741
 742	page_off = ee->offset % SFP_PAGE_SIZE;
 743	page = ee->offset / SFP_PAGE_SIZE;
 744
 745	while (space_remaining && (page < SFP_NUM_PAGES)) {
 746		MCDI_SET_DWORD(inbuf, GET_PHY_MEDIA_INFO_IN_PAGE, page);
 747
 748		rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_MEDIA_INFO,
 749				  inbuf, sizeof(inbuf),
 750				  outbuf, sizeof(outbuf),
 751				  &outlen);
 752		if (rc)
 753			return rc;
 754
 755		if (outlen < (MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST +
 756			      SFP_PAGE_SIZE))
 757			return -EIO;
 758
 759		payload_len = MCDI_DWORD(outbuf,
 760					 GET_PHY_MEDIA_INFO_OUT_DATALEN);
 761		if (payload_len != SFP_PAGE_SIZE)
 762			return -EIO;
 763
 764		/* Copy as much as we can into data */
 765		payload_len -= page_off;
 766		to_copy = (space_remaining < payload_len) ?
 767			space_remaining : payload_len;
 768
 769		memcpy(user_data,
 770		       MCDI_PTR(outbuf, GET_PHY_MEDIA_INFO_OUT_DATA) + page_off,
 771		       to_copy);
 772
 773		space_remaining -= to_copy;
 774		user_data += to_copy;
 775		page_off = 0;
 776		page++;
 777	}
 778
 779	return 0;
 780}
 781
 782static int efx_mcdi_phy_get_module_info(struct efx_nic *efx,
 783					struct ethtool_modinfo *modinfo)
 784{
 785	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 786
 787	switch (phy_cfg->media) {
 788	case MC_CMD_MEDIA_SFP_PLUS:
 789		modinfo->type = ETH_MODULE_SFF_8079;
 790		modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
 791		return 0;
 792	default:
 793		return -EOPNOTSUPP;
 794	}
 795}
 796
 797static const struct efx_phy_operations efx_mcdi_phy_ops = {
 798	.probe		= efx_mcdi_phy_probe,
 799	.init		= efx_port_dummy_op_int,
 800	.reconfigure	= efx_mcdi_port_reconfigure,
 801	.poll		= efx_mcdi_phy_poll,
 802	.fini		= efx_port_dummy_op_void,
 803	.remove		= efx_mcdi_phy_remove,
 804	.get_settings	= efx_mcdi_phy_get_settings,
 805	.set_settings	= efx_mcdi_phy_set_settings,
 806	.test_alive	= efx_mcdi_phy_test_alive,
 807	.run_tests	= efx_mcdi_phy_run_tests,
 808	.test_name	= efx_mcdi_phy_test_name,
 809	.get_module_eeprom = efx_mcdi_phy_get_module_eeprom,
 810	.get_module_info = efx_mcdi_phy_get_module_info,
 811};
 812
 813u32 efx_mcdi_phy_get_caps(struct efx_nic *efx)
 814{
 815	struct efx_mcdi_phy_data *phy_data = efx->phy_data;
 816
 817	return phy_data->supported_cap;
 818}
 819
 820static unsigned int efx_mcdi_event_link_speed[] = {
 821	[MCDI_EVENT_LINKCHANGE_SPEED_100M] = 100,
 822	[MCDI_EVENT_LINKCHANGE_SPEED_1G] = 1000,
 823	[MCDI_EVENT_LINKCHANGE_SPEED_10G] = 10000,
 824	[MCDI_EVENT_LINKCHANGE_SPEED_40G] = 40000,
 825};
 826
 827void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev)
 828{
 829	u32 flags, fcntl, speed, lpa;
 830
 831	speed = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_SPEED);
 832	EFX_BUG_ON_PARANOID(speed >= ARRAY_SIZE(efx_mcdi_event_link_speed));
 833	speed = efx_mcdi_event_link_speed[speed];
 834
 835	flags = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_LINK_FLAGS);
 836	fcntl = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_FCNTL);
 837	lpa = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_LP_CAP);
 838
 839	/* efx->link_state is only modified by efx_mcdi_phy_get_link(),
 840	 * which is only run after flushing the event queues. Therefore, it
 841	 * is safe to modify the link state outside of the mac_lock here.
 842	 */
 843	efx_mcdi_phy_decode_link(efx, &efx->link_state, speed, flags, fcntl);
 844
 845	efx_mcdi_phy_check_fcntl(efx, lpa);
 846
 847	efx_link_status_changed(efx);
 848}
 849
 850int efx_mcdi_set_mac(struct efx_nic *efx)
 851{
 852	u32 fcntl;
 853	MCDI_DECLARE_BUF(cmdbytes, MC_CMD_SET_MAC_IN_LEN);
 854
 855	BUILD_BUG_ON(MC_CMD_SET_MAC_OUT_LEN != 0);
 856
 857	ether_addr_copy(MCDI_PTR(cmdbytes, SET_MAC_IN_ADDR),
 858			efx->net_dev->dev_addr);
 859
 860	MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_MTU,
 861			EFX_MAX_FRAME_LEN(efx->net_dev->mtu));
 862	MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_DRAIN, 0);
 863
 864	/* Set simple MAC filter for Siena */
 865	MCDI_POPULATE_DWORD_1(cmdbytes, SET_MAC_IN_REJECT,
 866			      SET_MAC_IN_REJECT_UNCST, efx->unicast_filter);
 867
 868	switch (efx->wanted_fc) {
 869	case EFX_FC_RX | EFX_FC_TX:
 870		fcntl = MC_CMD_FCNTL_BIDIR;
 871		break;
 872	case EFX_FC_RX:
 873		fcntl = MC_CMD_FCNTL_RESPOND;
 874		break;
 875	default:
 876		fcntl = MC_CMD_FCNTL_OFF;
 877		break;
 878	}
 879	if (efx->wanted_fc & EFX_FC_AUTO)
 880		fcntl = MC_CMD_FCNTL_AUTO;
 881	if (efx->fc_disable)
 882		fcntl = MC_CMD_FCNTL_OFF;
 883
 884	MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_FCNTL, fcntl);
 885
 886	return efx_mcdi_rpc(efx, MC_CMD_SET_MAC, cmdbytes, sizeof(cmdbytes),
 887			    NULL, 0, NULL);
 888}
 889
 890bool efx_mcdi_mac_check_fault(struct efx_nic *efx)
 891{
 892	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
 893	size_t outlength;
 894	int rc;
 895
 896	BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
 897
 898	rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
 899			  outbuf, sizeof(outbuf), &outlength);
 900	if (rc)
 901		return true;
 902
 903	return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0;
 904}
 905
 906enum efx_stats_action {
 907	EFX_STATS_ENABLE,
 908	EFX_STATS_DISABLE,
 909	EFX_STATS_PULL,
 910};
 911
 912static int efx_mcdi_mac_stats(struct efx_nic *efx,
 913			      enum efx_stats_action action, int clear)
 914{
 915	MCDI_DECLARE_BUF(inbuf, MC_CMD_MAC_STATS_IN_LEN);
 916	int rc;
 917	int change = action == EFX_STATS_PULL ? 0 : 1;
 918	int enable = action == EFX_STATS_ENABLE ? 1 : 0;
 919	int period = action == EFX_STATS_ENABLE ? 1000 : 0;
 920	dma_addr_t dma_addr = efx->stats_buffer.dma_addr;
 921	u32 dma_len = action != EFX_STATS_DISABLE ?
 922		MC_CMD_MAC_NSTATS * sizeof(u64) : 0;
 923
 924	BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0);
 925
 926	MCDI_SET_QWORD(inbuf, MAC_STATS_IN_DMA_ADDR, dma_addr);
 927	MCDI_POPULATE_DWORD_7(inbuf, MAC_STATS_IN_CMD,
 928			      MAC_STATS_IN_DMA, !!enable,
 929			      MAC_STATS_IN_CLEAR, clear,
 930			      MAC_STATS_IN_PERIODIC_CHANGE, change,
 931			      MAC_STATS_IN_PERIODIC_ENABLE, enable,
 932			      MAC_STATS_IN_PERIODIC_CLEAR, 0,
 933			      MAC_STATS_IN_PERIODIC_NOEVENT, 1,
 934			      MAC_STATS_IN_PERIOD_MS, period);
 935	MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len);
 936
 937	rc = efx_mcdi_rpc(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf),
 938			  NULL, 0, NULL);
 939	return rc;
 940}
 941
 942void efx_mcdi_mac_start_stats(struct efx_nic *efx)
 943{
 944	__le64 *dma_stats = efx->stats_buffer.addr;
 945
 946	dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID;
 947
 948	efx_mcdi_mac_stats(efx, EFX_STATS_ENABLE, 0);
 949}
 950
 951void efx_mcdi_mac_stop_stats(struct efx_nic *efx)
 952{
 953	efx_mcdi_mac_stats(efx, EFX_STATS_DISABLE, 0);
 954}
 955
 956#define EFX_MAC_STATS_WAIT_US 100
 957#define EFX_MAC_STATS_WAIT_ATTEMPTS 10
 958
 959void efx_mcdi_mac_pull_stats(struct efx_nic *efx)
 960{
 961	__le64 *dma_stats = efx->stats_buffer.addr;
 962	int attempts = EFX_MAC_STATS_WAIT_ATTEMPTS;
 963
 964	dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID;
 965	efx_mcdi_mac_stats(efx, EFX_STATS_PULL, 0);
 966
 967	while (dma_stats[MC_CMD_MAC_GENERATION_END] ==
 968				EFX_MC_STATS_GENERATION_INVALID &&
 969			attempts-- != 0)
 970		udelay(EFX_MAC_STATS_WAIT_US);
 971}
 972
 973int efx_mcdi_port_probe(struct efx_nic *efx)
 974{
 975	int rc;
 976
 977	/* Hook in PHY operations table */
 978	efx->phy_op = &efx_mcdi_phy_ops;
 979
 980	/* Set up MDIO structure for PHY */
 981	efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
 982	efx->mdio.mdio_read = efx_mcdi_mdio_read;
 983	efx->mdio.mdio_write = efx_mcdi_mdio_write;
 984
 985	/* Fill out MDIO structure, loopback modes, and initial link state */
 986	rc = efx->phy_op->probe(efx);
 987	if (rc != 0)
 988		return rc;
 989
 990	/* Allocate buffer for stats */
 991	rc = efx_nic_alloc_buffer(efx, &efx->stats_buffer,
 992				  MC_CMD_MAC_NSTATS * sizeof(u64), GFP_KERNEL);
 993	if (rc)
 994		return rc;
 995	netif_dbg(efx, probe, efx->net_dev,
 996		  "stats buffer at %llx (virt %p phys %llx)\n",
 997		  (u64)efx->stats_buffer.dma_addr,
 998		  efx->stats_buffer.addr,
 999		  (u64)virt_to_phys(efx->stats_buffer.addr));
1000
1001	efx_mcdi_mac_stats(efx, EFX_STATS_DISABLE, 1);
1002
1003	return 0;
1004}
1005
1006void efx_mcdi_port_remove(struct efx_nic *efx)
1007{
1008	efx->phy_op->remove(efx);
1009	efx_nic_free_buffer(efx, &efx->stats_buffer);
1010}
1011
1012/* Get physical port number (EF10 only; on Siena it is same as PF number) */
1013int efx_mcdi_port_get_number(struct efx_nic *efx)
1014{
1015	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN);
1016	int rc;
1017
1018	rc = efx_mcdi_rpc(efx, MC_CMD_GET_PORT_ASSIGNMENT, NULL, 0,
1019			  outbuf, sizeof(outbuf), NULL);
1020	if (rc)
1021		return rc;
1022
1023	return MCDI_DWORD(outbuf, GET_PORT_ASSIGNMENT_OUT_PORT);
1024}