Linux Audio

Check our new training course

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