diff options
Diffstat (limited to 'drivers/net/igb/igb_main.c')
-rw-r--r-- | drivers/net/igb/igb_main.c | 127 |
1 files changed, 71 insertions, 56 deletions
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 2c28621eb30b..dc599059512a 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> @@ -54,9 +55,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 +141,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 +1363,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 +1749,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 +1794,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 +1803,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 +1944,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 +1967,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 +2076,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 +2960,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 +5713,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 +5810,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 +5894,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 +6269,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 +6283,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 +6292,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 +6334,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 +6346,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 +6356,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) |