Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

Conflicts:
	drivers/net/e1000/e1000_main.c
This commit is contained in:
David S. Miller
2009-01-30 14:31:07 -08:00
49 changed files with 515 additions and 427 deletions
+6 -19
View File
@@ -2,14 +2,14 @@
IP-Aliasing: IP-Aliasing:
============ ============
IP-aliases are additional IP-addresses/masks hooked up to a base IP-aliases are an obsolete way to manage multiple IP-addresses/masks
interface by adding a colon and a string when running ifconfig. per interface. Newer tools such as iproute2 support multiple
address/prefixes per interface, but aliases are still supported
for backwards compatibility.
An alias is formed by adding a colon and a string when running ifconfig.
This string is usually numeric, but this is not a must. This string is usually numeric, but this is not a must.
IP-Aliases are avail if CONFIG_INET (`standard' IPv4 networking)
is configured in the kernel.
o Alias creation. o Alias creation.
Alias creation is done by 'magic' interface naming: eg. to create a Alias creation is done by 'magic' interface naming: eg. to create a
200.1.1.1 alias for eth0 ... 200.1.1.1 alias for eth0 ...
@@ -38,16 +38,3 @@ o Relationship with main device
If the base device is shut down the added aliases will be deleted If the base device is shut down the added aliases will be deleted
too. too.
Contact
-------
Please finger or e-mail me:
Juan Jose Ciarlante <jjciarla@raiz.uncu.edu.ar>
Updated by Erik Schoenfelder <schoenfr@gaertner.DE>
; local variables:
; mode: indented-text
; mode: auto-fill
; end:
-2
View File
@@ -2836,8 +2836,6 @@ S: Maintained
MAC80211 MAC80211
P: Johannes Berg P: Johannes Berg
M: johannes@sipsolutions.net M: johannes@sipsolutions.net
P: Michael Wu
M: flamingice@sourmilk.net
L: linux-wireless@vger.kernel.org L: linux-wireless@vger.kernel.org
W: http://linuxwireless.org/ W: http://linuxwireless.org/
T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
+2 -2
View File
@@ -31,7 +31,7 @@
char e1000_driver_name[] = "e1000"; char e1000_driver_name[] = "e1000";
static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#define DRV_VERSION "7.3.21-k2-NAPI" #define DRV_VERSION "7.3.21-k3-NAPI"
const char e1000_driver_version[] = DRV_VERSION; const char e1000_driver_version[] = DRV_VERSION;
static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
@@ -3697,7 +3697,7 @@ static irqreturn_t e1000_intr(int irq, void *data)
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
u32 rctl, icr = er32(ICR); u32 rctl, icr = er32(ICR);
if (unlikely(!icr)) if (unlikely((!icr) || test_bit(__E1000_RESETTING, &adapter->flags)))
return IRQ_NONE; /* Not our interrupt */ return IRQ_NONE; /* Not our interrupt */
/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
+2
View File
@@ -234,6 +234,8 @@ static int gfar_mdio_probe(struct of_device *ofdev,
if (NULL == new_bus) if (NULL == new_bus)
return -ENOMEM; return -ENOMEM;
device_init_wakeup(&ofdev->dev, 1);
new_bus->name = "Gianfar MII Bus", new_bus->name = "Gianfar MII Bus",
new_bus->read = &gfar_mdio_read, new_bus->read = &gfar_mdio_read,
new_bus->write = &gfar_mdio_write, new_bus->write = &gfar_mdio_write,
+1 -1
View File
@@ -210,7 +210,7 @@
#define MAX_CMD_DESCRIPTORS_HOST 1024 #define MAX_CMD_DESCRIPTORS_HOST 1024
#define MAX_RCV_DESCRIPTORS_1G 2048 #define MAX_RCV_DESCRIPTORS_1G 2048
#define MAX_RCV_DESCRIPTORS_10G 4096 #define MAX_RCV_DESCRIPTORS_10G 4096
#define MAX_JUMBO_RCV_DESCRIPTORS 512 #define MAX_JUMBO_RCV_DESCRIPTORS 1024
#define MAX_LRO_RCV_DESCRIPTORS 8 #define MAX_LRO_RCV_DESCRIPTORS 8
#define MAX_RCVSTATUS_DESCRIPTORS MAX_RCV_DESCRIPTORS #define MAX_RCVSTATUS_DESCRIPTORS MAX_RCV_DESCRIPTORS
#define MAX_JUMBO_RCV_DESC MAX_JUMBO_RCV_DESCRIPTORS #define MAX_JUMBO_RCV_DESC MAX_JUMBO_RCV_DESCRIPTORS
+3 -1
View File
@@ -947,8 +947,10 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
} }
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (netxen_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 || if (netxen_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 ||
netxen_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0) netxen_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0) {
kfree(buf);
return -EIO; return -EIO;
}
buf[i].addr = addr; buf[i].addr = addr;
buf[i].data = val; buf[i].data = val;
-1
View File
@@ -438,7 +438,6 @@ static void r6040_down(struct net_device *dev)
{ {
struct r6040_private *lp = netdev_priv(dev); struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base; void __iomem *ioaddr = lp->base;
struct pci_dev *pdev = lp->pdev;
int limit = 2048; int limit = 2048;
u16 *adrp; u16 *adrp;
u16 cmd; u16 cmd;
+41 -18
View File
@@ -675,9 +675,8 @@ static int efx_init_port(struct efx_nic *efx)
rc = efx->phy_op->init(efx); rc = efx->phy_op->init(efx);
if (rc) if (rc)
return rc; return rc;
efx->phy_op->reconfigure(efx);
mutex_lock(&efx->mac_lock); mutex_lock(&efx->mac_lock);
efx->phy_op->reconfigure(efx);
rc = falcon_switch_mac(efx); rc = falcon_switch_mac(efx);
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
if (rc) if (rc)
@@ -685,7 +684,7 @@ static int efx_init_port(struct efx_nic *efx)
efx->mac_op->reconfigure(efx); efx->mac_op->reconfigure(efx);
efx->port_initialized = true; efx->port_initialized = true;
efx->stats_enabled = true; efx_stats_enable(efx);
return 0; return 0;
fail: fail:
@@ -734,6 +733,7 @@ static void efx_fini_port(struct efx_nic *efx)
if (!efx->port_initialized) if (!efx->port_initialized)
return; return;
efx_stats_disable(efx);
efx->phy_op->fini(efx); efx->phy_op->fini(efx);
efx->port_initialized = false; efx->port_initialized = false;
@@ -1352,6 +1352,20 @@ static int efx_net_stop(struct net_device *net_dev)
return 0; return 0;
} }
void efx_stats_disable(struct efx_nic *efx)
{
spin_lock(&efx->stats_lock);
++efx->stats_disable_count;
spin_unlock(&efx->stats_lock);
}
void efx_stats_enable(struct efx_nic *efx)
{
spin_lock(&efx->stats_lock);
--efx->stats_disable_count;
spin_unlock(&efx->stats_lock);
}
/* Context: process, dev_base_lock or RTNL held, non-blocking. */ /* Context: process, dev_base_lock or RTNL held, non-blocking. */
static struct net_device_stats *efx_net_stats(struct net_device *net_dev) static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
{ {
@@ -1360,12 +1374,12 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
struct net_device_stats *stats = &net_dev->stats; struct net_device_stats *stats = &net_dev->stats;
/* Update stats if possible, but do not wait if another thread /* Update stats if possible, but do not wait if another thread
* is updating them (or resetting the NIC); slightly stale * is updating them or if MAC stats fetches are temporarily
* stats are acceptable. * disabled; slightly stale stats are acceptable.
*/ */
if (!spin_trylock(&efx->stats_lock)) if (!spin_trylock(&efx->stats_lock))
return stats; return stats;
if (efx->stats_enabled) { if (!efx->stats_disable_count) {
efx->mac_op->update_stats(efx); efx->mac_op->update_stats(efx);
falcon_update_nic_stats(efx); falcon_update_nic_stats(efx);
} }
@@ -1613,16 +1627,12 @@ static void efx_unregister_netdev(struct efx_nic *efx)
/* Tears down the entire software state and most of the hardware state /* Tears down the entire software state and most of the hardware state
* before reset. */ * before reset. */
void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd) void efx_reset_down(struct efx_nic *efx, enum reset_type method,
struct ethtool_cmd *ecmd)
{ {
EFX_ASSERT_RESET_SERIALISED(efx); EFX_ASSERT_RESET_SERIALISED(efx);
/* The net_dev->get_stats handler is quite slow, and will fail efx_stats_disable(efx);
* if a fetch is pending over reset. Serialise against it. */
spin_lock(&efx->stats_lock);
efx->stats_enabled = false;
spin_unlock(&efx->stats_lock);
efx_stop_all(efx); efx_stop_all(efx);
mutex_lock(&efx->mac_lock); mutex_lock(&efx->mac_lock);
mutex_lock(&efx->spi_lock); mutex_lock(&efx->spi_lock);
@@ -1630,6 +1640,8 @@ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
efx->phy_op->get_settings(efx, ecmd); efx->phy_op->get_settings(efx, ecmd);
efx_fini_channels(efx); efx_fini_channels(efx);
if (efx->port_initialized && method != RESET_TYPE_INVISIBLE)
efx->phy_op->fini(efx);
} }
/* This function will always ensure that the locks acquired in /* This function will always ensure that the locks acquired in
@@ -1637,7 +1649,8 @@ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
* that we were unable to reinitialise the hardware, and the * that we were unable to reinitialise the hardware, and the
* driver should be disabled. If ok is false, then the rx and tx * driver should be disabled. If ok is false, then the rx and tx
* engines are not restarted, pending a RESET_DISABLE. */ * engines are not restarted, pending a RESET_DISABLE. */
int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok) int efx_reset_up(struct efx_nic *efx, enum reset_type method,
struct ethtool_cmd *ecmd, bool ok)
{ {
int rc; int rc;
@@ -1649,6 +1662,15 @@ int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok)
ok = false; ok = false;
} }
if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) {
if (ok) {
rc = efx->phy_op->init(efx);
if (rc)
ok = false;
} else
efx->port_initialized = false;
}
if (ok) { if (ok) {
efx_init_channels(efx); efx_init_channels(efx);
@@ -1661,7 +1683,7 @@ int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok)
if (ok) { if (ok) {
efx_start_all(efx); efx_start_all(efx);
efx->stats_enabled = true; efx_stats_enable(efx);
} }
return rc; return rc;
} }
@@ -1693,7 +1715,7 @@ static int efx_reset(struct efx_nic *efx)
EFX_INFO(efx, "resetting (%d)\n", method); EFX_INFO(efx, "resetting (%d)\n", method);
efx_reset_down(efx, &ecmd); efx_reset_down(efx, method, &ecmd);
rc = falcon_reset_hw(efx, method); rc = falcon_reset_hw(efx, method);
if (rc) { if (rc) {
@@ -1712,10 +1734,10 @@ static int efx_reset(struct efx_nic *efx)
/* Leave device stopped if necessary */ /* Leave device stopped if necessary */
if (method == RESET_TYPE_DISABLE) { if (method == RESET_TYPE_DISABLE) {
efx_reset_up(efx, &ecmd, false); efx_reset_up(efx, method, &ecmd, false);
rc = -EIO; rc = -EIO;
} else { } else {
rc = efx_reset_up(efx, &ecmd, true); rc = efx_reset_up(efx, method, &ecmd, true);
} }
out_disable: out_disable:
@@ -1867,6 +1889,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
efx->rx_checksum_enabled = true; efx->rx_checksum_enabled = true;
spin_lock_init(&efx->netif_stop_lock); spin_lock_init(&efx->netif_stop_lock);
spin_lock_init(&efx->stats_lock); spin_lock_init(&efx->stats_lock);
efx->stats_disable_count = 1;
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;
+6 -3
View File
@@ -36,13 +36,16 @@ extern void efx_process_channel_now(struct efx_channel *channel);
extern void efx_flush_queues(struct efx_nic *efx); extern void efx_flush_queues(struct efx_nic *efx);
/* Ports */ /* Ports */
extern void efx_stats_disable(struct efx_nic *efx);
extern void efx_stats_enable(struct efx_nic *efx);
extern void efx_reconfigure_port(struct efx_nic *efx); extern void efx_reconfigure_port(struct efx_nic *efx);
extern void __efx_reconfigure_port(struct efx_nic *efx); extern void __efx_reconfigure_port(struct efx_nic *efx);
/* Reset handling */ /* Reset handling */
extern void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd); extern void efx_reset_down(struct efx_nic *efx, enum reset_type method,
extern int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, struct ethtool_cmd *ecmd);
bool ok); extern int efx_reset_up(struct efx_nic *efx, enum reset_type method,
struct ethtool_cmd *ecmd, bool ok);
/* Global */ /* Global */
extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type); extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
-3
View File
@@ -219,9 +219,6 @@ int efx_ethtool_set_settings(struct net_device *net_dev,
struct efx_nic *efx = netdev_priv(net_dev); struct efx_nic *efx = netdev_priv(net_dev);
int rc; int rc;
if (EFX_WORKAROUND_13963(efx) && !ecmd->autoneg)
return -EINVAL;
/* Falcon GMAC does not support 1000Mbps HD */ /* Falcon GMAC does not support 1000Mbps HD */
if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) { if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) {
EFX_LOG(efx, "rejecting unsupported 1000Mbps HD" EFX_LOG(efx, "rejecting unsupported 1000Mbps HD"
+18 -14
View File
@@ -824,10 +824,6 @@ static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
rx_ev_pause_frm ? " [PAUSE]" : ""); rx_ev_pause_frm ? " [PAUSE]" : "");
} }
#endif #endif
if (unlikely(rx_ev_eth_crc_err && EFX_WORKAROUND_10750(efx) &&
efx->phy_type == PHY_TYPE_SFX7101))
tenxpress_crc_err(efx);
} }
/* Handle receive events that are not in-order. */ /* Handle receive events that are not in-order. */
@@ -1887,7 +1883,7 @@ static int falcon_reset_macs(struct efx_nic *efx)
/* MAC stats will fail whilst the TX fifo is draining. Serialise /* MAC stats will fail whilst the TX fifo is draining. Serialise
* the drain sequence with the statistics fetch */ * the drain sequence with the statistics fetch */
spin_lock(&efx->stats_lock); efx_stats_disable(efx);
falcon_read(efx, &reg, MAC0_CTRL_REG_KER); falcon_read(efx, &reg, MAC0_CTRL_REG_KER);
EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0, 1); EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0, 1);
@@ -1917,7 +1913,7 @@ static int falcon_reset_macs(struct efx_nic *efx)
udelay(10); udelay(10);
} }
spin_unlock(&efx->stats_lock); efx_stats_enable(efx);
/* If we've reset the EM block and the link is up, then /* If we've reset the EM block and the link is up, then
* we'll have to kick the XAUI link so the PHY can recover */ * we'll have to kick the XAUI link so the PHY can recover */
@@ -2277,6 +2273,10 @@ int falcon_switch_mac(struct efx_nic *efx)
struct efx_mac_operations *old_mac_op = efx->mac_op; struct efx_mac_operations *old_mac_op = efx->mac_op;
efx_oword_t nic_stat; efx_oword_t nic_stat;
unsigned strap_val; unsigned strap_val;
int rc = 0;
/* Don't try to fetch MAC stats while we're switching MACs */
efx_stats_disable(efx);
/* Internal loopbacks override the phy speed setting */ /* Internal loopbacks override the phy speed setting */
if (efx->loopback_mode == LOOPBACK_GMAC) { if (efx->loopback_mode == LOOPBACK_GMAC) {
@@ -2287,16 +2287,12 @@ int falcon_switch_mac(struct efx_nic *efx)
efx->link_fd = true; efx->link_fd = true;
} }
WARN_ON(!mutex_is_locked(&efx->mac_lock));
efx->mac_op = (EFX_IS10G(efx) ? efx->mac_op = (EFX_IS10G(efx) ?
&falcon_xmac_operations : &falcon_gmac_operations); &falcon_xmac_operations : &falcon_gmac_operations);
if (old_mac_op == efx->mac_op)
return 0;
WARN_ON(!mutex_is_locked(&efx->mac_lock));
/* Not all macs support a mac-level link state */
efx->mac_up = true;
/* Always push the NIC_STAT_REG setting even if the mac hasn't
* changed, because this function is run post online reset */
falcon_read(efx, &nic_stat, NIC_STAT_REG); falcon_read(efx, &nic_stat, NIC_STAT_REG);
strap_val = EFX_IS10G(efx) ? 5 : 3; strap_val = EFX_IS10G(efx) ? 5 : 3;
if (falcon_rev(efx) >= FALCON_REV_B0) { if (falcon_rev(efx) >= FALCON_REV_B0) {
@@ -2309,9 +2305,17 @@ int falcon_switch_mac(struct efx_nic *efx)
BUG_ON(EFX_OWORD_FIELD(nic_stat, STRAP_PINS) != strap_val); BUG_ON(EFX_OWORD_FIELD(nic_stat, STRAP_PINS) != strap_val);
} }
if (old_mac_op == efx->mac_op)
goto out;
EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G'); EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G');
return falcon_reset_macs(efx); /* Not all macs support a mac-level link state */
efx->mac_up = true;
rc = falcon_reset_macs(efx);
out:
efx_stats_enable(efx);
return rc;
} }
/* This call is responsible for hooking in the MAC and PHY operations */ /* This call is responsible for hooking in the MAC and PHY operations */
+87 -100
View File
@@ -15,6 +15,7 @@
#include "net_driver.h" #include "net_driver.h"
#include "mdio_10g.h" #include "mdio_10g.h"
#include "boards.h" #include "boards.h"
#include "workarounds.h"
int mdio_clause45_reset_mmd(struct efx_nic *port, int mmd, int mdio_clause45_reset_mmd(struct efx_nic *port, int mmd,
int spins, int spintime) int spins, int spintime)
@@ -179,17 +180,12 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
return false; return false;
else if (efx_phy_mode_disabled(efx->phy_mode)) else if (efx_phy_mode_disabled(efx->phy_mode))
return false; return false;
else if (efx->loopback_mode == LOOPBACK_PHYXS) { else if (efx->loopback_mode == LOOPBACK_PHYXS)
mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS | mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS |
MDIO_MMDREG_DEVS_PCS | MDIO_MMDREG_DEVS_PCS |
MDIO_MMDREG_DEVS_PMAPMD | MDIO_MMDREG_DEVS_PMAPMD |
MDIO_MMDREG_DEVS_AN); MDIO_MMDREG_DEVS_AN);
if (!mmd_mask) { else if (efx->loopback_mode == LOOPBACK_PCS)
reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS,
MDIO_PHYXS_STATUS2);
return !(reg & (1 << MDIO_PHYXS_STATUS2_RX_FAULT_LBN));
}
} else if (efx->loopback_mode == LOOPBACK_PCS)
mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS | mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS |
MDIO_MMDREG_DEVS_PMAPMD | MDIO_MMDREG_DEVS_PMAPMD |
MDIO_MMDREG_DEVS_AN); MDIO_MMDREG_DEVS_AN);
@@ -197,6 +193,13 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
mmd_mask &= ~(MDIO_MMDREG_DEVS_PMAPMD | mmd_mask &= ~(MDIO_MMDREG_DEVS_PMAPMD |
MDIO_MMDREG_DEVS_AN); MDIO_MMDREG_DEVS_AN);
if (!mmd_mask) {
/* Use presence of XGMII faults in leui of link state */
reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS,
MDIO_PHYXS_STATUS2);
return !(reg & (1 << MDIO_PHYXS_STATUS2_RX_FAULT_LBN));
}
while (mmd_mask) { while (mmd_mask) {
if (mmd_mask & 1) { if (mmd_mask & 1) {
/* Double reads because link state is latched, and a /* Double reads because link state is latched, and a
@@ -263,7 +266,7 @@ void mdio_clause45_set_mmds_lpower(struct efx_nic *efx,
} }
} }
static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr, u32 xnp) static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr)
{ {
int phy_id = efx->mii.phy_id; int phy_id = efx->mii.phy_id;
u32 result = 0; u32 result = 0;
@@ -278,9 +281,6 @@ static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr, u32 xnp)
result |= ADVERTISED_100baseT_Half; result |= ADVERTISED_100baseT_Half;
if (reg & ADVERTISE_100FULL) if (reg & ADVERTISE_100FULL)
result |= ADVERTISED_100baseT_Full; result |= ADVERTISED_100baseT_Full;
if (reg & LPA_RESV)
result |= xnp;
return result; return result;
} }
@@ -310,7 +310,7 @@ void mdio_clause45_get_settings(struct efx_nic *efx,
*/ */
void mdio_clause45_get_settings_ext(struct efx_nic *efx, void mdio_clause45_get_settings_ext(struct efx_nic *efx,
struct ethtool_cmd *ecmd, struct ethtool_cmd *ecmd,
u32 xnp, u32 xnp_lpa) u32 npage_adv, u32 npage_lpa)
{ {
int phy_id = efx->mii.phy_id; int phy_id = efx->mii.phy_id;
int reg; int reg;
@@ -361,8 +361,8 @@ void mdio_clause45_get_settings_ext(struct efx_nic *efx,
ecmd->autoneg = AUTONEG_ENABLE; ecmd->autoneg = AUTONEG_ENABLE;
ecmd->advertising |= ecmd->advertising |=
ADVERTISED_Autoneg | ADVERTISED_Autoneg |
mdio_clause45_get_an(efx, mdio_clause45_get_an(efx, MDIO_AN_ADVERTISE) |
MDIO_AN_ADVERTISE, xnp); npage_adv;
} else } else
ecmd->autoneg = AUTONEG_DISABLE; ecmd->autoneg = AUTONEG_DISABLE;
} else } else
@@ -371,27 +371,30 @@ void mdio_clause45_get_settings_ext(struct efx_nic *efx,
if (ecmd->autoneg) { if (ecmd->autoneg) {
/* If AN is complete, report best common mode, /* If AN is complete, report best common mode,
* otherwise report best advertised mode. */ * otherwise report best advertised mode. */
u32 common = ecmd->advertising; u32 modes = 0;
if (mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, if (mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
MDIO_MMDREG_STAT1) & MDIO_MMDREG_STAT1) &
(1 << MDIO_AN_STATUS_AN_DONE_LBN)) { (1 << MDIO_AN_STATUS_AN_DONE_LBN))
common &= mdio_clause45_get_an(efx, MDIO_AN_LPA, modes = (ecmd->advertising &
xnp_lpa); (mdio_clause45_get_an(efx, MDIO_AN_LPA) |
} npage_lpa));
if (common & ADVERTISED_10000baseT_Full) { if (modes == 0)
modes = ecmd->advertising;
if (modes & ADVERTISED_10000baseT_Full) {
ecmd->speed = SPEED_10000; ecmd->speed = SPEED_10000;
ecmd->duplex = DUPLEX_FULL; ecmd->duplex = DUPLEX_FULL;
} else if (common & (ADVERTISED_1000baseT_Full | } else if (modes & (ADVERTISED_1000baseT_Full |
ADVERTISED_1000baseT_Half)) { ADVERTISED_1000baseT_Half)) {
ecmd->speed = SPEED_1000; ecmd->speed = SPEED_1000;
ecmd->duplex = !!(common & ADVERTISED_1000baseT_Full); ecmd->duplex = !!(modes & ADVERTISED_1000baseT_Full);
} else if (common & (ADVERTISED_100baseT_Full | } else if (modes & (ADVERTISED_100baseT_Full |
ADVERTISED_100baseT_Half)) { ADVERTISED_100baseT_Half)) {
ecmd->speed = SPEED_100; ecmd->speed = SPEED_100;
ecmd->duplex = !!(common & ADVERTISED_100baseT_Full); ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full);
} else { } else {
ecmd->speed = SPEED_10; ecmd->speed = SPEED_10;
ecmd->duplex = !!(common & ADVERTISED_10baseT_Full); ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full);
} }
} else { } else {
/* Report forced settings */ /* Report forced settings */
@@ -415,7 +418,7 @@ int mdio_clause45_set_settings(struct efx_nic *efx,
int phy_id = efx->mii.phy_id; int phy_id = efx->mii.phy_id;
struct ethtool_cmd prev; struct ethtool_cmd prev;
u32 required; u32 required;
int ctrl1_bits, reg; int reg;
efx->phy_op->get_settings(efx, &prev); efx->phy_op->get_settings(efx, &prev);
@@ -430,99 +433,83 @@ int mdio_clause45_set_settings(struct efx_nic *efx,
if (prev.port != PORT_TP || ecmd->port != PORT_TP) if (prev.port != PORT_TP || ecmd->port != PORT_TP)
return -EINVAL; return -EINVAL;
/* Check that PHY supports these settings and work out the /* Check that PHY supports these settings */
* basic control bits */ if (ecmd->autoneg) {
if (ecmd->duplex) { required = SUPPORTED_Autoneg;
} else if (ecmd->duplex) {
switch (ecmd->speed) { switch (ecmd->speed) {
case SPEED_10: case SPEED_10: required = SUPPORTED_10baseT_Full; break;
ctrl1_bits = BMCR_FULLDPLX; case SPEED_100: required = SUPPORTED_100baseT_Full; break;
required = SUPPORTED_10baseT_Full; default: return -EINVAL;
break;
case SPEED_100:
ctrl1_bits = BMCR_SPEED100 | BMCR_FULLDPLX;
required = SUPPORTED_100baseT_Full;
break;
case SPEED_1000:
ctrl1_bits = BMCR_SPEED1000 | BMCR_FULLDPLX;
required = SUPPORTED_1000baseT_Full;
break;
case SPEED_10000:
ctrl1_bits = (BMCR_SPEED1000 | BMCR_SPEED100 |
BMCR_FULLDPLX);
required = SUPPORTED_10000baseT_Full;
break;
default:
return -EINVAL;
} }
} else { } else {
switch (ecmd->speed) { switch (ecmd->speed) {
case SPEED_10: case SPEED_10: required = SUPPORTED_10baseT_Half; break;
ctrl1_bits = 0; case SPEED_100: required = SUPPORTED_100baseT_Half; break;
required = SUPPORTED_10baseT_Half; default: return -EINVAL;
break;
case SPEED_100:
ctrl1_bits = BMCR_SPEED100;
required = SUPPORTED_100baseT_Half;
break;
case SPEED_1000:
ctrl1_bits = BMCR_SPEED1000;
required = SUPPORTED_1000baseT_Half;
break;
default:
return -EINVAL;
} }
} }
if (ecmd->autoneg)
required |= SUPPORTED_Autoneg;
required |= ecmd->advertising; required |= ecmd->advertising;
if (required & ~prev.supported) if (required & ~prev.supported)
return -EINVAL; return -EINVAL;
/* Set the basic control bits */ if (ecmd->autoneg) {
reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, bool xnp = (ecmd->advertising & ADVERTISED_10000baseT_Full
MDIO_MMDREG_CTRL1); || EFX_WORKAROUND_13204(efx));
reg &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX | 0x003c);
reg |= ctrl1_bits;
mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, MDIO_MMDREG_CTRL1,
reg);
/* Set the AN registers */ /* Set up the base page */
if (ecmd->autoneg != prev.autoneg || reg = ADVERTISE_CSMA;
ecmd->advertising != prev.advertising) { if (ecmd->advertising & ADVERTISED_10baseT_Half)
bool xnp = false; reg |= ADVERTISE_10HALF;
if (ecmd->advertising & ADVERTISED_10baseT_Full)
reg |= ADVERTISE_10FULL;
if (ecmd->advertising & ADVERTISED_100baseT_Half)
reg |= ADVERTISE_100HALF;
if (ecmd->advertising & ADVERTISED_100baseT_Full)
reg |= ADVERTISE_100FULL;
if (xnp)
reg |= ADVERTISE_RESV;
else if (ecmd->advertising & (ADVERTISED_1000baseT_Half |
ADVERTISED_1000baseT_Full))
reg |= ADVERTISE_NPAGE;
reg |= efx_fc_advertise(efx->wanted_fc);
mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
MDIO_AN_ADVERTISE, reg);
if (efx->phy_op->set_xnp_advertise) /* Set up the (extended) next page if necessary */
xnp = efx->phy_op->set_xnp_advertise(efx, if (efx->phy_op->set_npage_adv)
ecmd->advertising); efx->phy_op->set_npage_adv(efx, ecmd->advertising);
if (ecmd->autoneg) {
reg = 0;
if (ecmd->advertising & ADVERTISED_10baseT_Half)
reg |= ADVERTISE_10HALF;
if (ecmd->advertising & ADVERTISED_10baseT_Full)
reg |= ADVERTISE_10FULL;
if (ecmd->advertising & ADVERTISED_100baseT_Half)
reg |= ADVERTISE_100HALF;
if (ecmd->advertising & ADVERTISED_100baseT_Full)
reg |= ADVERTISE_100FULL;
if (xnp)
reg |= ADVERTISE_RESV;
mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
MDIO_AN_ADVERTISE, reg);
}
/* Enable and restart AN */
reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
MDIO_MMDREG_CTRL1); MDIO_MMDREG_CTRL1);
if (ecmd->autoneg) reg |= BMCR_ANENABLE;
reg |= BMCR_ANENABLE | BMCR_ANRESTART; if (!(EFX_WORKAROUND_15195(efx) &&
else LOOPBACK_MASK(efx) & efx->phy_op->loopbacks))
reg &= ~BMCR_ANENABLE; reg |= BMCR_ANRESTART;
if (xnp) if (xnp)
reg |= 1 << MDIO_AN_CTRL_XNP_LBN; reg |= 1 << MDIO_AN_CTRL_XNP_LBN;
else else
reg &= ~(1 << MDIO_AN_CTRL_XNP_LBN); reg &= ~(1 << MDIO_AN_CTRL_XNP_LBN);
mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
MDIO_MMDREG_CTRL1, reg); MDIO_MMDREG_CTRL1, reg);
} else {
/* Disable AN */
mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN,
MDIO_MMDREG_CTRL1,
__ffs(BMCR_ANENABLE), false);
/* Set the basic control bits */
reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
MDIO_MMDREG_CTRL1);
reg &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX |
0x003c);
if (ecmd->speed == SPEED_100)
reg |= BMCR_SPEED100;
if (ecmd->duplex)
reg |= BMCR_FULLDPLX;
mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
MDIO_MMDREG_CTRL1, reg);
} }
return 0; return 0;
+2 -1
View File
@@ -155,7 +155,8 @@
#define MDIO_AN_XNP 22 #define MDIO_AN_XNP 22
#define MDIO_AN_LPA_XNP 25 #define MDIO_AN_LPA_XNP 25
#define MDIO_AN_10GBT_ADVERTISE 32 #define MDIO_AN_10GBT_CTRL 32
#define MDIO_AN_10GBT_CTRL_ADV_10G_LBN 12
#define MDIO_AN_10GBT_STATUS (33) #define MDIO_AN_10GBT_STATUS (33)
#define MDIO_AN_10GBT_STATUS_MS_FLT_LBN (15) /* MASTER/SLAVE config fault */ #define MDIO_AN_10GBT_STATUS_MS_FLT_LBN (15) /* MASTER/SLAVE config fault */
#define MDIO_AN_10GBT_STATUS_MS_LBN (14) /* MASTER/SLAVE config */ #define MDIO_AN_10GBT_STATUS_MS_LBN (14) /* MASTER/SLAVE config */
+4 -5
View File
@@ -557,7 +557,7 @@ struct efx_mac_operations {
* @poll: Poll for hardware state. Serialised by the mac_lock. * @poll: Poll for hardware state. Serialised by the mac_lock.
* @get_settings: Get ethtool settings. Serialised by the mac_lock. * @get_settings: Get ethtool settings. Serialised by the mac_lock.
* @set_settings: Set ethtool settings. Serialised by the mac_lock. * @set_settings: Set ethtool settings. Serialised by the mac_lock.
* @set_xnp_advertise: Set abilities advertised in Extended Next Page * @set_npage_adv: Set abilities advertised in (Extended) Next Page
* (only needed where AN bit is set in mmds) * (only needed where AN bit is set in mmds)
* @num_tests: Number of PHY-specific tests/results * @num_tests: Number of PHY-specific tests/results
* @test_names: Names of the tests/results * @test_names: Names of the tests/results
@@ -577,7 +577,7 @@ struct efx_phy_operations {
struct ethtool_cmd *ecmd); struct ethtool_cmd *ecmd);
int (*set_settings) (struct efx_nic *efx, int (*set_settings) (struct efx_nic *efx,
struct ethtool_cmd *ecmd); struct ethtool_cmd *ecmd);
bool (*set_xnp_advertise) (struct efx_nic *efx, u32); void (*set_npage_adv) (struct efx_nic *efx, u32);
u32 num_tests; u32 num_tests;
const char *const *test_names; const char *const *test_names;
int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags); int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags);
@@ -745,8 +745,7 @@ union efx_multicast_hash {
* &struct net_device_stats. * &struct net_device_stats.
* @stats_buffer: DMA buffer for statistics * @stats_buffer: DMA buffer for statistics
* @stats_lock: Statistics update lock. Serialises statistics fetches * @stats_lock: Statistics update lock. Serialises statistics fetches
* @stats_enabled: Temporarily disable statistics fetches. * @stats_disable_count: Nest count for disabling statistics fetches
* Serialised by @stats_lock
* @mac_op: MAC interface * @mac_op: MAC interface
* @mac_address: Permanent MAC address * @mac_address: Permanent MAC address
* @phy_type: PHY type * @phy_type: PHY type
@@ -828,7 +827,7 @@ struct efx_nic {
struct efx_mac_stats mac_stats; struct efx_mac_stats mac_stats;
struct efx_buffer stats_buffer; struct efx_buffer stats_buffer;
spinlock_t stats_lock; spinlock_t stats_lock;
bool stats_enabled; unsigned int stats_disable_count;
struct efx_mac_operations *mac_op; struct efx_mac_operations *mac_op;
unsigned char mac_address[ETH_ALEN]; unsigned char mac_address[ETH_ALEN];
-1
View File
@@ -17,7 +17,6 @@ extern struct efx_phy_operations falcon_sfx7101_phy_ops;
extern struct efx_phy_operations falcon_sft9001_phy_ops; extern struct efx_phy_operations falcon_sft9001_phy_ops;
extern void tenxpress_phy_blink(struct efx_nic *efx, bool blink); extern void tenxpress_phy_blink(struct efx_nic *efx, bool blink);
extern void tenxpress_crc_err(struct efx_nic *efx);
/**************************************************************************** /****************************************************************************
* Exported functions from the driver for XFP optical PHYs * Exported functions from the driver for XFP optical PHYs
+4 -3
View File
@@ -665,6 +665,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
{ {
enum efx_loopback_mode loopback_mode = efx->loopback_mode; enum efx_loopback_mode loopback_mode = efx->loopback_mode;
int phy_mode = efx->phy_mode; int phy_mode = efx->phy_mode;
enum reset_type reset_method = RESET_TYPE_INVISIBLE;
struct ethtool_cmd ecmd; struct ethtool_cmd ecmd;
struct efx_channel *channel; struct efx_channel *channel;
int rc_test = 0, rc_reset = 0, rc; int rc_test = 0, rc_reset = 0, rc;
@@ -718,21 +719,21 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
/* free up all consumers of SRAM (including all the queues) */ /* free up all consumers of SRAM (including all the queues) */
efx_reset_down(efx, &ecmd); efx_reset_down(efx, reset_method, &ecmd);
rc = efx_test_chip(efx, tests); rc = efx_test_chip(efx, tests);
if (rc && !rc_test) if (rc && !rc_test)
rc_test = rc; rc_test = rc;
/* reset the chip to recover from the register test */ /* reset the chip to recover from the register test */
rc_reset = falcon_reset_hw(efx, RESET_TYPE_ALL); rc_reset = falcon_reset_hw(efx, reset_method);
/* Ensure that the phy is powered and out of loopback /* Ensure that the phy is powered and out of loopback
* for the bist and loopback tests */ * for the bist and loopback tests */
efx->phy_mode &= ~PHY_MODE_LOW_POWER; efx->phy_mode &= ~PHY_MODE_LOW_POWER;
efx->loopback_mode = LOOPBACK_NONE; efx->loopback_mode = LOOPBACK_NONE;
rc = efx_reset_up(efx, &ecmd, rc_reset == 0); rc = efx_reset_up(efx, reset_method, &ecmd, rc_reset == 0);
if (rc && !rc_reset) if (rc && !rc_reset)
rc_reset = rc; rc_reset = rc;
+33 -9
View File
@@ -187,19 +187,22 @@ static int sfn4111t_reset(struct efx_nic *efx)
{ {
efx_oword_t reg; efx_oword_t reg;
/* GPIO pins are also used for I2C, so block that temporarily */ /* GPIO 3 and the GPIO register are shared with I2C, so block that */
mutex_lock(&efx->i2c_adap.bus_lock); mutex_lock(&efx->i2c_adap.bus_lock);
/* Pull RST_N (GPIO 2) low then let it up again, setting the
* FLASH_CFG_1 strap (GPIO 3) appropriately. Only change the
* output enables; the output levels should always be 0 (low)
* and we rely on external pull-ups. */
falcon_read(efx, &reg, GPIO_CTL_REG_KER); falcon_read(efx, &reg, GPIO_CTL_REG_KER);
EFX_SET_OWORD_FIELD(reg, GPIO2_OEN, true); EFX_SET_OWORD_FIELD(reg, GPIO2_OEN, true);
EFX_SET_OWORD_FIELD(reg, GPIO2_OUT, false);
falcon_write(efx, &reg, GPIO_CTL_REG_KER); falcon_write(efx, &reg, GPIO_CTL_REG_KER);
msleep(1000); msleep(1000);
EFX_SET_OWORD_FIELD(reg, GPIO2_OUT, true); EFX_SET_OWORD_FIELD(reg, GPIO2_OEN, false);
EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, true); EFX_SET_OWORD_FIELD(reg, GPIO3_OEN,
EFX_SET_OWORD_FIELD(reg, GPIO3_OUT, !!(efx->phy_mode & PHY_MODE_SPECIAL));
!(efx->phy_mode & PHY_MODE_SPECIAL));
falcon_write(efx, &reg, GPIO_CTL_REG_KER); falcon_write(efx, &reg, GPIO_CTL_REG_KER);
msleep(1);
mutex_unlock(&efx->i2c_adap.bus_lock); mutex_unlock(&efx->i2c_adap.bus_lock);
@@ -233,12 +236,18 @@ static ssize_t set_phy_flash_cfg(struct device *dev,
} else if (efx->state != STATE_RUNNING || netif_running(efx->net_dev)) { } else if (efx->state != STATE_RUNNING || netif_running(efx->net_dev)) {
err = -EBUSY; err = -EBUSY;
} else { } else {
/* Reset the PHY, reconfigure the MAC and enable/disable
* MAC stats accordingly. */
efx->phy_mode = new_mode; efx->phy_mode = new_mode;
if (new_mode & PHY_MODE_SPECIAL)
efx_stats_disable(efx);
if (efx->board_info.type == EFX_BOARD_SFE4001) if (efx->board_info.type == EFX_BOARD_SFE4001)
err = sfe4001_poweron(efx); err = sfe4001_poweron(efx);
else else
err = sfn4111t_reset(efx); err = sfn4111t_reset(efx);
efx_reconfigure_port(efx); efx_reconfigure_port(efx);
if (!(new_mode & PHY_MODE_SPECIAL))
efx_stats_enable(efx);
} }
rtnl_unlock(); rtnl_unlock();
@@ -327,6 +336,11 @@ int sfe4001_init(struct efx_nic *efx)
efx->board_info.monitor = sfe4001_check_hw; efx->board_info.monitor = sfe4001_check_hw;
efx->board_info.fini = sfe4001_fini; efx->board_info.fini = sfe4001_fini;
if (efx->phy_mode & PHY_MODE_SPECIAL) {
/* PHY won't generate a 156.25 MHz clock and MAC stats fetch
* will fail. */
efx_stats_disable(efx);
}
rc = sfe4001_poweron(efx); rc = sfe4001_poweron(efx);
if (rc) if (rc)
goto fail_ioexp; goto fail_ioexp;
@@ -373,17 +387,25 @@ static void sfn4111t_fini(struct efx_nic *efx)
i2c_unregister_device(efx->board_info.hwmon_client); i2c_unregister_device(efx->board_info.hwmon_client);
} }
static struct i2c_board_info sfn4111t_hwmon_info = { static struct i2c_board_info sfn4111t_a0_hwmon_info = {
I2C_BOARD_INFO("max6647", 0x4e), I2C_BOARD_INFO("max6647", 0x4e),
.irq = -1, .irq = -1,
}; };
static struct i2c_board_info sfn4111t_r5_hwmon_info = {
I2C_BOARD_INFO("max6646", 0x4d),
.irq = -1,
};
int sfn4111t_init(struct efx_nic *efx) int sfn4111t_init(struct efx_nic *efx)
{ {
int rc; int rc;
efx->board_info.hwmon_client = efx->board_info.hwmon_client =
i2c_new_device(&efx->i2c_adap, &sfn4111t_hwmon_info); i2c_new_device(&efx->i2c_adap,
(efx->board_info.minor < 5) ?
&sfn4111t_a0_hwmon_info :
&sfn4111t_r5_hwmon_info);
if (!efx->board_info.hwmon_client) if (!efx->board_info.hwmon_client)
return -EIO; return -EIO;
@@ -395,8 +417,10 @@ int sfn4111t_init(struct efx_nic *efx)
if (rc) if (rc)
goto fail_hwmon; goto fail_hwmon;
if (efx->phy_mode & PHY_MODE_SPECIAL) if (efx->phy_mode & PHY_MODE_SPECIAL) {
efx_stats_disable(efx);
sfn4111t_reset(efx); sfn4111t_reset(efx);
}
return 0; return 0;
+80 -139
View File
@@ -68,6 +68,8 @@
#define PMA_PMD_EXT_CLK312_WIDTH 1 #define PMA_PMD_EXT_CLK312_WIDTH 1
#define PMA_PMD_EXT_LPOWER_LBN 12 #define PMA_PMD_EXT_LPOWER_LBN 12
#define PMA_PMD_EXT_LPOWER_WIDTH 1 #define PMA_PMD_EXT_LPOWER_WIDTH 1
#define PMA_PMD_EXT_ROBUST_LBN 14
#define PMA_PMD_EXT_ROBUST_WIDTH 1
#define PMA_PMD_EXT_SSR_LBN 15 #define PMA_PMD_EXT_SSR_LBN 15
#define PMA_PMD_EXT_SSR_WIDTH 1 #define PMA_PMD_EXT_SSR_WIDTH 1
@@ -178,35 +180,24 @@
#define C22EXT_STATUS_LINK_LBN 2 #define C22EXT_STATUS_LINK_LBN 2
#define C22EXT_STATUS_LINK_WIDTH 1 #define C22EXT_STATUS_LINK_WIDTH 1
#define C22EXT_MSTSLV_REG 49162 #define C22EXT_MSTSLV_CTRL 49161
#define C22EXT_MSTSLV_1000_HD_LBN 10 #define C22EXT_MSTSLV_CTRL_ADV_1000_HD_LBN 8
#define C22EXT_MSTSLV_1000_HD_WIDTH 1 #define C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN 9
#define C22EXT_MSTSLV_1000_FD_LBN 11
#define C22EXT_MSTSLV_1000_FD_WIDTH 1 #define C22EXT_MSTSLV_STATUS 49162
#define C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN 10
#define C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN 11
/* Time to wait between powering down the LNPGA and turning off the power /* Time to wait between powering down the LNPGA and turning off the power
* rails */ * rails */
#define LNPGA_PDOWN_WAIT (HZ / 5) #define LNPGA_PDOWN_WAIT (HZ / 5)
static int crc_error_reset_threshold = 100;
module_param(crc_error_reset_threshold, int, 0644);
MODULE_PARM_DESC(crc_error_reset_threshold,
"Max number of CRC errors before XAUI reset");
struct tenxpress_phy_data { struct tenxpress_phy_data {
enum efx_loopback_mode loopback_mode; enum efx_loopback_mode loopback_mode;
atomic_t bad_crc_count;
enum efx_phy_mode phy_mode; enum efx_phy_mode phy_mode;
int bad_lp_tries; int bad_lp_tries;
}; };
void tenxpress_crc_err(struct efx_nic *efx)
{
struct tenxpress_phy_data *phy_data = efx->phy_data;
if (phy_data != NULL)
atomic_inc(&phy_data->bad_crc_count);
}
static ssize_t show_phy_short_reach(struct device *dev, static ssize_t show_phy_short_reach(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
@@ -285,7 +276,9 @@ static int tenxpress_init(struct efx_nic *efx)
PMA_PMD_XCONTROL_REG); PMA_PMD_XCONTROL_REG);
reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) | reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) |
(1 << PMA_PMD_EXT_CLK_OUT_LBN) | (1 << PMA_PMD_EXT_CLK_OUT_LBN) |
(1 << PMA_PMD_EXT_CLK312_LBN)); (1 << PMA_PMD_EXT_CLK312_LBN) |
(1 << PMA_PMD_EXT_ROBUST_LBN));
mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
PMA_PMD_XCONTROL_REG, reg); PMA_PMD_XCONTROL_REG, reg);
mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
@@ -347,6 +340,7 @@ static int tenxpress_phy_init(struct efx_nic *efx)
rc = tenxpress_init(efx); rc = tenxpress_init(efx);
if (rc < 0) if (rc < 0)
goto fail; goto fail;
mdio_clause45_set_pause(efx);
if (efx->phy_type == PHY_TYPE_SFT9001B) { if (efx->phy_type == PHY_TYPE_SFT9001B) {
rc = device_create_file(&efx->pci_dev->dev, rc = device_create_file(&efx->pci_dev->dev,
@@ -377,8 +371,8 @@ static int tenxpress_special_reset(struct efx_nic *efx)
/* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so
* a special software reset can glitch the XGMAC sufficiently for stats * a special software reset can glitch the XGMAC sufficiently for stats
* requests to fail. Since we don't often special_reset, just lock. */ * requests to fail. */
spin_lock(&efx->stats_lock); efx_stats_disable(efx);
/* Initiate reset */ /* Initiate reset */
reg = mdio_clause45_read(efx, efx->mii.phy_id, reg = mdio_clause45_read(efx, efx->mii.phy_id,
@@ -393,17 +387,17 @@ static int tenxpress_special_reset(struct efx_nic *efx)
rc = mdio_clause45_wait_reset_mmds(efx, rc = mdio_clause45_wait_reset_mmds(efx,
TENXPRESS_REQUIRED_DEVS); TENXPRESS_REQUIRED_DEVS);
if (rc < 0) if (rc < 0)
goto unlock; goto out;
/* Try and reconfigure the device */ /* Try and reconfigure the device */
rc = tenxpress_init(efx); rc = tenxpress_init(efx);
if (rc < 0) if (rc < 0)
goto unlock; goto out;
/* Wait for the XGXS state machine to churn */ /* Wait for the XGXS state machine to churn */
mdelay(10); mdelay(10);
unlock: out:
spin_unlock(&efx->stats_lock); efx_stats_enable(efx);
return rc; return rc;
} }
@@ -521,7 +515,7 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
{ {
struct tenxpress_phy_data *phy_data = efx->phy_data; struct tenxpress_phy_data *phy_data = efx->phy_data;
struct ethtool_cmd ecmd; struct ethtool_cmd ecmd;
bool phy_mode_change, loop_reset, loop_toggle, loopback; bool phy_mode_change, loop_reset;
if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) { if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) {
phy_data->phy_mode = efx->phy_mode; phy_data->phy_mode = efx->phy_mode;
@@ -532,12 +526,10 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL && phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL &&
phy_data->phy_mode != PHY_MODE_NORMAL); phy_data->phy_mode != PHY_MODE_NORMAL);
loopback = LOOPBACK_MASK(efx) & efx->phy_op->loopbacks;
loop_toggle = LOOPBACK_CHANGED(phy_data, efx, efx->phy_op->loopbacks);
loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, efx->phy_op->loopbacks) || loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, efx->phy_op->loopbacks) ||
LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY)); LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY));
if (loop_reset || loop_toggle || loopback || phy_mode_change) { if (loop_reset || phy_mode_change) {
int rc; int rc;
efx->phy_op->get_settings(efx, &ecmd); efx->phy_op->get_settings(efx, &ecmd);
@@ -552,20 +544,6 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
falcon_reset_xaui(efx); falcon_reset_xaui(efx);
} }
if (efx->phy_type != PHY_TYPE_SFX7101) {
/* Only change autoneg once, on coming out or
* going into loopback */
if (loop_toggle)
ecmd.autoneg = !loopback;
if (loopback) {
ecmd.duplex = DUPLEX_FULL;
if (efx->loopback_mode == LOOPBACK_GPHY)
ecmd.speed = SPEED_1000;
else
ecmd.speed = SPEED_10000;
}
}
rc = efx->phy_op->set_settings(efx, &ecmd); rc = efx->phy_op->set_settings(efx, &ecmd);
WARN_ON(rc); WARN_ON(rc);
} }
@@ -624,13 +602,6 @@ static void tenxpress_phy_poll(struct efx_nic *efx)
if (phy_data->phy_mode != PHY_MODE_NORMAL) if (phy_data->phy_mode != PHY_MODE_NORMAL)
return; return;
if (EFX_WORKAROUND_10750(efx) &&
atomic_read(&phy_data->bad_crc_count) > crc_error_reset_threshold) {
EFX_ERR(efx, "Resetting XAUI due to too many CRC errors\n");
falcon_reset_xaui(efx);
atomic_set(&phy_data->bad_crc_count, 0);
}
} }
static void tenxpress_phy_fini(struct efx_nic *efx) static void tenxpress_phy_fini(struct efx_nic *efx)
@@ -773,107 +744,76 @@ reset:
return rc; return rc;
} }
static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx) static void
tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{ {
int phy = efx->mii.phy_id; int phy_id = efx->mii.phy_id;
u32 lpa = 0; u32 adv = 0, lpa = 0;
int reg; int reg;
if (efx->phy_type != PHY_TYPE_SFX7101) { if (efx->phy_type != PHY_TYPE_SFX7101) {
reg = mdio_clause45_read(efx, phy, MDIO_MMD_C22EXT, reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
C22EXT_MSTSLV_REG); C22EXT_MSTSLV_CTRL);
if (reg & (1 << C22EXT_MSTSLV_1000_HD_LBN)) if (reg & (1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN))
adv |= ADVERTISED_1000baseT_Full;
reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
C22EXT_MSTSLV_STATUS);
if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN))
lpa |= ADVERTISED_1000baseT_Half; lpa |= ADVERTISED_1000baseT_Half;
if (reg & (1 << C22EXT_MSTSLV_1000_FD_LBN)) if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN))
lpa |= ADVERTISED_1000baseT_Full; lpa |= ADVERTISED_1000baseT_Full;
} }
reg = mdio_clause45_read(efx, phy, MDIO_MMD_AN, MDIO_AN_10GBT_STATUS); reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
MDIO_AN_10GBT_CTRL);
if (reg & (1 << MDIO_AN_10GBT_CTRL_ADV_10G_LBN))
adv |= ADVERTISED_10000baseT_Full;
reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
MDIO_AN_10GBT_STATUS);
if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN)) if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN))
lpa |= ADVERTISED_10000baseT_Full; lpa |= ADVERTISED_10000baseT_Full;
return lpa;
mdio_clause45_get_settings_ext(efx, ecmd, adv, lpa);
if (efx->phy_type != PHY_TYPE_SFX7101)
ecmd->supported |= (SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Full);
/* In loopback, the PHY automatically brings up the correct interface,
* but doesn't advertise the correct speed. So override it */
if (efx->loopback_mode == LOOPBACK_GPHY)
ecmd->speed = SPEED_1000;
else if (LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)
ecmd->speed = SPEED_10000;
} }
static void sfx7101_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) static int tenxpress_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{ {
mdio_clause45_get_settings_ext(efx, ecmd, ADVERTISED_10000baseT_Full, if (!ecmd->autoneg)
tenxpress_get_xnp_lpa(efx)); return -EINVAL;
ecmd->supported |= SUPPORTED_10000baseT_Full;
ecmd->advertising |= ADVERTISED_10000baseT_Full; return mdio_clause45_set_settings(efx, ecmd);
} }
static void sft9001_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising)
{
mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_AN,
MDIO_AN_10GBT_CTRL,
MDIO_AN_10GBT_CTRL_ADV_10G_LBN,
advertising & ADVERTISED_10000baseT_Full);
}
static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising)
{ {
int phy_id = efx->mii.phy_id; int phy_id = efx->mii.phy_id;
u32 xnp_adv = 0;
int reg;
reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
PMA_PMD_SPEED_ENABLE_REG); C22EXT_MSTSLV_CTRL,
if (EFX_WORKAROUND_13204(efx) && (reg & (1 << PMA_PMD_100TX_ADV_LBN))) C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN,
xnp_adv |= ADVERTISED_100baseT_Full; advertising & ADVERTISED_1000baseT_Full);
if (reg & (1 << PMA_PMD_1000T_ADV_LBN)) mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN,
xnp_adv |= ADVERTISED_1000baseT_Full; MDIO_AN_10GBT_CTRL,
if (reg & (1 << PMA_PMD_10000T_ADV_LBN)) MDIO_AN_10GBT_CTRL_ADV_10G_LBN,
xnp_adv |= ADVERTISED_10000baseT_Full; advertising & ADVERTISED_10000baseT_Full);
mdio_clause45_get_settings_ext(efx, ecmd, xnp_adv,
tenxpress_get_xnp_lpa(efx));
ecmd->supported |= (SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Full);
/* Use the vendor defined C22ext register for duplex settings */
if (ecmd->speed != SPEED_10000 && !ecmd->autoneg) {
reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
GPHY_XCONTROL_REG);
ecmd->duplex = (reg & (1 << GPHY_DUPLEX_LBN) ?
DUPLEX_FULL : DUPLEX_HALF);
}
}
static int sft9001_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
int phy_id = efx->mii.phy_id;
int rc;
rc = mdio_clause45_set_settings(efx, ecmd);
if (rc)
return rc;
if (ecmd->speed != SPEED_10000 && !ecmd->autoneg)
mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
GPHY_XCONTROL_REG, GPHY_DUPLEX_LBN,
ecmd->duplex == DUPLEX_FULL);
return rc;
}
static bool sft9001_set_xnp_advertise(struct efx_nic *efx, u32 advertising)
{
int phy = efx->mii.phy_id;
int reg = mdio_clause45_read(efx, phy, MDIO_MMD_PMAPMD,
PMA_PMD_SPEED_ENABLE_REG);
bool enabled;
reg &= ~((1 << 2) | (1 << 3));
if (EFX_WORKAROUND_13204(efx) &&
(advertising & ADVERTISED_100baseT_Full))
reg |= 1 << PMA_PMD_100TX_ADV_LBN;
if (advertising & ADVERTISED_1000baseT_Full)
reg |= 1 << PMA_PMD_1000T_ADV_LBN;
if (advertising & ADVERTISED_10000baseT_Full)
reg |= 1 << PMA_PMD_10000T_ADV_LBN;
mdio_clause45_write(efx, phy, MDIO_MMD_PMAPMD,
PMA_PMD_SPEED_ENABLE_REG, reg);
enabled = (advertising &
(ADVERTISED_1000baseT_Half |
ADVERTISED_1000baseT_Full |
ADVERTISED_10000baseT_Full));
if (EFX_WORKAROUND_13204(efx))
enabled |= (advertising & ADVERTISED_100baseT_Full);
return enabled;
} }
struct efx_phy_operations falcon_sfx7101_phy_ops = { struct efx_phy_operations falcon_sfx7101_phy_ops = {
@@ -883,8 +823,9 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = {
.poll = tenxpress_phy_poll, .poll = tenxpress_phy_poll,
.fini = tenxpress_phy_fini, .fini = tenxpress_phy_fini,
.clear_interrupt = efx_port_dummy_op_void, .clear_interrupt = efx_port_dummy_op_void,
.get_settings = sfx7101_get_settings, .get_settings = tenxpress_get_settings,
.set_settings = mdio_clause45_set_settings, .set_settings = tenxpress_set_settings,
.set_npage_adv = sfx7101_set_npage_adv,
.num_tests = ARRAY_SIZE(sfx7101_test_names), .num_tests = ARRAY_SIZE(sfx7101_test_names),
.test_names = sfx7101_test_names, .test_names = sfx7101_test_names,
.run_tests = sfx7101_run_tests, .run_tests = sfx7101_run_tests,
@@ -899,9 +840,9 @@ struct efx_phy_operations falcon_sft9001_phy_ops = {
.poll = tenxpress_phy_poll, .poll = tenxpress_phy_poll,
.fini = tenxpress_phy_fini, .fini = tenxpress_phy_fini,
.clear_interrupt = efx_port_dummy_op_void, .clear_interrupt = efx_port_dummy_op_void,
.get_settings = sft9001_get_settings, .get_settings = tenxpress_get_settings,
.set_settings = sft9001_set_settings, .set_settings = tenxpress_set_settings,
.set_xnp_advertise = sft9001_set_xnp_advertise, .set_npage_adv = sft9001_set_npage_adv,
.num_tests = ARRAY_SIZE(sft9001_test_names), .num_tests = ARRAY_SIZE(sft9001_test_names),
.test_names = sft9001_test_names, .test_names = sft9001_test_names,
.run_tests = sft9001_run_tests, .run_tests = sft9001_run_tests,
+5 -7
View File
@@ -18,8 +18,8 @@
#define EFX_WORKAROUND_ALWAYS(efx) 1 #define EFX_WORKAROUND_ALWAYS(efx) 1
#define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1) #define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1)
#define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx) #define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx)
#define EFX_WORKAROUND_SFX7101(efx) ((efx)->phy_type == PHY_TYPE_SFX7101) #define EFX_WORKAROUND_SFT9001(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A || \
#define EFX_WORKAROUND_SFT9001A(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A) (efx)->phy_type == PHY_TYPE_SFT9001B)
/* XAUI resets if link not detected */ /* XAUI resets if link not detected */
#define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS #define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS
@@ -29,8 +29,6 @@
#define EFX_WORKAROUND_7884 EFX_WORKAROUND_10G #define EFX_WORKAROUND_7884 EFX_WORKAROUND_10G
/* TX pkt parser problem with <= 16 byte TXes */ /* TX pkt parser problem with <= 16 byte TXes */
#define EFX_WORKAROUND_9141 EFX_WORKAROUND_ALWAYS #define EFX_WORKAROUND_9141 EFX_WORKAROUND_ALWAYS
/* Low rate CRC errors require XAUI reset */
#define EFX_WORKAROUND_10750 EFX_WORKAROUND_SFX7101
/* TX_EV_PKT_ERR can be caused by a dangling TX descriptor /* TX_EV_PKT_ERR can be caused by a dangling TX descriptor
* or a PCIe error (bug 11028) */ * or a PCIe error (bug 11028) */
#define EFX_WORKAROUND_10727 EFX_WORKAROUND_ALWAYS #define EFX_WORKAROUND_10727 EFX_WORKAROUND_ALWAYS
@@ -55,8 +53,8 @@
#define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A #define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A
/* Need to send XNP pages for 100BaseT */ /* Need to send XNP pages for 100BaseT */
#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001A #define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001
/* Need to keep AN enabled */ /* Don't restart AN in near-side loopback */
#define EFX_WORKAROUND_13963 EFX_WORKAROUND_SFT9001A #define EFX_WORKAROUND_15195 EFX_WORKAROUND_SFT9001
#endif /* EFX_WORKAROUNDS_H */ #endif /* EFX_WORKAROUNDS_H */
+2 -2
View File
@@ -1003,9 +1003,9 @@ static int skfp_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break; break;
case SKFP_CLR_STATS: /* Zero out the driver statistics */ case SKFP_CLR_STATS: /* Zero out the driver statistics */
if (!capable(CAP_NET_ADMIN)) { if (!capable(CAP_NET_ADMIN)) {
memset(&lp->MacStat, 0, sizeof(lp->MacStat));
} else {
status = -EPERM; status = -EPERM;
} else {
memset(&lp->MacStat, 0, sizeof(lp->MacStat));
} }
break; break;
default: default:

Some files were not shown because too many files have changed in this diff Show More