aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/mdio_10g.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sfc/mdio_10g.c')
-rw-r--r--drivers/net/sfc/mdio_10g.c51
1 files changed, 32 insertions, 19 deletions
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c
index 231e580..1574e52 100644
--- a/drivers/net/sfc/mdio_10g.c
+++ b/drivers/net/sfc/mdio_10g.c
@@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2006-2008 Solarflare Communications Inc.
+ * Copyright 2006-2009 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@@ -15,6 +15,7 @@
#include "net_driver.h"
#include "mdio_10g.h"
#include "workarounds.h"
+#include "nic.h"
unsigned efx_mdio_id_oui(u32 id)
{
@@ -173,7 +174,7 @@ bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
* of mmd's */
if (LOOPBACK_INTERNAL(efx))
return true;
- else if (efx->loopback_mode == LOOPBACK_NETWORK)
+ else if (LOOPBACK_MASK(efx) & LOOPBACKS_WS)
return false;
else if (efx_phy_mode_disabled(efx->phy_mode))
return false;
@@ -210,7 +211,7 @@ void efx_mdio_phy_reconfigure(struct efx_nic *efx)
efx->loopback_mode == LOOPBACK_PCS);
efx_mdio_set_flag(efx, MDIO_MMD_PHYXS,
MDIO_CTRL1, MDIO_PHYXS_CTRL1_LOOPBACK,
- efx->loopback_mode == LOOPBACK_NETWORK);
+ efx->loopback_mode == LOOPBACK_PHYXS_WS);
}
static void efx_mdio_set_mmd_lpower(struct efx_nic *efx,
@@ -248,8 +249,6 @@ void efx_mdio_set_mmds_lpower(struct efx_nic *efx,
int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
struct ethtool_cmd prev;
- bool xnp;
- int reg;
efx->phy_op->get_settings(efx, &prev);
@@ -269,44 +268,58 @@ int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
(ecmd->advertising | SUPPORTED_Autoneg) & ~prev.supported)
return -EINVAL;
- xnp = (ecmd->advertising & ADVERTISED_10000baseT_Full
- || EFX_WORKAROUND_13204(efx));
+ efx_link_set_advertising(efx, ecmd->advertising | ADVERTISED_Autoneg);
+ efx_mdio_an_reconfigure(efx);
+ return 0;
+}
+
+/**
+ * efx_mdio_an_reconfigure - Push advertising flags and restart autonegotiation
+ * @efx: Efx NIC
+ */
+void efx_mdio_an_reconfigure(struct efx_nic *efx)
+{
+ bool xnp = (efx->link_advertising & ADVERTISED_10000baseT_Full
+ || EFX_WORKAROUND_13204(efx));
+ int reg;
+
+ WARN_ON(!(efx->mdio.mmds & MDIO_DEVS_AN));
/* Set up the base page */
reg = ADVERTISE_CSMA;
- if (ecmd->advertising & ADVERTISED_10baseT_Half)
+ if (efx->link_advertising & ADVERTISED_10baseT_Half)
reg |= ADVERTISE_10HALF;
- if (ecmd->advertising & ADVERTISED_10baseT_Full)
+ if (efx->link_advertising & ADVERTISED_10baseT_Full)
reg |= ADVERTISE_10FULL;
- if (ecmd->advertising & ADVERTISED_100baseT_Half)
+ if (efx->link_advertising & ADVERTISED_100baseT_Half)
reg |= ADVERTISE_100HALF;
- if (ecmd->advertising & ADVERTISED_100baseT_Full)
+ if (efx->link_advertising & ADVERTISED_100baseT_Full)
reg |= ADVERTISE_100FULL;
if (xnp)
reg |= ADVERTISE_RESV;
- else if (ecmd->advertising & (ADVERTISED_1000baseT_Half |
- ADVERTISED_1000baseT_Full))
+ else if (efx->link_advertising & (ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full))
reg |= ADVERTISE_NPAGE;
- reg |= mii_advertise_flowctrl(efx->wanted_fc);
+ if (efx->link_advertising & ADVERTISED_Pause)
+ reg |= ADVERTISE_PAUSE_CAP;
+ if (efx->link_advertising & ADVERTISED_Asym_Pause)
+ reg |= ADVERTISE_PAUSE_ASYM;
efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg);
/* Set up the (extended) next page if necessary */
if (efx->phy_op->set_npage_adv)
- efx->phy_op->set_npage_adv(efx, ecmd->advertising);
+ efx->phy_op->set_npage_adv(efx, efx->link_advertising);
/* Enable and restart AN */
reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1);
reg |= MDIO_AN_CTRL1_ENABLE;
- if (!(EFX_WORKAROUND_15195(efx) &&
- LOOPBACK_MASK(efx) & efx->phy_op->loopbacks))
+ if (!(EFX_WORKAROUND_15195(efx) && LOOPBACK_EXTERNAL(efx)))
reg |= MDIO_AN_CTRL1_RESTART;
if (xnp)
reg |= MDIO_AN_CTRL1_XNP;
else
reg &= ~MDIO_AN_CTRL1_XNP;
efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg);
-
- return 0;
}
enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx)