Commit 68e7f45e authored by Ben Hutchings's avatar Ben Hutchings Committed by David S. Miller

sfc: Use generic MDIO functions and definitions

Make use of the newly-added generic MDIO clause 45 support and remove
redundant definitions.

Add an 'efx_' prefix to the remaining driver-specific MDIO functions
and remove arguments which are redundant with efx->mdio.prtad.
Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1b1c2e95
config SFC config SFC
tristate "Solarflare Solarstorm SFC4000 support" tristate "Solarflare Solarstorm SFC4000 support"
depends on PCI && INET depends on PCI && INET
select MII select MDIO
select CRC32 select CRC32
select I2C select I2C
select I2C_ALGOBIT select I2C_ALGOBIT
......
...@@ -1300,10 +1300,16 @@ static void efx_monitor(struct work_struct *data) ...@@ -1300,10 +1300,16 @@ static void efx_monitor(struct work_struct *data)
static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd) static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
{ {
struct efx_nic *efx = netdev_priv(net_dev); struct efx_nic *efx = netdev_priv(net_dev);
struct mii_ioctl_data *data = if_mii(ifr);
EFX_ASSERT_RESET_SERIALISED(efx); EFX_ASSERT_RESET_SERIALISED(efx);
return generic_mii_ioctl(&efx->mii, if_mii(ifr), cmd, NULL); /* Convert phy_id from older PRTAD/DEVAD format */
if ((cmd == SIOCGMIIREG || cmd == SIOCSMIIREG) &&
(data->phy_id & 0xfc00) == 0x0400)
data->phy_id ^= MDIO_PHY_ID_C45 | 0x0400;
return mdio_mii_ioctl(&efx->mdio, data, cmd);
} }
/************************************************************************** /**************************************************************************
...@@ -1945,7 +1951,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, ...@@ -1945,7 +1951,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
mutex_init(&efx->mac_lock); mutex_init(&efx->mac_lock);
efx->mac_op = &efx_dummy_mac_operations; efx->mac_op = &efx_dummy_mac_operations;
efx->phy_op = &efx_dummy_phy_operations; efx->phy_op = &efx_dummy_phy_operations;
efx->mii.dev = net_dev; efx->mdio.dev = net_dev;
INIT_WORK(&efx->phy_work, efx_phy_work); INIT_WORK(&efx->phy_work, efx_phy_work);
INIT_WORK(&efx->mac_work, efx_mac_work); INIT_WORK(&efx->mac_work, efx_mac_work);
atomic_set(&efx->netif_stop_count, 1); atomic_set(&efx->netif_stop_count, 1);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/mdio.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include "net_driver.h" #include "net_driver.h"
#include "workarounds.h" #include "workarounds.h"
...@@ -345,8 +346,8 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, ...@@ -345,8 +346,8 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
unsigned int n = 0, i; unsigned int n = 0, i;
enum efx_loopback_mode mode; enum efx_loopback_mode mode;
efx_fill_test(n++, strings, data, &tests->mii, efx_fill_test(n++, strings, data, &tests->mdio,
"core", 0, "mii", NULL); "core", 0, "mdio", NULL);
efx_fill_test(n++, strings, data, &tests->nvram, efx_fill_test(n++, strings, data, &tests->nvram,
"core", 0, "nvram", NULL); "core", 0, "nvram", NULL);
efx_fill_test(n++, strings, data, &tests->interrupt, efx_fill_test(n++, strings, data, &tests->interrupt,
...@@ -529,14 +530,7 @@ static int efx_ethtool_nway_reset(struct net_device *net_dev) ...@@ -529,14 +530,7 @@ static int efx_ethtool_nway_reset(struct net_device *net_dev)
{ {
struct efx_nic *efx = netdev_priv(net_dev); struct efx_nic *efx = netdev_priv(net_dev);
if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) { return mdio45_nway_restart(&efx->mdio);
mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_AN,
MDIO_MMDREG_CTRL1,
__ffs(BMCR_ANRESTART), true);
return 0;
}
return -EOPNOTSUPP;
} }
static u32 efx_ethtool_get_link(struct net_device *net_dev) static u32 efx_ethtool_get_link(struct net_device *net_dev)
...@@ -689,7 +683,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, ...@@ -689,7 +683,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
return -EINVAL; return -EINVAL;
} }
if (!(efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) && if (!(efx->phy_op->mmds & MDIO_DEVS_AN) &&
(wanted_fc & EFX_FC_AUTO)) { (wanted_fc & EFX_FC_AUTO)) {
EFX_LOG(efx, "PHY does not support flow control " EFX_LOG(efx, "PHY does not support flow control "
"autonegotiation\n"); "autonegotiation\n");
...@@ -717,7 +711,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, ...@@ -717,7 +711,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
mutex_lock(&efx->mac_lock); mutex_lock(&efx->mac_lock);
efx->wanted_fc = wanted_fc; efx->wanted_fc = wanted_fc;
mdio_clause45_set_pause(efx); efx_mdio_set_pause(efx);
__efx_reconfigure_port(efx); __efx_reconfigure_port(efx);
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
......
...@@ -2063,26 +2063,6 @@ int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset) ...@@ -2063,26 +2063,6 @@ int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset)
************************************************************************** **************************************************************************
*/ */
/* Use the top bit of the MII PHY id to indicate the PHY type
* (1G/10G), with the remaining bits as the actual PHY id.
*
* This allows us to avoid leaking information from the mii_if_info
* structure into other data structures.
*/
#define FALCON_PHY_ID_ID_WIDTH EFX_WIDTH(MD_PRT_DEV_ADR)
#define FALCON_PHY_ID_ID_MASK ((1 << FALCON_PHY_ID_ID_WIDTH) - 1)
#define FALCON_PHY_ID_WIDTH (FALCON_PHY_ID_ID_WIDTH + 1)
#define FALCON_PHY_ID_MASK ((1 << FALCON_PHY_ID_WIDTH) - 1)
#define FALCON_PHY_ID_10G (1 << (FALCON_PHY_ID_WIDTH - 1))
/* Packing the clause 45 port and device fields into a single value */
#define MD_PRT_ADR_COMP_LBN (MD_PRT_ADR_LBN - MD_DEV_ADR_LBN)
#define MD_PRT_ADR_COMP_WIDTH MD_PRT_ADR_WIDTH
#define MD_DEV_ADR_COMP_LBN 0
#define MD_DEV_ADR_COMP_WIDTH MD_DEV_ADR_WIDTH
/* Wait for GMII access to complete */ /* Wait for GMII access to complete */
static int falcon_gmii_wait(struct efx_nic *efx) static int falcon_gmii_wait(struct efx_nic *efx)
{ {
...@@ -2108,49 +2088,29 @@ static int falcon_gmii_wait(struct efx_nic *efx) ...@@ -2108,49 +2088,29 @@ static int falcon_gmii_wait(struct efx_nic *efx)
return -ETIMEDOUT; return -ETIMEDOUT;
} }
/* Writes a GMII register of a PHY connected to Falcon using MDIO. */ /* Write an MDIO register of a PHY connected to Falcon. */
static void falcon_mdio_write(struct net_device *net_dev, int phy_id, static int falcon_mdio_write(struct net_device *net_dev,
int addr, int value) int prtad, int devad, u16 addr, u16 value)
{ {
struct efx_nic *efx = netdev_priv(net_dev); struct efx_nic *efx = netdev_priv(net_dev);
unsigned int phy_id2 = phy_id & FALCON_PHY_ID_ID_MASK;
efx_oword_t reg; efx_oword_t reg;
int rc;
/* The 'generic' prt/dev packing in mdio_10g.h is conveniently EFX_REGDUMP(efx, "writing MDIO %d register %d.%d with 0x%04x\n",
* chosen so that the only current user, Falcon, can take the prtad, devad, addr, value);
* packed value and use them directly.
* Fail to build if this assumption is broken.
*/
BUILD_BUG_ON(FALCON_PHY_ID_10G != MDIO45_XPRT_ID_IS10G);
BUILD_BUG_ON(FALCON_PHY_ID_ID_WIDTH != MDIO45_PRT_DEV_WIDTH);
BUILD_BUG_ON(MD_PRT_ADR_COMP_LBN != MDIO45_PRT_ID_COMP_LBN);
BUILD_BUG_ON(MD_DEV_ADR_COMP_LBN != MDIO45_DEV_ID_COMP_LBN);
if (phy_id2 == PHY_ADDR_INVALID)
return;
/* See falcon_mdio_read for an explanation. */
if (!(phy_id & FALCON_PHY_ID_10G)) {
int mmd = ffs(efx->phy_op->mmds) - 1;
EFX_TRACE(efx, "Fixing erroneous clause22 write\n");
phy_id2 = mdio_clause45_pack(phy_id2, mmd)
& FALCON_PHY_ID_ID_MASK;
}
EFX_REGDUMP(efx, "writing GMII %d register %02x with %04x\n", phy_id,
addr, value);
spin_lock_bh(&efx->phy_lock); spin_lock_bh(&efx->phy_lock);
/* Check MII not currently being accessed */ /* Check MDIO not currently being accessed */
if (falcon_gmii_wait(efx) != 0) rc = falcon_gmii_wait(efx);
if (rc)
goto out; goto out;
/* Write the address/ID register */ /* Write the address/ID register */
EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr); EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr);
falcon_write(efx, &reg, MD_PHY_ADR_REG_KER); falcon_write(efx, &reg, MD_PHY_ADR_REG_KER);
EFX_POPULATE_OWORD_1(reg, MD_PRT_DEV_ADR, phy_id2); EFX_POPULATE_OWORD_2(reg, MD_PRT_ADR, prtad, MD_DEV_ADR, devad);
falcon_write(efx, &reg, MD_ID_REG_KER); falcon_write(efx, &reg, MD_ID_REG_KER);
/* Write data */ /* Write data */
...@@ -2163,7 +2123,8 @@ static void falcon_mdio_write(struct net_device *net_dev, int phy_id, ...@@ -2163,7 +2123,8 @@ static void falcon_mdio_write(struct net_device *net_dev, int phy_id,
falcon_write(efx, &reg, MD_CS_REG_KER); falcon_write(efx, &reg, MD_CS_REG_KER);
/* Wait for data to be written */ /* Wait for data to be written */
if (falcon_gmii_wait(efx) != 0) { rc = falcon_gmii_wait(efx);
if (rc) {
/* Abort the write operation */ /* Abort the write operation */
EFX_POPULATE_OWORD_2(reg, EFX_POPULATE_OWORD_2(reg,
MD_WRC, 0, MD_WRC, 0,
...@@ -2174,45 +2135,28 @@ static void falcon_mdio_write(struct net_device *net_dev, int phy_id, ...@@ -2174,45 +2135,28 @@ static void falcon_mdio_write(struct net_device *net_dev, int phy_id,
out: out:
spin_unlock_bh(&efx->phy_lock); spin_unlock_bh(&efx->phy_lock);
return rc;
} }
/* Reads a GMII register from a PHY connected to Falcon. If no value /* Read an MDIO register of a PHY connected to Falcon. */
* could be read, -1 will be returned. */ static int falcon_mdio_read(struct net_device *net_dev,
static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr) int prtad, int devad, u16 addr)
{ {
struct efx_nic *efx = netdev_priv(net_dev); struct efx_nic *efx = netdev_priv(net_dev);
unsigned int phy_addr = phy_id & FALCON_PHY_ID_ID_MASK;
efx_oword_t reg; efx_oword_t reg;
int value = -1; int rc;
if (phy_addr == PHY_ADDR_INVALID)
return -1;
/* Our PHY code knows whether it needs to talk clause 22(1G) or 45(10G)
* but the generic Linux code does not make any distinction or have
* any state for this.
* We spot the case where someone tried to talk 22 to a 45 PHY and
* redirect the request to the lowest numbered MMD as a clause45
* request. This is enough to allow simple queries like id and link
* state to succeed. TODO: We may need to do more in future.
*/
if (!(phy_id & FALCON_PHY_ID_10G)) {
int mmd = ffs(efx->phy_op->mmds) - 1;
EFX_TRACE(efx, "Fixing erroneous clause22 read\n");
phy_addr = mdio_clause45_pack(phy_addr, mmd)
& FALCON_PHY_ID_ID_MASK;
}
spin_lock_bh(&efx->phy_lock); spin_lock_bh(&efx->phy_lock);
/* Check MII not currently being accessed */ /* Check MDIO not currently being accessed */
if (falcon_gmii_wait(efx) != 0) rc = falcon_gmii_wait(efx);
if (rc)
goto out; goto out;
EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr); EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr);
falcon_write(efx, &reg, MD_PHY_ADR_REG_KER); falcon_write(efx, &reg, MD_PHY_ADR_REG_KER);
EFX_POPULATE_OWORD_1(reg, MD_PRT_DEV_ADR, phy_addr); EFX_POPULATE_OWORD_2(reg, MD_PRT_ADR, prtad, MD_DEV_ADR, devad);
falcon_write(efx, &reg, MD_ID_REG_KER); falcon_write(efx, &reg, MD_ID_REG_KER);
/* Request data to be read */ /* Request data to be read */
...@@ -2220,12 +2164,12 @@ static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr) ...@@ -2220,12 +2164,12 @@ static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr)
falcon_write(efx, &reg, MD_CS_REG_KER); falcon_write(efx, &reg, MD_CS_REG_KER);
/* Wait for data to become available */ /* Wait for data to become available */
value = falcon_gmii_wait(efx); rc = falcon_gmii_wait(efx);
if (value == 0) { if (rc == 0) {
falcon_read(efx, &reg, MD_RXD_REG_KER); falcon_read(efx, &reg, MD_RXD_REG_KER);
value = EFX_OWORD_FIELD(reg, MD_RXD); rc = EFX_OWORD_FIELD(reg, MD_RXD);
EFX_REGDUMP(efx, "read from GMII %d register %02x, got %04x\n", EFX_REGDUMP(efx, "read from MDIO %d register %d.%d, got %04x\n",
phy_id, addr, value); prtad, devad, addr, rc);
} else { } else {
/* Abort the read operation */ /* Abort the read operation */
EFX_POPULATE_OWORD_2(reg, EFX_POPULATE_OWORD_2(reg,
...@@ -2233,22 +2177,13 @@ static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr) ...@@ -2233,22 +2177,13 @@ static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr)
MD_GC, 1); MD_GC, 1);
falcon_write(efx, &reg, MD_CS_REG_KER); falcon_write(efx, &reg, MD_CS_REG_KER);
EFX_LOG(efx, "read from GMII 0x%x register %02x, got " EFX_LOG(efx, "read from MDIO %d register %d.%d, got error %d\n",
"error %d\n", phy_id, addr, value); prtad, devad, addr, rc);
} }
out: out:
spin_unlock_bh(&efx->phy_lock); spin_unlock_bh(&efx->phy_lock);
return rc;
return value;
}
static void falcon_init_mdio(struct mii_if_info *gmii)
{
gmii->mdio_read = falcon_mdio_read;
gmii->mdio_write = falcon_mdio_write;
gmii->phy_id_mask = FALCON_PHY_ID_MASK;
gmii->reg_num_mask = ((1 << EFX_WIDTH(MD_PHY_ADR)) - 1);
} }
static int falcon_probe_phy(struct efx_nic *efx) static int falcon_probe_phy(struct efx_nic *efx)
...@@ -2342,9 +2277,11 @@ int falcon_probe_port(struct efx_nic *efx) ...@@ -2342,9 +2277,11 @@ int falcon_probe_port(struct efx_nic *efx)
if (rc) if (rc)
return rc; return rc;
/* Set up GMII structure for PHY */ /* Set up MDIO structure for PHY */
efx->mii.supports_gmii = true; efx->mdio.mmds = efx->phy_op->mmds;
falcon_init_mdio(&efx->mii); efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
efx->mdio.mdio_read = falcon_mdio_read;
efx->mdio.mdio_write = falcon_mdio_write;
/* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */ /* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */
if (falcon_rev(efx) >= FALCON_REV_B0) if (falcon_rev(efx) >= FALCON_REV_B0)
...@@ -2761,7 +2698,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) ...@@ -2761,7 +2698,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx)
if (rc == -EINVAL) { if (rc == -EINVAL) {
EFX_ERR(efx, "NVRAM is invalid therefore using defaults\n"); EFX_ERR(efx, "NVRAM is invalid therefore using defaults\n");
efx->phy_type = PHY_TYPE_NONE; efx->phy_type = PHY_TYPE_NONE;
efx->mii.phy_id = PHY_ADDR_INVALID; efx->mdio.prtad = MDIO_PRTAD_NONE;
board_rev = 0; board_rev = 0;
rc = 0; rc = 0;
} else if (rc) { } else if (rc) {
...@@ -2771,7 +2708,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) ...@@ -2771,7 +2708,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx)
struct falcon_nvconfig_board_v3 *v3 = &nvconfig->board_v3; struct falcon_nvconfig_board_v3 *v3 = &nvconfig->board_v3;
efx->phy_type = v2->port0_phy_type; efx->phy_type = v2->port0_phy_type;
efx->mii.phy_id = v2->port0_phy_addr; efx->mdio.prtad = v2->port0_phy_addr;
board_rev = le16_to_cpu(v2->board_revision); board_rev = le16_to_cpu(v2->board_revision);
if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) { if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) {
...@@ -2793,7 +2730,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) ...@@ -2793,7 +2730,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx)
/* Read the MAC addresses */ /* Read the MAC addresses */
memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN); memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN);
EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mii.phy_id); EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mdio.prtad);
efx_set_board_info(efx, board_rev); efx_set_board_info(efx, board_rev);
......
...@@ -456,9 +456,6 @@ ...@@ -456,9 +456,6 @@
#define MD_PRT_ADR_WIDTH 5 #define MD_PRT_ADR_WIDTH 5
#define MD_DEV_ADR_LBN 6 #define MD_DEV_ADR_LBN 6
#define MD_DEV_ADR_WIDTH 5 #define MD_DEV_ADR_WIDTH 5
/* Used for writing both at once */
#define MD_PRT_DEV_ADR_LBN 6
#define MD_PRT_DEV_ADR_WIDTH 10
/* PHY management status & mask register (DWORD read only) */ /* PHY management status & mask register (DWORD read only) */
#define MD_STAT_REG_KER 0xc50 #define MD_STAT_REG_KER 0xc50
......
...@@ -133,7 +133,7 @@ bool falcon_xaui_link_ok(struct efx_nic *efx) ...@@ -133,7 +133,7 @@ bool falcon_xaui_link_ok(struct efx_nic *efx)
/* If the link is up, then check the phy side of the xaui link */ /* If the link is up, then check the phy side of the xaui link */
if (efx->link_up && link_ok) if (efx->link_up && link_ok)
if (efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS)) if (efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS))
link_ok = mdio_clause45_phyxgxs_lane_sync(efx); link_ok = efx_mdio_phyxgxs_lane_sync(efx);
return link_ok; return link_ok;
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/mii.h> #include <linux/mdio.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/device.h> #include <linux/device.h>
...@@ -458,8 +458,6 @@ enum phy_type { ...@@ -458,8 +458,6 @@ enum phy_type {
PHY_TYPE_MAX /* Insert any new items before this */ PHY_TYPE_MAX /* Insert any new items before this */
}; };
#define PHY_ADDR_INVALID 0xff
#define EFX_IS10G(efx) ((efx)->link_speed == 10000) #define EFX_IS10G(efx) ((efx)->link_speed == 10000)
enum nic_state { enum nic_state {
...@@ -758,7 +756,7 @@ union efx_multicast_hash { ...@@ -758,7 +756,7 @@ union efx_multicast_hash {
* @phy_lock: PHY access lock * @phy_lock: PHY access lock
* @phy_op: PHY interface * @phy_op: PHY interface
* @phy_data: PHY private data (including PHY-specific stats) * @phy_data: PHY private data (including PHY-specific stats)
* @mii: PHY interface * @mdio: PHY MDIO interface
* @phy_mode: PHY operating mode. Serialised by @mac_lock. * @phy_mode: PHY operating mode. Serialised by @mac_lock.
* @mac_up: MAC link state * @mac_up: MAC link state
* @link_up: Link status * @link_up: Link status
...@@ -845,7 +843,7 @@ struct efx_nic { ...@@ -845,7 +843,7 @@ struct efx_nic {
struct work_struct phy_work; struct work_struct phy_work;
struct efx_phy_operations *phy_op; struct efx_phy_operations *phy_op;
void *phy_data; void *phy_data;
struct mii_if_info mii; struct mdio_if_info mdio;
enum efx_phy_mode phy_mode; enum efx_phy_mode phy_mode;
bool mac_up; bool mac_up;
......
...@@ -80,39 +80,38 @@ struct efx_loopback_state { ...@@ -80,39 +80,38 @@ struct efx_loopback_state {
* *
**************************************************************************/ **************************************************************************/
static int efx_test_mii(struct efx_nic *efx, struct efx_self_tests *tests) static int efx_test_mdio(struct efx_nic *efx, struct efx_self_tests *tests)
{ {
int rc = 0; int rc = 0;
int devad = __ffs(efx->mdio.mmds);
u16 physid1, physid2; u16 physid1, physid2;
struct mii_if_info *mii = &efx->mii;
struct net_device *net_dev = efx->net_dev;
if (efx->phy_type == PHY_TYPE_NONE) if (efx->phy_type == PHY_TYPE_NONE)
return 0; return 0;
mutex_lock(&efx->mac_lock); mutex_lock(&efx->mac_lock);
tests->mii = -1; tests->mdio = -1;
physid1 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID1); physid1 = efx_mdio_read(efx, devad, MDIO_DEVID1);
physid2 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID2); physid2 = efx_mdio_read(efx, devad, MDIO_DEVID2);
if ((physid1 == 0x0000) || (physid1 == 0xffff) || if ((physid1 == 0x0000) || (physid1 == 0xffff) ||
(physid2 == 0x0000) || (physid2 == 0xffff)) { (physid2 == 0x0000) || (physid2 == 0xffff)) {
EFX_ERR(efx, "no MII PHY present with ID %d\n", EFX_ERR(efx, "no MDIO PHY present with ID %d\n",
mii->phy_id); efx->mdio.prtad);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
if (EFX_IS10G(efx)) { if (EFX_IS10G(efx)) {
rc = mdio_clause45_check_mmds(efx, efx->phy_op->mmds, 0); rc = efx_mdio_check_mmds(efx, efx->phy_op->mmds, 0);
if (rc) if (rc)
goto out; goto out;
} }
out: out:
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
tests->mii = rc ? -1 : 1; tests->mdio = rc ? -1 : 1;
return rc; return rc;
} }
...@@ -673,7 +672,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, ...@@ -673,7 +672,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
/* Online (i.e. non-disruptive) testing /* Online (i.e. non-disruptive) testing
* This checks interrupt generation, event delivery and PHY presence. */ * This checks interrupt generation, event delivery and PHY presence. */
rc = efx_test_mii(efx, tests); rc = efx_test_mdio(efx, tests);
if (rc && !rc_test) if (rc && !rc_test)
rc_test = rc; rc_test = rc;
......
...@@ -32,7 +32,7 @@ struct efx_loopback_self_tests { ...@@ -32,7 +32,7 @@ struct efx_loopback_self_tests {
*/ */
struct efx_self_tests { struct efx_self_tests {
/* online tests */ /* online tests */
int mii; int mdio;
int nvram; int nvram;
int interrupt; int interrupt;
int eventq_dma[EFX_MAX_CHANNELS]; int eventq_dma[EFX_MAX_CHANNELS];
......
This diff is collapsed.
...@@ -34,29 +34,24 @@ ...@@ -34,29 +34,24 @@
/* Enable LASI interrupts for PHY */ /* Enable LASI interrupts for PHY */
static inline void xenpack_enable_lasi_irqs(struct efx_nic *efx) static inline void xenpack_enable_lasi_irqs(struct efx_nic *efx)
{ {
int reg;
int phy_id = efx->mii.phy_id;
/* Read to clear LASI status register */ /* Read to clear LASI status register */
reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_XP_LASI_STAT);
MDIO_XP_LASI_STAT);
mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, efx_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_XP_LASI_CTRL,
MDIO_XP_LASI_CTRL, XP_LASI_LS_ALARM); XP_LASI_LS_ALARM);
} }
/* Read the LASI interrupt status to clear the interrupt. */ /* Read the LASI interrupt status to clear the interrupt. */
static inline int xenpack_clear_lasi_irqs(struct efx_nic *efx) static inline int xenpack_clear_lasi_irqs(struct efx_nic *efx)
{ {
/* Read to clear link status alarm */ /* Read to clear link status alarm */
return mdio_clause45_read(efx, efx->mii.phy_id, return efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_XP_LASI_STAT);
MDIO_MMD_PMAPMD, MDIO_XP_LASI_STAT);
} }
/* Turn off LASI interrupts */ /* Turn off LASI interrupts */
static inline void xenpack_disable_lasi_irqs(struct efx_nic *efx) static inline void xenpack_disable_lasi_irqs(struct efx_nic *efx)
{ {
mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, efx_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_XP_LASI_CTRL, 0);
MDIO_XP_LASI_CTRL, 0);
} }
#endif /* EFX_XENPACK_H */ #endif /* EFX_XENPACK_H */
...@@ -19,9 +19,9 @@ ...@@ -19,9 +19,9 @@
#include "phy.h" #include "phy.h"
#include "falcon.h" #include "falcon.h"
#define XFP_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PCS | \ #define XFP_REQUIRED_DEVS (MDIO_DEVS_PCS | \
MDIO_MMDREG_DEVS_PMAPMD | \ MDIO_DEVS_PMAPMD | \
MDIO_MMDREG_DEVS_PHYXS) MDIO_DEVS_PHYXS)
#define XFP_LOOPBACKS ((1 << LOOPBACK_PCS) | \ #define XFP_LOOPBACKS ((1 << LOOPBACK_PCS) | \
(1 << LOOPBACK_PMAPMD) | \ (1 << LOOPBACK_PMAPMD) | \
...@@ -49,8 +49,7 @@ ...@@ -49,8 +49,7 @@
void xfp_set_led(struct efx_nic *p, int led, int mode) void xfp_set_led(struct efx_nic *p, int led, int mode)
{ {
int addr = MDIO_QUAKE_LED0_REG + led; int addr = MDIO_QUAKE_LED0_REG + led;
mdio_clause45_write(p, p->mii.phy_id, MDIO_MMD_PMAPMD, addr, efx_mdio_write(p, MDIO_MMD_PMAPMD, addr, mode);
mode);
} }
struct xfp_phy_data { struct xfp_phy_data {
...@@ -63,14 +62,12 @@ struct xfp_phy_data { ...@@ -63,14 +62,12 @@ struct xfp_phy_data {
static int qt2025c_wait_reset(struct efx_nic *efx) static int qt2025c_wait_reset(struct efx_nic *efx)
{ {
unsigned long timeout = jiffies + 10 * HZ; unsigned long timeout = jiffies + 10 * HZ;
int phy_id = efx->mii.phy_id;
int reg, old_counter = 0; int reg, old_counter = 0;
/* Wait for firmware heartbeat to start */ /* Wait for firmware heartbeat to start */
for (;;) { for (;;) {
int counter; int counter;
reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS, reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_FW_HEARTBEAT_REG);
PCS_FW_HEARTBEAT_REG);
if (reg < 0) if (reg < 0)
return reg; return reg;
counter = ((reg >> PCS_FW_HEARTB_LBN) & counter = ((reg >> PCS_FW_HEARTB_LBN) &
...@@ -86,8 +83,7 @@ static int qt2025c_wait_reset(struct efx_nic *efx) ...@@ -86,8 +83,7 @@ static int qt2025c_wait_reset(struct efx_nic *efx)
/* Wait for firmware status to look good */ /* Wait for firmware status to look good */
for (;;) { for (;;) {
reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS, reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_UC8051_STATUS_REG);
PCS_UC8051_STATUS_REG);
if (reg < 0) if (reg < 0)
return reg; return reg;
if ((reg & if ((reg &
...@@ -109,9 +105,9 @@ static int xfp_reset_phy(struct efx_nic *efx) ...@@ -109,9 +105,9 @@ static int xfp_reset_phy(struct efx_nic *efx)
{ {
int rc; int rc;
rc = mdio_clause45_reset_mmd(efx, MDIO_MMD_PHYXS, rc = efx_mdio_reset_mmd(efx, MDIO_MMD_PHYXS,
XFP_MAX_RESET_TIME / XFP_RESET_WAIT, XFP_MAX_RESET_TIME / XFP_RESET_WAIT,
XFP_RESET_WAIT); XFP_RESET_WAIT);
if (rc < 0) if (rc < 0)
goto fail; goto fail;
...@@ -126,8 +122,7 @@ static int xfp_reset_phy(struct efx_nic *efx) ...@@ -126,8 +122,7 @@ static int xfp_reset_phy(struct efx_nic *efx)
/* Check that all the MMDs we expect are present and responding. We /* Check that all the MMDs we expect are present and responding. We
* expect faults on some if the link is down, but not on the PHY XS */ * expect faults on some if the link is down, but not on the PHY XS */
rc = mdio_clause45_check_mmds(efx, XFP_REQUIRED_DEVS, rc = efx_mdio_check_mmds(efx, XFP_REQUIRED_DEVS, MDIO_DEVS_PHYXS);
MDIO_MMDREG_DEVS_PHYXS);
if (rc < 0) if (rc < 0)
goto fail; goto fail;
...@@ -143,7 +138,7 @@ static int xfp_reset_phy(struct efx_nic *efx) ...@@ -143,7 +138,7 @@ static int xfp_reset_phy(struct efx_nic *efx)
static int xfp_phy_init(struct efx_nic *efx) static int xfp_phy_init(struct efx_nic *efx)
{ {
struct xfp_phy_data *phy_data; struct xfp_phy_data *phy_data;
u32 devid = mdio_clause45_read_id(efx, MDIO_MMD_PHYXS); u32 devid = efx_mdio_read_id(efx, MDIO_MMD_PHYXS);
int rc; int rc;
phy_data = kzalloc(sizeof(struct xfp_phy_data), GFP_KERNEL); phy_data = kzalloc(sizeof(struct xfp_phy_data), GFP_KERNEL);
...@@ -152,8 +147,8 @@ static int xfp_phy_init(struct efx_nic *efx) ...@@ -152,8 +147,8 @@ static int xfp_phy_init(struct efx_nic *efx)
efx->phy_data = phy_data; efx->phy_data = phy_data;
EFX_INFO(efx, "PHY ID reg %x (OUI %06x model %02x revision %x)\n", EFX_INFO(efx, "PHY ID reg %x (OUI %06x model %02x revision %x)\n",
devid, mdio_id_oui(devid), mdio_id_model(devid), devid, efx_mdio_id_oui(devid), efx_mdio_id_model(devid),
mdio_id_rev(devid)); efx_mdio_id_rev(devid));
phy_data->phy_mode = efx->phy_mode; phy_data->phy_mode = efx->phy_mode;
...@@ -179,7 +174,7 @@ static void xfp_phy_clear_interrupt(struct efx_nic *efx) ...@@ -179,7 +174,7 @@ static void xfp_phy_clear_interrupt(struct efx_nic *efx)
static int xfp_link_ok(struct efx_nic *efx) static int xfp_link_ok(struct efx_nic *efx)
{ {
return mdio_clause45_links_ok(efx, XFP_REQUIRED_DEVS); return efx_mdio_links_ok(efx, XFP_REQUIRED_DEVS);
} }
static void xfp_phy_poll(struct efx_nic *efx) static void xfp_phy_poll(struct efx_nic *efx)
...@@ -200,9 +195,9 @@ static void xfp_phy_reconfigure(struct efx_nic *efx) ...@@ -200,9 +195,9 @@ static void xfp_phy_reconfigure(struct efx_nic *efx)
* or optical transceivers, varying somewhat between * or optical transceivers, varying somewhat between
* firmware versions. Only 'static mode' appears to * firmware versions. Only 'static mode' appears to
* cover everything. */ * cover everything. */
mdio_clause45_set_flag( mdio_set_flag(
efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, &efx->mdio, efx->mdio.prtad, MDIO_MMD_PMAPMD,
PMA_PMD_FTX_CTRL2_REG, PMA_PMD_FTX_STATIC_LBN, PMA_PMD_FTX_CTRL2_REG, 1 << PMA_PMD_FTX_STATIC_LBN,
efx->phy_mode & PHY_MODE_TX_DISABLED || efx->phy_mode & PHY_MODE_TX_DISABLED ||
efx->phy_mode & PHY_MODE_LOW_POWER || efx->phy_mode & PHY_MODE_LOW_POWER ||
efx->loopback_mode == LOOPBACK_PCS || efx->loopback_mode == LOOPBACK_PCS ||
...@@ -213,10 +208,10 @@ static void xfp_phy_reconfigure(struct efx_nic *efx) ...@@ -213,10 +208,10 @@ static void xfp_phy_reconfigure(struct efx_nic *efx)
(phy_data->phy_mode & PHY_MODE_TX_DISABLED)) (phy_data->phy_mode & PHY_MODE_TX_DISABLED))
xfp_reset_phy(efx); xfp_reset_phy(efx);
mdio_clause45_transmit_disable(efx); efx_mdio_transmit_disable(efx);
} }
mdio_clause45_phy_reconfigure(efx); efx_mdio_phy_reconfigure(efx);
phy_data->phy_mode = efx->phy_mode; phy_data->phy_mode = efx->phy_mode;
efx->link_up = xfp_link_ok(efx); efx->link_up = xfp_link_ok(efx);
...@@ -225,6 +220,10 @@ static void xfp_phy_reconfigure(struct efx_nic *efx) ...@@ -225,6 +220,10 @@ static void xfp_phy_reconfigure(struct efx_nic *efx)
efx->link_fc = efx->wanted_fc; efx->link_fc = efx->wanted_fc;
} }
static void xfp_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
mdio45_ethtool_gset(&efx->mdio, ecmd);
}
static void xfp_phy_fini(struct efx_nic *efx) static void xfp_phy_fini(struct efx_nic *efx)
{ {
...@@ -243,8 +242,8 @@ struct efx_phy_operations falcon_xfp_phy_ops = { ...@@ -243,8 +242,8 @@ struct efx_phy_operations falcon_xfp_phy_ops = {
.poll = xfp_phy_poll, .poll = xfp_phy_poll,
.fini = xfp_phy_fini, .fini = xfp_phy_fini,
.clear_interrupt = xfp_phy_clear_interrupt, .clear_interrupt = xfp_phy_clear_interrupt,
.get_settings = mdio_clause45_get_settings, .get_settings = xfp_phy_get_settings,
.set_settings = mdio_clause45_set_settings, .set_settings = efx_mdio_set_settings,
.mmds = XFP_REQUIRED_DEVS, .mmds = XFP_REQUIRED_DEVS,
.loopbacks = XFP_LOOPBACKS, .loopbacks = XFP_LOOPBACKS,
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment