From 35e9e025b64fb03b8e9b08927be2c36bb69ba838 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 11 Jan 2009 18:27:10 +0000 Subject: [PATCH] --- yaml --- r: 130552 b: refs/heads/master c: 012703e0fc9fb1d6cdf778c49f45b796a85ef5bc h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/mips/kernel/mips-mt-fpaff.c | 3 +- trunk/drivers/char/selection.c | 2 +- trunk/drivers/gpu/drm/drm_gem.c | 2 +- trunk/drivers/net/igb/e1000_82575.c | 11 +- trunk/drivers/net/igb/igb.h | 9 +- trunk/drivers/net/igb/igb_main.c | 24 +-- trunk/drivers/net/sfc/efx.c | 59 +++---- trunk/drivers/net/sfc/efx.h | 9 +- trunk/drivers/net/sfc/ethtool.c | 3 + trunk/drivers/net/sfc/falcon.c | 32 ++-- trunk/drivers/net/sfc/mdio_10g.c | 191 +++++++++++----------- trunk/drivers/net/sfc/mdio_10g.h | 3 +- trunk/drivers/net/sfc/net_driver.h | 9 +- trunk/drivers/net/sfc/phy.h | 1 + trunk/drivers/net/sfc/selftest.c | 7 +- trunk/drivers/net/sfc/sfe4001.c | 42 ++--- trunk/drivers/net/sfc/tenxpress.c | 213 ++++++++++++++++--------- trunk/drivers/net/sfc/workarounds.h | 12 +- trunk/drivers/net/sky2.c | 6 +- trunk/ipc/shm.c | 4 +- trunk/mm/mmap.c | 48 +++--- trunk/mm/shmem.c | 2 +- trunk/net/ipv6/ip6mr.c | 1 - trunk/net/packet/af_packet.c | 9 +- 25 files changed, 359 insertions(+), 345 deletions(-) diff --git a/[refs] b/[refs] index be7e318c29d0..6752c77b312a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 878b8619f711280fd05845e21956434b5e588cc4 +refs/heads/master: 012703e0fc9fb1d6cdf778c49f45b796a85ef5bc diff --git a/trunk/arch/mips/kernel/mips-mt-fpaff.c b/trunk/arch/mips/kernel/mips-mt-fpaff.c index 5e77a3a21f98..42461310b185 100644 --- a/trunk/arch/mips/kernel/mips-mt-fpaff.c +++ b/trunk/arch/mips/kernel/mips-mt-fpaff.c @@ -79,7 +79,8 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len, euid = current_euid(); retval = -EPERM; - if (euid != p->euid && euid != p->uid && !capable(CAP_SYS_NICE)) { + if (euid != p->cred->euid && euid != p->cred->uid && + !capable(CAP_SYS_NICE)) { read_unlock(&tasklist_lock); goto out_unlock; } diff --git a/trunk/drivers/char/selection.c b/trunk/drivers/char/selection.c index cb8ca5698963..f29fbe9b8ed7 100644 --- a/trunk/drivers/char/selection.c +++ b/trunk/drivers/char/selection.c @@ -268,7 +268,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t /* Allocate a new buffer before freeing the old one ... */ multiplier = use_unicode ? 3 : 1; /* chars can take up to 3 bytes */ - bp = kmalloc(((sel_end-sel_start)/2+1)*multiplier, GFP_KERNEL); + bp = kmalloc((sel_end-sel_start)/2*multiplier+1, GFP_KERNEL); if (!bp) { printk(KERN_WARNING "selection: kmalloc() failed\n"); clear_selection(); diff --git a/trunk/drivers/gpu/drm/drm_gem.c b/trunk/drivers/gpu/drm/drm_gem.c index 6915fb82d0b0..9da581452874 100644 --- a/trunk/drivers/gpu/drm/drm_gem.c +++ b/trunk/drivers/gpu/drm/drm_gem.c @@ -136,7 +136,7 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size) obj = kcalloc(1, sizeof(*obj), GFP_KERNEL); obj->dev = dev; - obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE); + obj->filp = shmem_file_setup("drm mm object", size, 0); if (IS_ERR(obj->filp)) { kfree(obj); return NULL; diff --git a/trunk/drivers/net/igb/e1000_82575.c b/trunk/drivers/net/igb/e1000_82575.c index 13ca73f96ec6..f5e2e7235fcb 100644 --- a/trunk/drivers/net/igb/e1000_82575.c +++ b/trunk/drivers/net/igb/e1000_82575.c @@ -699,18 +699,11 @@ static s32 igb_check_for_link_82575(struct e1000_hw *hw) /* SGMII link check is done through the PCS register. */ if ((hw->phy.media_type != e1000_media_type_copper) || - (igb_sgmii_active_82575(hw))) { + (igb_sgmii_active_82575(hw))) ret_val = igb_get_pcs_speed_and_duplex_82575(hw, &speed, &duplex); - /* - * Use this flag to determine if link needs to be checked or - * not. If we have link clear the flag so that we do not - * continue to check for link. - */ - hw->mac.get_link_status = !hw->mac.serdes_has_link; - } else { + else ret_val = igb_check_for_copper_link(hw); - } return ret_val; } diff --git a/trunk/drivers/net/igb/igb.h b/trunk/drivers/net/igb/igb.h index aebef8e48e76..5a27825cc48a 100644 --- a/trunk/drivers/net/igb/igb.h +++ b/trunk/drivers/net/igb/igb.h @@ -300,10 +300,11 @@ struct igb_adapter { #define IGB_FLAG_HAS_MSI (1 << 0) #define IGB_FLAG_MSI_ENABLE (1 << 1) -#define IGB_FLAG_DCA_ENABLED (1 << 2) -#define IGB_FLAG_IN_NETPOLL (1 << 3) -#define IGB_FLAG_QUAD_PORT_A (1 << 4) -#define IGB_FLAG_NEED_CTX_IDX (1 << 5) +#define IGB_FLAG_HAS_DCA (1 << 2) +#define IGB_FLAG_DCA_ENABLED (1 << 3) +#define IGB_FLAG_IN_NETPOLL (1 << 5) +#define IGB_FLAG_QUAD_PORT_A (1 << 6) +#define IGB_FLAG_NEED_CTX_IDX (1 << 7) enum e1000_state_t { __IGB_TESTING, diff --git a/trunk/drivers/net/igb/igb_main.c b/trunk/drivers/net/igb/igb_main.c index a50db5398fa5..b82b0fb2056c 100644 --- a/trunk/drivers/net/igb/igb_main.c +++ b/trunk/drivers/net/igb/igb_main.c @@ -206,11 +206,10 @@ static int __init igb_init_module(void) global_quad_port_a = 0; + ret = pci_register_driver(&igb_driver); #ifdef CONFIG_IGB_DCA dca_register_notify(&dca_notifier); #endif - - ret = pci_register_driver(&igb_driver); return ret; } @@ -1157,10 +1156,11 @@ static int __devinit igb_probe(struct pci_dev *pdev, /* set flags */ switch (hw->mac.type) { + case e1000_82576: case e1000_82575: + adapter->flags |= IGB_FLAG_HAS_DCA; adapter->flags |= IGB_FLAG_NEED_CTX_IDX; break; - case e1000_82576: default: break; } @@ -1310,7 +1310,8 @@ static int __devinit igb_probe(struct pci_dev *pdev, goto err_register; #ifdef CONFIG_IGB_DCA - if (dca_add_requester(&pdev->dev) == 0) { + if ((adapter->flags & IGB_FLAG_HAS_DCA) && + (dca_add_requester(&pdev->dev) == 0)) { adapter->flags |= IGB_FLAG_DCA_ENABLED; dev_info(&pdev->dev, "DCA enabled\n"); /* Always use CB2 mode, difference is masked @@ -1834,11 +1835,11 @@ static void igb_setup_rctl(struct igb_adapter *adapter) rctl |= E1000_RCTL_SECRC; /* - * disable store bad packets and clear size bits. + * disable store bad packets, long packet enable, and clear size bits. */ - rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_SZ_256); + rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_LPE | E1000_RCTL_SZ_256); - /* enable LPE when to prevent packets larger than max_frame_size */ + if (adapter->netdev->mtu > ETH_DATA_LEN) rctl |= E1000_RCTL_LPE; /* Setup buffer sizes */ @@ -1864,7 +1865,7 @@ static void igb_setup_rctl(struct igb_adapter *adapter) */ /* allocations using alloc_page take too long for regular MTU * so only enable packet split for jumbo frames */ - if (adapter->netdev->mtu > ETH_DATA_LEN) { + if (rctl & E1000_RCTL_LPE) { adapter->rx_ps_hdr_size = IGB_RXBUFFER_128; srrctl |= adapter->rx_ps_hdr_size << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT; @@ -3472,16 +3473,19 @@ static int __igb_notify_dca(struct device *dev, void *data) struct e1000_hw *hw = &adapter->hw; unsigned long event = *(unsigned long *)data; + if (!(adapter->flags & IGB_FLAG_HAS_DCA)) + goto out; + switch (event) { case DCA_PROVIDER_ADD: /* if already enabled, don't do it again */ if (adapter->flags & IGB_FLAG_DCA_ENABLED) break; + adapter->flags |= IGB_FLAG_DCA_ENABLED; /* Always use CB2 mode, difference is masked * in the CB driver. */ wr32(E1000_DCA_CTRL, 2); if (dca_add_requester(dev) == 0) { - adapter->flags |= IGB_FLAG_DCA_ENABLED; dev_info(&adapter->pdev->dev, "DCA enabled\n"); igb_setup_dca(adapter); break; @@ -3498,7 +3502,7 @@ static int __igb_notify_dca(struct device *dev, void *data) } break; } - +out: return 0; } diff --git a/trunk/drivers/net/sfc/efx.c b/trunk/drivers/net/sfc/efx.c index ab0e09bf154d..7673fd92eaf5 100644 --- a/trunk/drivers/net/sfc/efx.c +++ b/trunk/drivers/net/sfc/efx.c @@ -676,8 +676,9 @@ static int efx_init_port(struct efx_nic *efx) rc = efx->phy_op->init(efx); if (rc) return rc; - mutex_lock(&efx->mac_lock); efx->phy_op->reconfigure(efx); + + mutex_lock(&efx->mac_lock); rc = falcon_switch_mac(efx); mutex_unlock(&efx->mac_lock); if (rc) @@ -685,7 +686,7 @@ static int efx_init_port(struct efx_nic *efx) efx->mac_op->reconfigure(efx); efx->port_initialized = true; - efx_stats_enable(efx); + efx->stats_enabled = true; return 0; fail: @@ -734,7 +735,6 @@ static void efx_fini_port(struct efx_nic *efx) if (!efx->port_initialized) return; - efx_stats_disable(efx); efx->phy_op->fini(efx); efx->port_initialized = false; @@ -1361,20 +1361,6 @@ static int efx_net_stop(struct net_device *net_dev) 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. */ static struct net_device_stats *efx_net_stats(struct net_device *net_dev) { @@ -1383,12 +1369,12 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev) struct net_device_stats *stats = &net_dev->stats; /* Update stats if possible, but do not wait if another thread - * is updating them or if MAC stats fetches are temporarily - * disabled; slightly stale stats are acceptable. + * is updating them (or resetting the NIC); slightly stale + * stats are acceptable. */ if (!spin_trylock(&efx->stats_lock)) return stats; - if (!efx->stats_disable_count) { + if (efx->stats_enabled) { efx->mac_op->update_stats(efx); falcon_update_nic_stats(efx); } @@ -1636,12 +1622,16 @@ static void efx_unregister_netdev(struct efx_nic *efx) /* Tears down the entire software state and most of the hardware state * before reset. */ -void efx_reset_down(struct efx_nic *efx, enum reset_type method, - struct ethtool_cmd *ecmd) +void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd) { EFX_ASSERT_RESET_SERIALISED(efx); - efx_stats_disable(efx); + /* The net_dev->get_stats handler is quite slow, and will fail + * 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); mutex_lock(&efx->mac_lock); mutex_lock(&efx->spi_lock); @@ -1649,8 +1639,6 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method, efx->phy_op->get_settings(efx, ecmd); 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 @@ -1658,8 +1646,7 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method, * that we were unable to reinitialise the hardware, and the * driver should be disabled. If ok is false, then the rx and tx * engines are not restarted, pending a RESET_DISABLE. */ -int efx_reset_up(struct efx_nic *efx, enum reset_type method, - struct ethtool_cmd *ecmd, bool ok) +int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok) { int rc; @@ -1671,15 +1658,6 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, 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) { efx_init_channels(efx); @@ -1692,7 +1670,7 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, if (ok) { efx_start_all(efx); - efx_stats_enable(efx); + efx->stats_enabled = true; } return rc; } @@ -1724,7 +1702,7 @@ static int efx_reset(struct efx_nic *efx) EFX_INFO(efx, "resetting (%d)\n", method); - efx_reset_down(efx, method, &ecmd); + efx_reset_down(efx, &ecmd); rc = falcon_reset_hw(efx, method); if (rc) { @@ -1743,10 +1721,10 @@ static int efx_reset(struct efx_nic *efx) /* Leave device stopped if necessary */ if (method == RESET_TYPE_DISABLE) { - efx_reset_up(efx, method, &ecmd, false); + efx_reset_up(efx, &ecmd, false); rc = -EIO; } else { - rc = efx_reset_up(efx, method, &ecmd, true); + rc = efx_reset_up(efx, &ecmd, true); } out_disable: @@ -1898,7 +1876,6 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, efx->rx_checksum_enabled = true; spin_lock_init(&efx->netif_stop_lock); spin_lock_init(&efx->stats_lock); - efx->stats_disable_count = 1; mutex_init(&efx->mac_lock); efx->mac_op = &efx_dummy_mac_operations; efx->phy_op = &efx_dummy_phy_operations; diff --git a/trunk/drivers/net/sfc/efx.h b/trunk/drivers/net/sfc/efx.h index 55d0f131b0e9..0dd7a532c78a 100644 --- a/trunk/drivers/net/sfc/efx.h +++ b/trunk/drivers/net/sfc/efx.h @@ -36,16 +36,13 @@ extern void efx_process_channel_now(struct efx_channel *channel); extern void efx_flush_queues(struct efx_nic *efx); /* 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); /* Reset handling */ -extern void efx_reset_down(struct efx_nic *efx, enum reset_type method, - struct ethtool_cmd *ecmd); -extern int efx_reset_up(struct efx_nic *efx, enum reset_type method, - struct ethtool_cmd *ecmd, bool ok); +extern void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd); +extern int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, + bool ok); /* Global */ extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type); diff --git a/trunk/drivers/net/sfc/ethtool.c b/trunk/drivers/net/sfc/ethtool.c index 7b5924c039b3..53d259e90187 100644 --- a/trunk/drivers/net/sfc/ethtool.c +++ b/trunk/drivers/net/sfc/ethtool.c @@ -219,6 +219,9 @@ int efx_ethtool_set_settings(struct net_device *net_dev, struct efx_nic *efx = netdev_priv(net_dev); int rc; + if (EFX_WORKAROUND_13963(efx) && !ecmd->autoneg) + return -EINVAL; + /* Falcon GMAC does not support 1000Mbps HD */ if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) { EFX_LOG(efx, "rejecting unsupported 1000Mbps HD" diff --git a/trunk/drivers/net/sfc/falcon.c b/trunk/drivers/net/sfc/falcon.c index d5378e60fcdd..5b9f2d9cc4ed 100644 --- a/trunk/drivers/net/sfc/falcon.c +++ b/trunk/drivers/net/sfc/falcon.c @@ -824,6 +824,10 @@ static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue, rx_ev_pause_frm ? " [PAUSE]" : ""); } #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. */ @@ -1883,7 +1887,7 @@ static int falcon_reset_macs(struct efx_nic *efx) /* MAC stats will fail whilst the TX fifo is draining. Serialise * the drain sequence with the statistics fetch */ - efx_stats_disable(efx); + spin_lock(&efx->stats_lock); falcon_read(efx, ®, MAC0_CTRL_REG_KER); EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0, 1); @@ -1913,7 +1917,7 @@ static int falcon_reset_macs(struct efx_nic *efx) udelay(10); } - efx_stats_enable(efx); + spin_unlock(&efx->stats_lock); /* 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 */ @@ -2273,10 +2277,6 @@ int falcon_switch_mac(struct efx_nic *efx) struct efx_mac_operations *old_mac_op = efx->mac_op; efx_oword_t nic_stat; 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 */ if (efx->loopback_mode == LOOPBACK_GMAC) { @@ -2287,12 +2287,16 @@ int falcon_switch_mac(struct efx_nic *efx) efx->link_fd = true; } - WARN_ON(!mutex_is_locked(&efx->mac_lock)); efx->mac_op = (EFX_IS10G(efx) ? &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); strap_val = EFX_IS10G(efx) ? 5 : 3; if (falcon_rev(efx) >= FALCON_REV_B0) { @@ -2305,17 +2309,9 @@ int falcon_switch_mac(struct efx_nic *efx) 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'); - /* 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; + return falcon_reset_macs(efx); } /* This call is responsible for hooking in the MAC and PHY operations */ diff --git a/trunk/drivers/net/sfc/mdio_10g.c b/trunk/drivers/net/sfc/mdio_10g.c index f9e2f95c3b48..f6a16428113d 100644 --- a/trunk/drivers/net/sfc/mdio_10g.c +++ b/trunk/drivers/net/sfc/mdio_10g.c @@ -15,7 +15,6 @@ #include "net_driver.h" #include "mdio_10g.h" #include "boards.h" -#include "workarounds.h" int mdio_clause45_reset_mmd(struct efx_nic *port, int mmd, int spins, int spintime) @@ -180,12 +179,17 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask) return false; else if (efx_phy_mode_disabled(efx->phy_mode)) return false; - else if (efx->loopback_mode == LOOPBACK_PHYXS) + else if (efx->loopback_mode == LOOPBACK_PHYXS) { mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS | MDIO_MMDREG_DEVS_PCS | MDIO_MMDREG_DEVS_PMAPMD | MDIO_MMDREG_DEVS_AN); - else if (efx->loopback_mode == LOOPBACK_PCS) + if (!mmd_mask) { + 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 | MDIO_MMDREG_DEVS_PMAPMD | MDIO_MMDREG_DEVS_AN); @@ -193,13 +197,6 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask) mmd_mask &= ~(MDIO_MMDREG_DEVS_PMAPMD | 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) { if (mmd_mask & 1) { /* Double reads because link state is latched, and a @@ -266,7 +263,7 @@ void mdio_clause45_set_mmds_lpower(struct efx_nic *efx, } } -static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr) +static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr, u32 xnp) { int phy_id = efx->mii.phy_id; u32 result = 0; @@ -281,6 +278,9 @@ static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr) result |= ADVERTISED_100baseT_Half; if (reg & ADVERTISE_100FULL) result |= ADVERTISED_100baseT_Full; + if (reg & LPA_RESV) + result |= xnp; + 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, struct ethtool_cmd *ecmd, - u32 npage_adv, u32 npage_lpa) + u32 xnp, u32 xnp_lpa) { int phy_id = efx->mii.phy_id; int reg; @@ -361,8 +361,8 @@ void mdio_clause45_get_settings_ext(struct efx_nic *efx, ecmd->autoneg = AUTONEG_ENABLE; ecmd->advertising |= ADVERTISED_Autoneg | - mdio_clause45_get_an(efx, MDIO_AN_ADVERTISE) | - npage_adv; + mdio_clause45_get_an(efx, + MDIO_AN_ADVERTISE, xnp); } else ecmd->autoneg = AUTONEG_DISABLE; } else @@ -371,30 +371,27 @@ void mdio_clause45_get_settings_ext(struct efx_nic *efx, if (ecmd->autoneg) { /* If AN is complete, report best common mode, * otherwise report best advertised mode. */ - u32 modes = 0; + u32 common = ecmd->advertising; if (mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, MDIO_MMDREG_STAT1) & - (1 << MDIO_AN_STATUS_AN_DONE_LBN)) - modes = (ecmd->advertising & - (mdio_clause45_get_an(efx, MDIO_AN_LPA) | - npage_lpa)); - if (modes == 0) - modes = ecmd->advertising; - - if (modes & ADVERTISED_10000baseT_Full) { + (1 << MDIO_AN_STATUS_AN_DONE_LBN)) { + common &= mdio_clause45_get_an(efx, MDIO_AN_LPA, + xnp_lpa); + } + if (common & ADVERTISED_10000baseT_Full) { ecmd->speed = SPEED_10000; ecmd->duplex = DUPLEX_FULL; - } else if (modes & (ADVERTISED_1000baseT_Full | - ADVERTISED_1000baseT_Half)) { + } else if (common & (ADVERTISED_1000baseT_Full | + ADVERTISED_1000baseT_Half)) { ecmd->speed = SPEED_1000; - ecmd->duplex = !!(modes & ADVERTISED_1000baseT_Full); - } else if (modes & (ADVERTISED_100baseT_Full | - ADVERTISED_100baseT_Half)) { + ecmd->duplex = !!(common & ADVERTISED_1000baseT_Full); + } else if (common & (ADVERTISED_100baseT_Full | + ADVERTISED_100baseT_Half)) { ecmd->speed = SPEED_100; - ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full); + ecmd->duplex = !!(common & ADVERTISED_100baseT_Full); } else { ecmd->speed = SPEED_10; - ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full); + ecmd->duplex = !!(common & ADVERTISED_10baseT_Full); } } else { /* Report forced settings */ @@ -418,7 +415,7 @@ int mdio_clause45_set_settings(struct efx_nic *efx, int phy_id = efx->mii.phy_id; struct ethtool_cmd prev; u32 required; - int reg; + int ctrl1_bits, reg; efx->phy_op->get_settings(efx, &prev); @@ -433,83 +430,99 @@ int mdio_clause45_set_settings(struct efx_nic *efx, if (prev.port != PORT_TP || ecmd->port != PORT_TP) return -EINVAL; - /* Check that PHY supports these settings */ - if (ecmd->autoneg) { - required = SUPPORTED_Autoneg; - } else if (ecmd->duplex) { + /* Check that PHY supports these settings and work out the + * basic control bits */ + if (ecmd->duplex) { switch (ecmd->speed) { - case SPEED_10: required = SUPPORTED_10baseT_Full; break; - case SPEED_100: required = SUPPORTED_100baseT_Full; break; - default: return -EINVAL; + case SPEED_10: + ctrl1_bits = BMCR_FULLDPLX; + required = SUPPORTED_10baseT_Full; + 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 { switch (ecmd->speed) { - case SPEED_10: required = SUPPORTED_10baseT_Half; break; - case SPEED_100: required = SUPPORTED_100baseT_Half; break; - default: return -EINVAL; + case SPEED_10: + ctrl1_bits = 0; + required = SUPPORTED_10baseT_Half; + 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; if (required & ~prev.supported) return -EINVAL; - if (ecmd->autoneg) { - bool xnp = (ecmd->advertising & ADVERTISED_10000baseT_Full - || EFX_WORKAROUND_13204(efx)); - - /* Set up the base page */ - reg = ADVERTISE_CSMA; - 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; - 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); - - /* Set up the (extended) next page if necessary */ - if (efx->phy_op->set_npage_adv) - efx->phy_op->set_npage_adv(efx, ecmd->advertising); + /* 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); + reg |= ctrl1_bits; + mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, MDIO_MMDREG_CTRL1, + reg); + + /* Set the AN registers */ + if (ecmd->autoneg != prev.autoneg || + ecmd->advertising != prev.advertising) { + bool xnp = false; + + if (efx->phy_op->set_xnp_advertise) + xnp = efx->phy_op->set_xnp_advertise(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, MDIO_MMDREG_CTRL1); - reg |= BMCR_ANENABLE; - if (!(EFX_WORKAROUND_15195(efx) && - LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)) - reg |= BMCR_ANRESTART; + if (ecmd->autoneg) + reg |= BMCR_ANENABLE | BMCR_ANRESTART; + else + reg &= ~BMCR_ANENABLE; if (xnp) reg |= 1 << MDIO_AN_CTRL_XNP_LBN; else reg &= ~(1 << MDIO_AN_CTRL_XNP_LBN); mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, 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; diff --git a/trunk/drivers/net/sfc/mdio_10g.h b/trunk/drivers/net/sfc/mdio_10g.h index 8ba49773ce7e..09bf801d0569 100644 --- a/trunk/drivers/net/sfc/mdio_10g.h +++ b/trunk/drivers/net/sfc/mdio_10g.h @@ -155,8 +155,7 @@ #define MDIO_AN_XNP 22 #define MDIO_AN_LPA_XNP 25 -#define MDIO_AN_10GBT_CTRL 32 -#define MDIO_AN_10GBT_CTRL_ADV_10G_LBN 12 +#define MDIO_AN_10GBT_ADVERTISE 32 #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_LBN (14) /* MASTER/SLAVE config */ diff --git a/trunk/drivers/net/sfc/net_driver.h b/trunk/drivers/net/sfc/net_driver.h index e019ad1fb9a0..5f255f75754e 100644 --- a/trunk/drivers/net/sfc/net_driver.h +++ b/trunk/drivers/net/sfc/net_driver.h @@ -566,7 +566,7 @@ struct efx_mac_operations { * @poll: Poll for hardware state. 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_npage_adv: Set abilities advertised in (Extended) Next Page + * @set_xnp_advertise: Set abilities advertised in Extended Next Page * (only needed where AN bit is set in mmds) * @num_tests: Number of PHY-specific tests/results * @test_names: Names of the tests/results @@ -586,7 +586,7 @@ struct efx_phy_operations { struct ethtool_cmd *ecmd); int (*set_settings) (struct efx_nic *efx, struct ethtool_cmd *ecmd); - void (*set_npage_adv) (struct efx_nic *efx, u32); + bool (*set_xnp_advertise) (struct efx_nic *efx, u32); u32 num_tests; const char *const *test_names; int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags); @@ -754,7 +754,8 @@ union efx_multicast_hash { * &struct net_device_stats. * @stats_buffer: DMA buffer for statistics * @stats_lock: Statistics update lock. Serialises statistics fetches - * @stats_disable_count: Nest count for disabling statistics fetches + * @stats_enabled: Temporarily disable statistics fetches. + * Serialised by @stats_lock * @mac_op: MAC interface * @mac_address: Permanent MAC address * @phy_type: PHY type @@ -836,7 +837,7 @@ struct efx_nic { struct efx_mac_stats mac_stats; struct efx_buffer stats_buffer; spinlock_t stats_lock; - unsigned int stats_disable_count; + bool stats_enabled; struct efx_mac_operations *mac_op; unsigned char mac_address[ETH_ALEN]; diff --git a/trunk/drivers/net/sfc/phy.h b/trunk/drivers/net/sfc/phy.h index 07e855c148bc..58c493ef81bb 100644 --- a/trunk/drivers/net/sfc/phy.h +++ b/trunk/drivers/net/sfc/phy.h @@ -17,6 +17,7 @@ extern struct efx_phy_operations falcon_sfx7101_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_crc_err(struct efx_nic *efx); /**************************************************************************** * Exported functions from the driver for XFP optical PHYs diff --git a/trunk/drivers/net/sfc/selftest.c b/trunk/drivers/net/sfc/selftest.c index 0a598084c513..dba0d64d50cd 100644 --- a/trunk/drivers/net/sfc/selftest.c +++ b/trunk/drivers/net/sfc/selftest.c @@ -665,7 +665,6 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, { enum efx_loopback_mode loopback_mode = efx->loopback_mode; int phy_mode = efx->phy_mode; - enum reset_type reset_method = RESET_TYPE_INVISIBLE; struct ethtool_cmd ecmd; struct efx_channel *channel; int rc_test = 0, rc_reset = 0, rc; @@ -719,21 +718,21 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, mutex_unlock(&efx->mac_lock); /* free up all consumers of SRAM (including all the queues) */ - efx_reset_down(efx, reset_method, &ecmd); + efx_reset_down(efx, &ecmd); rc = efx_test_chip(efx, tests); if (rc && !rc_test) rc_test = rc; /* reset the chip to recover from the register test */ - rc_reset = falcon_reset_hw(efx, reset_method); + rc_reset = falcon_reset_hw(efx, RESET_TYPE_ALL); /* Ensure that the phy is powered and out of loopback * for the bist and loopback tests */ efx->phy_mode &= ~PHY_MODE_LOW_POWER; efx->loopback_mode = LOOPBACK_NONE; - rc = efx_reset_up(efx, reset_method, &ecmd, rc_reset == 0); + rc = efx_reset_up(efx, &ecmd, rc_reset == 0); if (rc && !rc_reset) rc_reset = rc; diff --git a/trunk/drivers/net/sfc/sfe4001.c b/trunk/drivers/net/sfc/sfe4001.c index cb25ae5b257a..16b80acb9992 100644 --- a/trunk/drivers/net/sfc/sfe4001.c +++ b/trunk/drivers/net/sfc/sfe4001.c @@ -186,22 +186,19 @@ static int sfn4111t_reset(struct efx_nic *efx) { efx_oword_t reg; - /* GPIO 3 and the GPIO register are shared with I2C, so block that */ + /* GPIO pins are also used for I2C, so block that temporarily */ 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, ®, GPIO_CTL_REG_KER); EFX_SET_OWORD_FIELD(reg, GPIO2_OEN, true); + EFX_SET_OWORD_FIELD(reg, GPIO2_OUT, false); falcon_write(efx, ®, GPIO_CTL_REG_KER); msleep(1000); - EFX_SET_OWORD_FIELD(reg, GPIO2_OEN, false); - EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, - !!(efx->phy_mode & PHY_MODE_SPECIAL)); + EFX_SET_OWORD_FIELD(reg, GPIO2_OUT, true); + EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, true); + EFX_SET_OWORD_FIELD(reg, GPIO3_OUT, + !(efx->phy_mode & PHY_MODE_SPECIAL)); falcon_write(efx, ®, GPIO_CTL_REG_KER); - msleep(1); mutex_unlock(&efx->i2c_adap.bus_lock); @@ -235,18 +232,12 @@ static ssize_t set_phy_flash_cfg(struct device *dev, } else if (efx->state != STATE_RUNNING || netif_running(efx->net_dev)) { err = -EBUSY; } else { - /* Reset the PHY, reconfigure the MAC and enable/disable - * MAC stats accordingly. */ efx->phy_mode = new_mode; - if (new_mode & PHY_MODE_SPECIAL) - efx_stats_disable(efx); if (efx->board_info.type == EFX_BOARD_SFE4001) err = sfe4001_poweron(efx); else err = sfn4111t_reset(efx); efx_reconfigure_port(efx); - if (!(new_mode & PHY_MODE_SPECIAL)) - efx_stats_enable(efx); } rtnl_unlock(); @@ -335,11 +326,6 @@ int sfe4001_init(struct efx_nic *efx) efx->board_info.monitor = sfe4001_check_hw; 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); if (rc) goto fail_ioexp; @@ -386,25 +372,17 @@ static void sfn4111t_fini(struct efx_nic *efx) i2c_unregister_device(efx->board_info.hwmon_client); } -static struct i2c_board_info sfn4111t_a0_hwmon_info = { +static struct i2c_board_info sfn4111t_hwmon_info = { I2C_BOARD_INFO("max6647", 0x4e), .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 rc; efx->board_info.hwmon_client = - i2c_new_device(&efx->i2c_adap, - (efx->board_info.minor < 5) ? - &sfn4111t_a0_hwmon_info : - &sfn4111t_r5_hwmon_info); + i2c_new_device(&efx->i2c_adap, &sfn4111t_hwmon_info); if (!efx->board_info.hwmon_client) return -EIO; @@ -416,10 +394,8 @@ int sfn4111t_init(struct efx_nic *efx) if (rc) goto fail_hwmon; - if (efx->phy_mode & PHY_MODE_SPECIAL) { - efx_stats_disable(efx); + if (efx->phy_mode & PHY_MODE_SPECIAL) sfn4111t_reset(efx); - } return 0; diff --git a/trunk/drivers/net/sfc/tenxpress.c b/trunk/drivers/net/sfc/tenxpress.c index f0efd246962c..9ecb77da9545 100644 --- a/trunk/drivers/net/sfc/tenxpress.c +++ b/trunk/drivers/net/sfc/tenxpress.c @@ -67,8 +67,6 @@ #define PMA_PMD_EXT_CLK312_WIDTH 1 #define PMA_PMD_EXT_LPOWER_LBN 12 #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_WIDTH 1 @@ -179,24 +177,35 @@ #define C22EXT_STATUS_LINK_LBN 2 #define C22EXT_STATUS_LINK_WIDTH 1 -#define C22EXT_MSTSLV_CTRL 49161 -#define C22EXT_MSTSLV_CTRL_ADV_1000_HD_LBN 8 -#define C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN 9 - -#define C22EXT_MSTSLV_STATUS 49162 -#define C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN 10 -#define C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN 11 +#define C22EXT_MSTSLV_REG 49162 +#define C22EXT_MSTSLV_1000_HD_LBN 10 +#define C22EXT_MSTSLV_1000_HD_WIDTH 1 +#define C22EXT_MSTSLV_1000_FD_LBN 11 +#define C22EXT_MSTSLV_1000_FD_WIDTH 1 /* Time to wait between powering down the LNPGA and turning off the power * rails */ #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 { enum efx_loopback_mode loopback_mode; + atomic_t bad_crc_count; enum efx_phy_mode phy_mode; 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, struct device_attribute *attr, char *buf) { @@ -275,9 +284,7 @@ static int tenxpress_init(struct efx_nic *efx) PMA_PMD_XCONTROL_REG); reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) | (1 << PMA_PMD_EXT_CLK_OUT_LBN) | - (1 << PMA_PMD_EXT_CLK312_LBN) | - (1 << PMA_PMD_EXT_ROBUST_LBN)); - + (1 << PMA_PMD_EXT_CLK312_LBN)); mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, @@ -339,7 +346,6 @@ static int tenxpress_phy_init(struct efx_nic *efx) rc = tenxpress_init(efx); if (rc < 0) goto fail; - mdio_clause45_set_pause(efx); if (efx->phy_type == PHY_TYPE_SFT9001B) { rc = device_create_file(&efx->pci_dev->dev, @@ -370,8 +376,8 @@ static int tenxpress_special_reset(struct efx_nic *efx) /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so * a special software reset can glitch the XGMAC sufficiently for stats - * requests to fail. */ - efx_stats_disable(efx); + * requests to fail. Since we don't often special_reset, just lock. */ + spin_lock(&efx->stats_lock); /* Initiate reset */ reg = mdio_clause45_read(efx, efx->mii.phy_id, @@ -386,17 +392,17 @@ static int tenxpress_special_reset(struct efx_nic *efx) rc = mdio_clause45_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); if (rc < 0) - goto out; + goto unlock; /* Try and reconfigure the device */ rc = tenxpress_init(efx); if (rc < 0) - goto out; + goto unlock; /* Wait for the XGXS state machine to churn */ mdelay(10); -out: - efx_stats_enable(efx); +unlock: + spin_unlock(&efx->stats_lock); return rc; } @@ -514,7 +520,7 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx) { struct tenxpress_phy_data *phy_data = efx->phy_data; struct ethtool_cmd ecmd; - bool phy_mode_change, loop_reset; + bool phy_mode_change, loop_reset, loop_toggle, loopback; if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) { phy_data->phy_mode = efx->phy_mode; @@ -525,10 +531,12 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx) phy_mode_change = (efx->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) || LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY)); - if (loop_reset || phy_mode_change) { + if (loop_reset || loop_toggle || loopback || phy_mode_change) { int rc; efx->phy_op->get_settings(efx, &ecmd); @@ -543,6 +551,20 @@ static void tenxpress_phy_reconfigure(struct efx_nic *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); WARN_ON(rc); } @@ -601,6 +623,13 @@ static void tenxpress_phy_poll(struct efx_nic *efx) if (phy_data->phy_mode != PHY_MODE_NORMAL) 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) @@ -743,76 +772,107 @@ static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags) return rc; } -static void -tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) +static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx) { - int phy_id = efx->mii.phy_id; - u32 adv = 0, lpa = 0; + int phy = efx->mii.phy_id; + u32 lpa = 0; int reg; if (efx->phy_type != PHY_TYPE_SFX7101) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, - C22EXT_MSTSLV_CTRL); - 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)) + reg = mdio_clause45_read(efx, phy, MDIO_MMD_C22EXT, + C22EXT_MSTSLV_REG); + if (reg & (1 << C22EXT_MSTSLV_1000_HD_LBN)) lpa |= ADVERTISED_1000baseT_Half; - if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN)) + if (reg & (1 << C22EXT_MSTSLV_1000_FD_LBN)) lpa |= ADVERTISED_1000baseT_Full; } - 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); + reg = mdio_clause45_read(efx, phy, MDIO_MMD_AN, MDIO_AN_10GBT_STATUS); if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN)) lpa |= ADVERTISED_10000baseT_Full; - - 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; + return lpa; } -static int tenxpress_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) +static void sfx7101_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { - if (!ecmd->autoneg) - return -EINVAL; - - return mdio_clause45_set_settings(efx, ecmd); + mdio_clause45_get_settings_ext(efx, ecmd, ADVERTISED_10000baseT_Full, + tenxpress_get_xnp_lpa(efx)); + ecmd->supported |= SUPPORTED_10000baseT_Full; + ecmd->advertising |= ADVERTISED_10000baseT_Full; } -static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising) +static void sft9001_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { - 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); + int phy_id = efx->mii.phy_id; + u32 xnp_adv = 0; + int reg; + + reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, + PMA_PMD_SPEED_ENABLE_REG); + if (EFX_WORKAROUND_13204(efx) && (reg & (1 << PMA_PMD_100TX_ADV_LBN))) + xnp_adv |= ADVERTISED_100baseT_Full; + if (reg & (1 << PMA_PMD_1000T_ADV_LBN)) + xnp_adv |= ADVERTISED_1000baseT_Full; + if (reg & (1 << PMA_PMD_10000T_ADV_LBN)) + xnp_adv |= 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 void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising) +static int sft9001_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { int phy_id = efx->mii.phy_id; + int rc; - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, - C22EXT_MSTSLV_CTRL, - C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN, - advertising & ADVERTISED_1000baseT_Full); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_10GBT_CTRL, - MDIO_AN_10GBT_CTRL_ADV_10G_LBN, - advertising & ADVERTISED_10000baseT_Full); + 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 = { @@ -822,9 +882,8 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = { .poll = tenxpress_phy_poll, .fini = tenxpress_phy_fini, .clear_interrupt = efx_port_dummy_op_void, - .get_settings = tenxpress_get_settings, - .set_settings = tenxpress_set_settings, - .set_npage_adv = sfx7101_set_npage_adv, + .get_settings = sfx7101_get_settings, + .set_settings = mdio_clause45_set_settings, .num_tests = ARRAY_SIZE(sfx7101_test_names), .test_names = sfx7101_test_names, .run_tests = sfx7101_run_tests, @@ -839,9 +898,9 @@ struct efx_phy_operations falcon_sft9001_phy_ops = { .poll = tenxpress_phy_poll, .fini = tenxpress_phy_fini, .clear_interrupt = efx_port_dummy_op_void, - .get_settings = tenxpress_get_settings, - .set_settings = tenxpress_set_settings, - .set_npage_adv = sft9001_set_npage_adv, + .get_settings = sft9001_get_settings, + .set_settings = sft9001_set_settings, + .set_xnp_advertise = sft9001_set_xnp_advertise, .num_tests = ARRAY_SIZE(sft9001_test_names), .test_names = sft9001_test_names, .run_tests = sft9001_run_tests, diff --git a/trunk/drivers/net/sfc/workarounds.h b/trunk/drivers/net/sfc/workarounds.h index 78de68f4a95b..82e03e1d7371 100644 --- a/trunk/drivers/net/sfc/workarounds.h +++ b/trunk/drivers/net/sfc/workarounds.h @@ -18,8 +18,8 @@ #define EFX_WORKAROUND_ALWAYS(efx) 1 #define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1) #define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx) -#define EFX_WORKAROUND_SFT9001(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A || \ - (efx)->phy_type == PHY_TYPE_SFT9001B) +#define EFX_WORKAROUND_SFX7101(efx) ((efx)->phy_type == PHY_TYPE_SFX7101) +#define EFX_WORKAROUND_SFT9001A(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A) /* XAUI resets if link not detected */ #define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS @@ -29,6 +29,8 @@ #define EFX_WORKAROUND_7884 EFX_WORKAROUND_10G /* TX pkt parser problem with <= 16 byte TXes */ #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 * or a PCIe error (bug 11028) */ #define EFX_WORKAROUND_10727 EFX_WORKAROUND_ALWAYS @@ -53,8 +55,8 @@ #define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A /* Need to send XNP pages for 100BaseT */ -#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001 -/* Don't restart AN in near-side loopback */ -#define EFX_WORKAROUND_15195 EFX_WORKAROUND_SFT9001 +#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001A +/* Need to keep AN enabled */ +#define EFX_WORKAROUND_13963 EFX_WORKAROUND_SFT9001A #endif /* EFX_WORKAROUNDS_H */ diff --git a/trunk/drivers/net/sky2.c b/trunk/drivers/net/sky2.c index 994703cc0db3..3668e81e474d 100644 --- a/trunk/drivers/net/sky2.c +++ b/trunk/drivers/net/sky2.c @@ -1403,6 +1403,9 @@ static int sky2_up(struct net_device *dev) } + if (netif_msg_ifup(sky2)) + printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); + netif_carrier_off(dev); /* must be power of 2 */ @@ -1481,9 +1484,6 @@ static int sky2_up(struct net_device *dev) sky2_write32(hw, B0_IMSK, imask); sky2_set_multicast(dev); - - if (netif_msg_ifup(sky2)) - printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); return 0; err_out: diff --git a/trunk/ipc/shm.c b/trunk/ipc/shm.c index c0a021f7f41a..a9e09ad2263e 100644 --- a/trunk/ipc/shm.c +++ b/trunk/ipc/shm.c @@ -368,14 +368,14 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) file = hugetlb_file_setup(name, size); shp->mlock_user = current_user(); } else { - int acctflag = 0; + int acctflag = VM_ACCOUNT; /* * Do not allow no accounting for OVERCOMMIT_NEVER, even * if it's asked for. */ if ((shmflg & SHM_NORESERVE) && sysctl_overcommit_memory != OVERCOMMIT_NEVER) - acctflag = VM_NORESERVE; + acctflag = 0; file = shmem_file_setup(name, size, acctflag); } error = PTR_ERR(file); diff --git a/trunk/mm/mmap.c b/trunk/mm/mmap.c index 214b6a258eeb..c581df14d0de 100644 --- a/trunk/mm/mmap.c +++ b/trunk/mm/mmap.c @@ -1090,15 +1090,6 @@ int vma_wants_writenotify(struct vm_area_struct *vma) mapping_cap_account_dirty(vma->vm_file->f_mapping); } -/* - * We account for memory if it's a private writeable mapping, - * and VM_NORESERVE wasn't set. - */ -static inline int accountable_mapping(unsigned int vm_flags) -{ - return (vm_flags & (VM_NORESERVE | VM_SHARED | VM_WRITE)) == VM_WRITE; -} - unsigned long mmap_region(struct file *file, unsigned long addr, unsigned long len, unsigned long flags, unsigned int vm_flags, unsigned long pgoff, @@ -1126,24 +1117,23 @@ unsigned long mmap_region(struct file *file, unsigned long addr, if (!may_expand_vm(mm, len >> PAGE_SHIFT)) return -ENOMEM; - /* - * Set 'VM_NORESERVE' if we should not account for the - * memory use of this mapping. We only honor MAP_NORESERVE - * if we're allowed to overcommit memory. - */ - if ((flags & MAP_NORESERVE) && sysctl_overcommit_memory != OVERCOMMIT_NEVER) - vm_flags |= VM_NORESERVE; - if (!accountable) + if (flags & MAP_NORESERVE) vm_flags |= VM_NORESERVE; - /* - * Private writable mapping: check memory availability - */ - if (accountable_mapping(vm_flags)) { - charged = len >> PAGE_SHIFT; - if (security_vm_enough_memory(charged)) - return -ENOMEM; - vm_flags |= VM_ACCOUNT; + if (accountable && (!(flags & MAP_NORESERVE) || + sysctl_overcommit_memory == OVERCOMMIT_NEVER)) { + if (vm_flags & VM_SHARED) { + /* Check memory availability in shmem_file_setup? */ + vm_flags |= VM_ACCOUNT; + } else if (vm_flags & VM_WRITE) { + /* + * Private writable mapping: check memory availability + */ + charged = len >> PAGE_SHIFT; + if (security_vm_enough_memory(charged)) + return -ENOMEM; + vm_flags |= VM_ACCOUNT; + } } /* @@ -1194,6 +1184,14 @@ unsigned long mmap_region(struct file *file, unsigned long addr, goto free_vma; } + /* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform + * shmem_zero_setup (perhaps called through /dev/zero's ->mmap) + * that memory reservation must be checked; but that reservation + * belongs to shared memory object, not to vma: so now clear it. + */ + if ((vm_flags & (VM_SHARED|VM_ACCOUNT)) == (VM_SHARED|VM_ACCOUNT)) + vma->vm_flags &= ~VM_ACCOUNT; + /* Can addr have changed?? * * Answer: Yes, several device drivers can do it in their diff --git a/trunk/mm/shmem.c b/trunk/mm/shmem.c index 19d566ccdeea..5d0de96c9789 100644 --- a/trunk/mm/shmem.c +++ b/trunk/mm/shmem.c @@ -2628,7 +2628,7 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags) goto close_file; #ifdef CONFIG_SHMEM - SHMEM_I(inode)->flags = (flags & VM_NORESERVE) ? 0 : VM_ACCOUNT; + SHMEM_I(inode)->flags = flags & VM_ACCOUNT; #endif d_instantiate(dentry, inode); inode->i_size = size; diff --git a/trunk/net/ipv6/ip6mr.c b/trunk/net/ipv6/ip6mr.c index 228be551e9c1..d19a84b79503 100644 --- a/trunk/net/ipv6/ip6mr.c +++ b/trunk/net/ipv6/ip6mr.c @@ -48,7 +48,6 @@ #include #include #include -#include /* Big lock, protecting vif table, mrt cache and mroute socket state. Note that the changes are semaphored via rtnl_lock. diff --git a/trunk/net/packet/af_packet.c b/trunk/net/packet/af_packet.c index 9454d4ae46df..5f94db2f3e9e 100644 --- a/trunk/net/packet/af_packet.c +++ b/trunk/net/packet/af_packet.c @@ -77,7 +77,6 @@ #include #include #include -#include #ifdef CONFIG_INET #include @@ -176,7 +175,6 @@ struct packet_sock { #endif struct packet_type prot_hook; spinlock_t bind_lock; - struct mutex pg_vec_lock; unsigned int running:1, /* prot_hook is attached*/ auxdata:1, origdev:1; @@ -1071,7 +1069,6 @@ static int packet_create(struct net *net, struct socket *sock, int protocol) */ spin_lock_init(&po->bind_lock); - mutex_init(&po->pg_vec_lock); po->prot_hook.func = packet_rcv; if (sock->type == SOCK_PACKET) @@ -1868,7 +1865,6 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing synchronize_net(); err = -EBUSY; - mutex_lock(&po->pg_vec_lock); if (closing || atomic_read(&po->mapped) == 0) { err = 0; #define XC(a, b) ({ __typeof__ ((a)) __t; __t = (a); (a) = (b); __t; }) @@ -1890,7 +1886,6 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing if (atomic_read(&po->mapped)) printk(KERN_DEBUG "packet_mmap: vma is busy: %d\n", atomic_read(&po->mapped)); } - mutex_unlock(&po->pg_vec_lock); spin_lock(&po->bind_lock); if (was_running && !po->running) { @@ -1923,7 +1918,7 @@ static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_st size = vma->vm_end - vma->vm_start; - mutex_lock(&po->pg_vec_lock); + lock_sock(sk); if (po->pg_vec == NULL) goto out; if (size != po->pg_vec_len*po->pg_vec_pages*PAGE_SIZE) @@ -1946,7 +1941,7 @@ static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_st err = 0; out: - mutex_unlock(&po->pg_vec_lock); + release_sock(sk); return err; } #endif