diff options
Diffstat (limited to 'drivers/net/igb')
-rw-r--r-- | drivers/net/igb/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/igb/e1000_82575.c | 22 | ||||
-rw-r--r-- | drivers/net/igb/e1000_82575.h | 4 | ||||
-rw-r--r-- | drivers/net/igb/e1000_defines.h | 17 | ||||
-rw-r--r-- | drivers/net/igb/e1000_hw.h | 2 | ||||
-rw-r--r-- | drivers/net/igb/e1000_mac.c | 5 | ||||
-rw-r--r-- | drivers/net/igb/e1000_mac.h | 2 | ||||
-rw-r--r-- | drivers/net/igb/e1000_mbx.c | 2 | ||||
-rw-r--r-- | drivers/net/igb/e1000_mbx.h | 2 | ||||
-rw-r--r-- | drivers/net/igb/e1000_nvm.c | 2 | ||||
-rw-r--r-- | drivers/net/igb/e1000_nvm.h | 2 | ||||
-rw-r--r-- | drivers/net/igb/e1000_phy.c | 2 | ||||
-rw-r--r-- | drivers/net/igb/e1000_phy.h | 2 | ||||
-rw-r--r-- | drivers/net/igb/e1000_regs.h | 2 | ||||
-rw-r--r-- | drivers/net/igb/igb.h | 6 | ||||
-rw-r--r-- | drivers/net/igb/igb_ethtool.c | 102 | ||||
-rw-r--r-- | drivers/net/igb/igb_main.c | 128 |
17 files changed, 159 insertions, 145 deletions
diff --git a/drivers/net/igb/Makefile b/drivers/net/igb/Makefile index 8372cb9a8c1a..c6e4621b6262 100644 --- a/drivers/net/igb/Makefile +++ b/drivers/net/igb/Makefile @@ -1,7 +1,7 @@ ################################################################################ # # Intel 82575 PCI-Express Ethernet Linux driver -# Copyright(c) 1999 - 2009 Intel Corporation. +# Copyright(c) 1999 - 2011 Intel Corporation. # # This program is free software; you can redistribute it and/or modify it # under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 0f563c8c5ffc..c0857bdfb03a 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 Intel Corporation. + Copyright(c) 2007-2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -1156,10 +1156,13 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) { u32 ctrl_ext, ctrl_reg, reg; bool pcs_autoneg; + s32 ret_val = E1000_SUCCESS; + u16 data; if ((hw->phy.media_type != e1000_media_type_internal_serdes) && !igb_sgmii_active_82575(hw)) - return 0; + return ret_val; + /* * On the 82575, SerDes loopback mode persists until it is @@ -1203,6 +1206,18 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) /* disable PCS autoneg and support parallel detect only */ pcs_autoneg = false; default: + if (hw->mac.type == e1000_82575 || + hw->mac.type == e1000_82576) { + ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &data); + if (ret_val) { + printk(KERN_DEBUG "NVM Read Error\n\n"); + return ret_val; + } + + if (data & E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT) + pcs_autoneg = false; + } + /* * non-SGMII modes only supports a speed of 1000/Full for the * link so it is best to just force the MAC and let the pcs @@ -1250,7 +1265,7 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) if (!igb_sgmii_active_82575(hw)) igb_force_mac_fc(hw); - return 0; + return ret_val; } /** @@ -1735,6 +1750,7 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw) ctrl |= E1000_CTRL_RST; wr32(E1000_CTRL, ctrl); + wrfl(); /* Add delay to insure DEV_RST has time to complete */ if (global_device_reset) diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index dd6df3498998..786e110011a3 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 Intel Corporation. + Copyright(c) 2007-2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -243,6 +243,8 @@ struct e1000_adv_tx_context_desc { #define E1000_DTXCTL_MDP_EN 0x0020 #define E1000_DTXCTL_SPOOF_INT 0x0040 +#define E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT (1 << 14) + #define ALL_QUEUES 0xFFFF /* RX packet buffer size defines */ diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 6b80d40110ca..7b8ddd830f19 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 Intel Corporation. + Copyright(c) 2007-2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -437,6 +437,7 @@ #define E1000_RAH_POOL_1 0x00040000 /* Error Codes */ +#define E1000_SUCCESS 0 #define E1000_ERR_NVM 1 #define E1000_ERR_PHY 2 #define E1000_ERR_CONFIG 3 @@ -511,6 +512,16 @@ #define E1000_GCR_CMPL_TMOUT_RESEND 0x00010000 #define E1000_GCR_CAP_VER2 0x00040000 +/* mPHY Address Control and Data Registers */ +#define E1000_MPHY_ADDR_CTL 0x0024 /* mPHY Address Control Register */ +#define E1000_MPHY_ADDR_CTL_OFFSET_MASK 0xFFFF0000 +#define E1000_MPHY_DATA 0x0E10 /* mPHY Data Register */ + +/* mPHY PCS CLK Register */ +#define E1000_MPHY_PCS_CLK_REG_OFFSET 0x0004 /* mPHY PCS CLK AFE CSR Offset */ +/* mPHY Near End Digital Loopback Override Bit */ +#define E1000_MPHY_PCS_CLK_REG_DIGINELBEN 0x10 + /* PHY Control Register */ #define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ #define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ @@ -587,8 +598,8 @@ #define E1000_NVM_POLL_READ 0 /* Flag for polling for read complete */ /* NVM Word Offsets */ -#define NVM_ID_LED_SETTINGS 0x0004 -/* For SERDES output amplitude adjustment. */ +#define NVM_COMPAT 0x0003 +#define NVM_ID_LED_SETTINGS 0x0004 /* SERDES output amplitude */ #define NVM_INIT_CONTROL2_REG 0x000F #define NVM_INIT_CONTROL3_PORT_B 0x0014 #define NVM_INIT_CONTROL3_PORT_A 0x0024 diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index 27153e8d7b16..4519a1367170 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 Intel Corporation. + Copyright(c) 2007-2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c index ce8255fc3c52..2b5ef761d2ab 100644 --- a/drivers/net/igb/e1000_mac.c +++ b/drivers/net/igb/e1000_mac.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 Intel Corporation. + Copyright(c) 2007-2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -29,6 +29,7 @@ #include <linux/delay.h> #include <linux/pci.h> #include <linux/netdevice.h> +#include <linux/etherdevice.h> #include "e1000_mac.h" @@ -217,7 +218,7 @@ s32 igb_check_alt_mac_addr(struct e1000_hw *hw) } /* if multicast bit is set, the alternate address will not be used */ - if (alt_mac_addr[0] & 0x01) { + if (is_multicast_ether_addr(alt_mac_addr)) { hw_dbg("Ignoring Alternate Mac Address with MC bit set\n"); goto out; } diff --git a/drivers/net/igb/e1000_mac.h b/drivers/net/igb/e1000_mac.h index 601be99711c2..4927f61fbbc8 100644 --- a/drivers/net/igb/e1000_mac.h +++ b/drivers/net/igb/e1000_mac.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 Intel Corporation. + Copyright(c) 2007-2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_mbx.c b/drivers/net/igb/e1000_mbx.c index 78d48c7fa859..74f2f11ac290 100644 --- a/drivers/net/igb/e1000_mbx.c +++ b/drivers/net/igb/e1000_mbx.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 Intel Corporation. + Copyright(c) 2007-2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_mbx.h b/drivers/net/igb/e1000_mbx.h index bb112fb6c3a1..eddb0f83dcea 100644 --- a/drivers/net/igb/e1000_mbx.h +++ b/drivers/net/igb/e1000_mbx.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 Intel Corporation. + Copyright(c) 2007-2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_nvm.c b/drivers/net/igb/e1000_nvm.c index 75bf36a4baee..7dcd65cede56 100644 --- a/drivers/net/igb/e1000_nvm.c +++ b/drivers/net/igb/e1000_nvm.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 Intel Corporation. + Copyright(c) 2007-2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_nvm.h b/drivers/net/igb/e1000_nvm.h index 7f43564c4bcc..a2a7ca9fa733 100644 --- a/drivers/net/igb/e1000_nvm.h +++ b/drivers/net/igb/e1000_nvm.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007 Intel Corporation. + Copyright(c) 2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c index d639706eb3f6..e662554c62d6 100644 --- a/drivers/net/igb/e1000_phy.c +++ b/drivers/net/igb/e1000_phy.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 Intel Corporation. + Copyright(c) 2007-2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_phy.h b/drivers/net/igb/e1000_phy.h index 2cc117705a31..8510797b9d81 100644 --- a/drivers/net/igb/e1000_phy.h +++ b/drivers/net/igb/e1000_phy.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 Intel Corporation. + Copyright(c) 2007-2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index 958ca3bda482..0990f6d860c7 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 Intel Corporation. + Copyright(c) 2007-2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index f4fa4b1751cf..265e151b66c4 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 Intel Corporation. + Copyright(c) 2007-2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -37,6 +37,8 @@ #include <linux/clocksource.h> #include <linux/timecompare.h> #include <linux/net_tstamp.h> +#include <linux/bitops.h> +#include <linux/if_vlan.h> struct igb_adapter; @@ -252,7 +254,7 @@ static inline int igb_desc_unused(struct igb_ring *ring) struct igb_adapter { struct timer_list watchdog_timer; struct timer_list phy_info_timer; - struct vlan_group *vlgrp; + unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; u16 mng_vlan_id; u32 bd_number; u32 wol; diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index fdc895e5a3f8..ff244ce803ce 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 Intel Corporation. + Copyright(c) 2007-2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -318,65 +318,6 @@ static int igb_set_pauseparam(struct net_device *netdev, return retval; } -static u32 igb_get_rx_csum(struct net_device *netdev) -{ - struct igb_adapter *adapter = netdev_priv(netdev); - return !!(adapter->rx_ring[0]->flags & IGB_RING_FLAG_RX_CSUM); -} - -static int igb_set_rx_csum(struct net_device *netdev, u32 data) -{ - struct igb_adapter *adapter = netdev_priv(netdev); - int i; - - for (i = 0; i < adapter->num_rx_queues; i++) { - if (data) - adapter->rx_ring[i]->flags |= IGB_RING_FLAG_RX_CSUM; - else - adapter->rx_ring[i]->flags &= ~IGB_RING_FLAG_RX_CSUM; - } - - return 0; -} - -static u32 igb_get_tx_csum(struct net_device *netdev) -{ - return (netdev->features & NETIF_F_IP_CSUM) != 0; -} - -static int igb_set_tx_csum(struct net_device *netdev, u32 data) -{ - struct igb_adapter *adapter = netdev_priv(netdev); - - if (data) { - netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - if (adapter->hw.mac.type >= e1000_82576) - netdev->features |= NETIF_F_SCTP_CSUM; - } else { - netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_SCTP_CSUM); - } - - return 0; -} - -static int igb_set_tso(struct net_device *netdev, u32 data) -{ - struct igb_adapter *adapter = netdev_priv(netdev); - - if (data) { - netdev->features |= NETIF_F_TSO; - netdev->features |= NETIF_F_TSO6; - } else { - netdev->features &= ~NETIF_F_TSO; - netdev->features &= ~NETIF_F_TSO6; - } - - dev_info(&adapter->pdev->dev, "TSO is %s\n", - data ? "Enabled" : "Disabled"); - return 0; -} - static u32 igb_get_msglevel(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); @@ -1520,6 +1461,22 @@ static int igb_setup_loopback_test(struct igb_adapter *adapter) /* use CTRL_EXT to identify link type as SGMII can appear as copper */ if (reg & E1000_CTRL_EXT_LINK_MODE_MASK) { + if ((hw->device_id == E1000_DEV_ID_DH89XXCC_SGMII) || + (hw->device_id == E1000_DEV_ID_DH89XXCC_SERDES) || + (hw->device_id == E1000_DEV_ID_DH89XXCC_BACKPLANE) || + (hw->device_id == E1000_DEV_ID_DH89XXCC_SFP)) { + + /* Enable DH89xxCC MPHY for near end loopback */ + reg = rd32(E1000_MPHY_ADDR_CTL); + reg = (reg & E1000_MPHY_ADDR_CTL_OFFSET_MASK) | + E1000_MPHY_PCS_CLK_REG_OFFSET; + wr32(E1000_MPHY_ADDR_CTL, reg); + + reg = rd32(E1000_MPHY_DATA); + reg |= E1000_MPHY_PCS_CLK_REG_DIGINELBEN; + wr32(E1000_MPHY_DATA, reg); + } + reg = rd32(E1000_RCTL); reg |= E1000_RCTL_LBM_TCVR; wr32(E1000_RCTL, reg); @@ -1561,6 +1518,23 @@ static void igb_loopback_cleanup(struct igb_adapter *adapter) u32 rctl; u16 phy_reg; + if ((hw->device_id == E1000_DEV_ID_DH89XXCC_SGMII) || + (hw->device_id == E1000_DEV_ID_DH89XXCC_SERDES) || + (hw->device_id == E1000_DEV_ID_DH89XXCC_BACKPLANE) || + (hw->device_id == E1000_DEV_ID_DH89XXCC_SFP)) { + u32 reg; + + /* Disable near end loopback on DH89xxCC */ + reg = rd32(E1000_MPHY_ADDR_CTL); + reg = (reg & E1000_MPHY_ADDR_CTL_OFFSET_MASK) | + E1000_MPHY_PCS_CLK_REG_OFFSET; + wr32(E1000_MPHY_ADDR_CTL, reg); + + reg = rd32(E1000_MPHY_DATA); + reg &= ~E1000_MPHY_PCS_CLK_REG_DIGINELBEN; + wr32(E1000_MPHY_DATA, reg); + } + rctl = rd32(E1000_RCTL); rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); wr32(E1000_RCTL, rctl); @@ -2207,14 +2181,6 @@ static const struct ethtool_ops igb_ethtool_ops = { .set_ringparam = igb_set_ringparam, .get_pauseparam = igb_get_pauseparam, .set_pauseparam = igb_set_pauseparam, - .get_rx_csum = igb_get_rx_csum, - .set_rx_csum = igb_set_rx_csum, - .get_tx_csum = igb_get_tx_csum, - .set_tx_csum = igb_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = igb_set_tso, .self_test = igb_diag_test, .get_strings = igb_get_strings, .set_phys_id = igb_set_phys_id, diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 2c28621eb30b..cb8c6bbbf0d2 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 Intel Corporation. + Copyright(c) 2007-2011 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -28,6 +28,7 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/init.h> +#include <linux/bitops.h> #include <linux/vmalloc.h> #include <linux/pagemap.h> #include <linux/netdevice.h> @@ -46,6 +47,7 @@ #include <linux/if_ether.h> #include <linux/aer.h> #include <linux/prefetch.h> +#include <linux/if_vlan.h> #ifdef CONFIG_IGB_DCA #include <linux/dca.h> #endif @@ -54,9 +56,8 @@ #define MAJ 3 #define MIN 0 #define BUILD 6 -#define KFIX 2 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \ -__stringify(BUILD) "-k" __stringify(KFIX) +__stringify(BUILD) "-k" char igb_driver_name[] = "igb"; char igb_driver_version[] = DRV_VERSION; static const char igb_driver_string[] = @@ -141,7 +142,7 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *, int *, int); static int igb_ioctl(struct net_device *, struct ifreq *, int cmd); static void igb_tx_timeout(struct net_device *); static void igb_reset_task(struct work_struct *); -static void igb_vlan_rx_register(struct net_device *, struct vlan_group *); +static void igb_vlan_mode(struct net_device *netdev, u32 features); static void igb_vlan_rx_add_vid(struct net_device *, u16); static void igb_vlan_rx_kill_vid(struct net_device *, u16); static void igb_restore_vlan(struct igb_adapter *); @@ -1363,7 +1364,7 @@ static void igb_update_mng_vlan(struct igb_adapter *adapter) if ((old_vid != (u16)IGB_MNG_VLAN_NONE) && (vid != old_vid) && - !vlan_group_get_device(adapter->vlgrp, old_vid)) { + !test_bit(old_vid, adapter->active_vlans)) { /* remove VID from filter table */ igb_vfta_set(hw, old_vid, false); } @@ -1749,6 +1750,39 @@ void igb_reset(struct igb_adapter *adapter) igb_get_phy_info(hw); } +static u32 igb_fix_features(struct net_device *netdev, u32 features) +{ + /* + * Since there is no support for separate rx/tx vlan accel + * enable/disable make sure tx flag is always in same state as rx. + */ + if (features & NETIF_F_HW_VLAN_RX) + features |= NETIF_F_HW_VLAN_TX; + else + features &= ~NETIF_F_HW_VLAN_TX; + + return features; +} + +static int igb_set_features(struct net_device *netdev, u32 features) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + int i; + u32 changed = netdev->features ^ features; + + for (i = 0; i < adapter->num_rx_queues; i++) { + if (features & NETIF_F_RXCSUM) + adapter->rx_ring[i]->flags |= IGB_RING_FLAG_RX_CSUM; + else + adapter->rx_ring[i]->flags &= ~IGB_RING_FLAG_RX_CSUM; + } + + if (changed & NETIF_F_HW_VLAN_RX) + igb_vlan_mode(netdev, features); + + return 0; +} + static const struct net_device_ops igb_netdev_ops = { .ndo_open = igb_open, .ndo_stop = igb_close, @@ -1761,7 +1795,6 @@ static const struct net_device_ops igb_netdev_ops = { .ndo_do_ioctl = igb_ioctl, .ndo_tx_timeout = igb_tx_timeout, .ndo_validate_addr = eth_validate_addr, - .ndo_vlan_rx_register = igb_vlan_rx_register, .ndo_vlan_rx_add_vid = igb_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = igb_vlan_rx_kill_vid, .ndo_set_vf_mac = igb_ndo_set_vf_mac, @@ -1771,6 +1804,8 @@ static const struct net_device_ops igb_netdev_ops = { #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = igb_netpoll, #endif + .ndo_fix_features = igb_fix_features, + .ndo_set_features = igb_set_features, }; /** @@ -1910,17 +1945,18 @@ static int __devinit igb_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "PHY reset is blocked due to SOL/IDER session.\n"); - netdev->features = NETIF_F_SG | + netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | + NETIF_F_TSO | + NETIF_F_TSO6 | + NETIF_F_RXCSUM | + NETIF_F_HW_VLAN_RX; + + netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_TX | - NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; - netdev->features |= NETIF_F_IPV6_CSUM; - netdev->features |= NETIF_F_TSO; - netdev->features |= NETIF_F_TSO6; - netdev->features |= NETIF_F_GRO; - netdev->vlan_features |= NETIF_F_TSO; netdev->vlan_features |= NETIF_F_TSO6; netdev->vlan_features |= NETIF_F_IP_CSUM; @@ -1932,8 +1968,10 @@ static int __devinit igb_probe(struct pci_dev *pdev, netdev->vlan_features |= NETIF_F_HIGHDMA; } - if (hw->mac.type >= e1000_82576) + if (hw->mac.type >= e1000_82576) { + netdev->hw_features |= NETIF_F_SCTP_CSUM; netdev->features |= NETIF_F_SCTP_CSUM; + } adapter->en_mng_pt = igb_enable_mng_pass_thru(hw); @@ -2039,6 +2077,8 @@ static int __devinit igb_probe(struct pci_dev *pdev, if (err) goto err_register; + igb_vlan_mode(netdev, netdev->features); + /* carrier off reporting is important to ethtool even BEFORE open */ netif_carrier_off(netdev); @@ -2921,12 +2961,11 @@ static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size, **/ static void igb_rlpml_set(struct igb_adapter *adapter) { - u32 max_frame_size = adapter->max_frame_size; + u32 max_frame_size; struct e1000_hw *hw = &adapter->hw; u16 pf_id = adapter->vfs_allocated_count; - if (adapter->vlgrp) - max_frame_size += VLAN_TAG_SIZE; + max_frame_size = adapter->max_frame_size + VLAN_TAG_SIZE; /* if vfs are enabled we set RLPML to the largest possible request * size and set the VMOLR RLPML to the size we need */ @@ -5675,25 +5714,6 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) return count < tx_ring->count; } -/** - * igb_receive_skb - helper function to handle rx indications - * @q_vector: structure containing interrupt and ring information - * @skb: packet to send up - * @vlan_tag: vlan tag for packet - **/ -static void igb_receive_skb(struct igb_q_vector *q_vector, - struct sk_buff *skb, - u16 vlan_tag) -{ - struct igb_adapter *adapter = q_vector->adapter; - - if (vlan_tag && adapter->vlgrp) - vlan_gro_receive(&q_vector->napi, adapter->vlgrp, - vlan_tag, skb); - else - napi_gro_receive(&q_vector->napi, skb); -} - static inline void igb_rx_checksum_adv(struct igb_ring *ring, u32 status_err, struct sk_buff *skb) { @@ -5791,7 +5811,6 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector, unsigned int i; u32 staterr; u16 length; - u16 vlan_tag; i = rx_ring->next_to_clean; buffer_info = &rx_ring->buffer_info[i]; @@ -5876,10 +5895,12 @@ send_up: skb->protocol = eth_type_trans(skb, netdev); skb_record_rx_queue(skb, rx_ring->queue_index); - vlan_tag = ((staterr & E1000_RXD_STAT_VP) ? - le16_to_cpu(rx_desc->wb.upper.vlan) : 0); + if (staterr & E1000_RXD_STAT_VP) { + u16 vid = le16_to_cpu(rx_desc->wb.upper.vlan); - igb_receive_skb(q_vector, skb, vlan_tag); + __vlan_hwaccel_put_tag(skb, vid); + } + napi_gro_receive(&q_vector->napi, skb); next_desc: rx_desc->wb.upper.status_error = 0; @@ -6249,7 +6270,7 @@ s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) struct igb_adapter *adapter = hw->back; u16 cap_offset; - cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP); + cap_offset = adapter->pdev->pcie_cap; if (!cap_offset) return -E1000_ERR_CONFIG; @@ -6263,7 +6284,7 @@ s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) struct igb_adapter *adapter = hw->back; u16 cap_offset; - cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP); + cap_offset = adapter->pdev->pcie_cap; if (!cap_offset) return -E1000_ERR_CONFIG; @@ -6272,17 +6293,15 @@ s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) return 0; } -static void igb_vlan_rx_register(struct net_device *netdev, - struct vlan_group *grp) +static void igb_vlan_mode(struct net_device *netdev, u32 features) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; u32 ctrl, rctl; igb_irq_disable(adapter); - adapter->vlgrp = grp; - if (grp) { + if (features & NETIF_F_HW_VLAN_RX) { /* enable VLAN tag insert/strip */ ctrl = rd32(E1000_CTRL); ctrl |= E1000_CTRL_VME; @@ -6316,6 +6335,8 @@ static void igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid) /* add the filter since PF can receive vlans w/o entry in vlvf */ igb_vfta_set(hw, vid, true); + + set_bit(vid, adapter->active_vlans); } static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) @@ -6326,7 +6347,6 @@ static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) s32 err; igb_irq_disable(adapter); - vlan_group_set_device(adapter->vlgrp, vid, NULL); if (!test_bit(__IGB_DOWN, &adapter->state)) igb_irq_enable(adapter); @@ -6337,20 +6357,16 @@ static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) /* if vid was not present in VLVF just remove it from table */ if (err) igb_vfta_set(hw, vid, false); + + clear_bit(vid, adapter->active_vlans); } static void igb_restore_vlan(struct igb_adapter *adapter) { - igb_vlan_rx_register(adapter->netdev, adapter->vlgrp); + u16 vid; - if (adapter->vlgrp) { - u16 vid; - for (vid = 0; vid < VLAN_N_VID; vid++) { - if (!vlan_group_get_device(adapter->vlgrp, vid)) - continue; - igb_vlan_rx_add_vid(adapter->netdev, vid); - } - } + for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID) + igb_vlan_rx_add_vid(adapter->netdev, vid); } int igb_set_spd_dplx(struct igb_adapter *adapter, u32 spd, u8 dplx) |