]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/ixgbe/ixgbe_main.c
Merge branches 'irq-core-for-linus' and 'core-locking-for-linus' of git://git.kernel...
[karo-tx-linux.git] / drivers / net / ixgbe / ixgbe_main.c
index 998debe8023bd9c3f26e679ac4c5665ddf90f28f..2bd3eb4ee5a1996d9c219c90419c0b9a455c0b5b 100644 (file)
@@ -824,8 +824,10 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
 
        tx_ring->total_bytes += total_bytes;
        tx_ring->total_packets += total_packets;
+       u64_stats_update_begin(&tx_ring->syncp);
        tx_ring->stats.packets += total_packets;
        tx_ring->stats.bytes += total_bytes;
+       u64_stats_update_end(&tx_ring->syncp);
        return count < tx_ring->work_limit;
 }
 
@@ -954,17 +956,13 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector,
        bool is_vlan = (status & IXGBE_RXD_STAT_VP);
        u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
 
-       if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
-               if (adapter->vlgrp && is_vlan && (tag & VLAN_VID_MASK))
-                       vlan_gro_receive(napi, adapter->vlgrp, tag, skb);
-               else
-                       napi_gro_receive(napi, skb);
-       } else {
-               if (adapter->vlgrp && is_vlan && (tag & VLAN_VID_MASK))
-                       vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
-               else
-                       netif_rx(skb);
-       }
+       if (is_vlan && (tag & VLAN_VID_MASK))
+               __vlan_hwaccel_put_tag(skb, tag);
+
+       if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
+               napi_gro_receive(napi, skb);
+       else
+               netif_rx(skb);
 }
 
 /**
@@ -1172,7 +1170,6 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
                               int *work_done, int work_to_do)
 {
        struct ixgbe_adapter *adapter = q_vector->adapter;
-       struct net_device *netdev = adapter->netdev;
        struct pci_dev *pdev = adapter->pdev;
        union ixgbe_adv_rx_desc *rx_desc, *next_rxd;
        struct ixgbe_rx_buffer *rx_buffer_info, *next_buffer;
@@ -1298,8 +1295,10 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
                                        rx_ring->rsc_count++;
                                rx_ring->rsc_flush++;
                        }
+                       u64_stats_update_begin(&rx_ring->syncp);
                        rx_ring->stats.packets++;
                        rx_ring->stats.bytes += skb->len;
+                       u64_stats_update_end(&rx_ring->syncp);
                } else {
                        if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
                                rx_buffer_info->skb = next_buffer->skb;
@@ -1375,8 +1374,6 @@ next_desc:
 
        rx_ring->total_packets += total_rx_packets;
        rx_ring->total_bytes += total_rx_bytes;
-       netdev->stats.rx_bytes += total_rx_bytes;
-       netdev->stats.rx_packets += total_rx_packets;
 
        return cleaned;
 }
@@ -3065,6 +3062,7 @@ static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
 
        /* add VID to filter table */
        hw->mac.ops.set_vfta(&adapter->hw, vid, pool_ndx, true);
+       set_bit(vid, adapter->active_vlans);
 }
 
 static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
@@ -3073,16 +3071,9 @@ static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
        struct ixgbe_hw *hw = &adapter->hw;
        int pool_ndx = adapter->num_vfs;
 
-       if (!test_bit(__IXGBE_DOWN, &adapter->state))
-               ixgbe_irq_disable(adapter);
-
-       vlan_group_set_device(adapter->vlgrp, vid, NULL);
-
-       if (!test_bit(__IXGBE_DOWN, &adapter->state))
-               ixgbe_irq_enable(adapter, true, true);
-
        /* remove VID from filter table */
        hw->mac.ops.set_vfta(&adapter->hw, vid, pool_ndx, false);
+       clear_bit(vid, adapter->active_vlans);
 }
 
 /**
@@ -3092,27 +3083,45 @@ static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 static void ixgbe_vlan_filter_disable(struct ixgbe_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
-       u32 vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+       u32 vlnctrl;
+
+       vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+       vlnctrl &= ~(IXGBE_VLNCTRL_VFE | IXGBE_VLNCTRL_CFIEN);
+       IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
+}
+
+/**
+ * ixgbe_vlan_filter_enable - helper to enable hw vlan filtering
+ * @adapter: driver data
+ */
+static void ixgbe_vlan_filter_enable(struct ixgbe_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       u32 vlnctrl;
+
+       vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+       vlnctrl |= IXGBE_VLNCTRL_VFE;
+       vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
+       IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
+}
+
+/**
+ * ixgbe_vlan_strip_disable - helper to disable hw vlan stripping
+ * @adapter: driver data
+ */
+static void ixgbe_vlan_strip_disable(struct ixgbe_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       u32 vlnctrl;
        int i, j;
 
        switch (hw->mac.type) {
        case ixgbe_mac_82598EB:
-               vlnctrl &= ~IXGBE_VLNCTRL_VFE;
-#ifdef CONFIG_IXGBE_DCB
-               if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
-                       vlnctrl &= ~IXGBE_VLNCTRL_VME;
-#endif
-               vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
+               vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+               vlnctrl &= ~IXGBE_VLNCTRL_VME;
                IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
                break;
        case ixgbe_mac_82599EB:
-               vlnctrl &= ~IXGBE_VLNCTRL_VFE;
-               vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
-               IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
-#ifdef CONFIG_IXGBE_DCB
-               if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
-                       break;
-#endif
                for (i = 0; i < adapter->num_rx_queues; i++) {
                        j = adapter->rx_ring[i]->reg_idx;
                        vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
@@ -3126,25 +3135,22 @@ static void ixgbe_vlan_filter_disable(struct ixgbe_adapter *adapter)
 }
 
 /**
- * ixgbe_vlan_filter_enable - helper to enable hw vlan filtering
+ * ixgbe_vlan_strip_enable - helper to enable hw vlan stripping
  * @adapter: driver data
  */
-static void ixgbe_vlan_filter_enable(struct ixgbe_adapter *adapter)
+static void ixgbe_vlan_strip_enable(struct ixgbe_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
-       u32 vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+       u32 vlnctrl;
        int i, j;
 
        switch (hw->mac.type) {
        case ixgbe_mac_82598EB:
-               vlnctrl |= IXGBE_VLNCTRL_VME | IXGBE_VLNCTRL_VFE;
-               vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
+               vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+               vlnctrl |= IXGBE_VLNCTRL_VME;
                IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
                break;
        case ixgbe_mac_82599EB:
-               vlnctrl |= IXGBE_VLNCTRL_VFE;
-               vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
-               IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
                for (i = 0; i < adapter->num_rx_queues; i++) {
                        j = adapter->rx_ring[i]->reg_idx;
                        vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
@@ -3157,40 +3163,14 @@ static void ixgbe_vlan_filter_enable(struct ixgbe_adapter *adapter)
        }
 }
 
-static void ixgbe_vlan_rx_register(struct net_device *netdev,
-                                  struct vlan_group *grp)
-{
-       struct ixgbe_adapter *adapter = netdev_priv(netdev);
-
-       if (!test_bit(__IXGBE_DOWN, &adapter->state))
-               ixgbe_irq_disable(adapter);
-       adapter->vlgrp = grp;
-
-       /*
-        * For a DCB driver, always enable VLAN tag stripping so we can
-        * still receive traffic from a DCB-enabled host even if we're
-        * not in DCB mode.
-        */
-       ixgbe_vlan_filter_enable(adapter);
-
-       ixgbe_vlan_rx_add_vid(netdev, 0);
-
-       if (!test_bit(__IXGBE_DOWN, &adapter->state))
-               ixgbe_irq_enable(adapter, true, true);
-}
-
 static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter)
 {
-       ixgbe_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;
-                       ixgbe_vlan_rx_add_vid(adapter->netdev, vid);
-               }
-       }
+       ixgbe_vlan_rx_add_vid(adapter->netdev, 0);
+
+       for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+               ixgbe_vlan_rx_add_vid(adapter->netdev, vid);
 }
 
 /**
@@ -3305,6 +3285,11 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
        }
 
        IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
+
+       if (netdev->features & NETIF_F_HW_VLAN_RX)
+               ixgbe_vlan_strip_enable(adapter);
+       else
+               ixgbe_vlan_strip_disable(adapter);
 }
 
 static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter)
@@ -3362,6 +3347,7 @@ static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter)
 static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
+       int max_frame = adapter->netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
        u32 txdctl;
        int i, j;
 
@@ -3374,8 +3360,15 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
        if (hw->mac.type == ixgbe_mac_82598EB)
                netif_set_gso_max_size(adapter->netdev, 32768);
 
-       ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_TX_CONFIG);
-       ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_RX_CONFIG);
+#ifdef CONFIG_FCOE
+       if (adapter->netdev->features & NETIF_F_FCOE_MTU)
+               max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
+#endif
+
+       ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, max_frame,
+                                       DCB_TX_CONFIG);
+       ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, max_frame,
+                                       DCB_RX_CONFIG);
 
        /* reconfigure the hardware */
        ixgbe_dcb_hw_config(&adapter->hw, &adapter->dcb_cfg);
@@ -3388,7 +3381,7 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
                IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
        }
        /* Enable VLAN tag insert/strip */
-       ixgbe_vlan_filter_enable(adapter);
+       adapter->netdev->features |= NETIF_F_HW_VLAN_RX;
 
        hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true);
 }
@@ -3400,13 +3393,13 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
        struct ixgbe_hw *hw = &adapter->hw;
        int i;
 
-       ixgbe_set_rx_mode(netdev);
-
-       ixgbe_restore_vlan(adapter);
 #ifdef CONFIG_IXGBE_DCB
        ixgbe_configure_dcb(adapter);
 #endif
 
+       ixgbe_set_rx_mode(netdev);
+       ixgbe_restore_vlan(adapter);
+
 #ifdef IXGBE_FCOE
        if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
                ixgbe_configure_fcoe(adapter);
@@ -6558,6 +6551,38 @@ static void ixgbe_netpoll(struct net_device *netdev)
 }
 #endif
 
+static struct rtnl_link_stats64 *ixgbe_get_stats64(struct net_device *netdev,
+                                                  struct rtnl_link_stats64 *stats)
+{
+       struct ixgbe_adapter *adapter = netdev_priv(netdev);
+       int i;
+
+       /* accurate rx/tx bytes/packets stats */
+       dev_txq_stats_fold(netdev, stats);
+       for (i = 0; i < adapter->num_rx_queues; i++) {
+               struct ixgbe_ring *ring = adapter->rx_ring[i];
+               u64 bytes, packets;
+               unsigned int start;
+
+               do {
+                       start = u64_stats_fetch_begin_bh(&ring->syncp);
+                       packets = ring->stats.packets;
+                       bytes   = ring->stats.bytes;
+               } while (u64_stats_fetch_retry_bh(&ring->syncp, start));
+               stats->rx_packets += packets;
+               stats->rx_bytes   += bytes;
+       }
+
+       /* following stats updated by ixgbe_watchdog_task() */
+       stats->multicast        = netdev->stats.multicast;
+       stats->rx_errors        = netdev->stats.rx_errors;
+       stats->rx_length_errors = netdev->stats.rx_length_errors;
+       stats->rx_crc_errors    = netdev->stats.rx_crc_errors;
+       stats->rx_missed_errors = netdev->stats.rx_missed_errors;
+       return stats;
+}
+
+
 static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_open               = ixgbe_open,
        .ndo_stop               = ixgbe_close,
@@ -6569,7 +6594,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_set_mac_address    = ixgbe_set_mac,
        .ndo_change_mtu         = ixgbe_change_mtu,
        .ndo_tx_timeout         = ixgbe_tx_timeout,
-       .ndo_vlan_rx_register   = ixgbe_vlan_rx_register,
        .ndo_vlan_rx_add_vid    = ixgbe_vlan_rx_add_vid,
        .ndo_vlan_rx_kill_vid   = ixgbe_vlan_rx_kill_vid,
        .ndo_do_ioctl           = ixgbe_ioctl,
@@ -6577,6 +6601,7 @@ static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_set_vf_vlan        = ixgbe_ndo_set_vf_vlan,
        .ndo_set_vf_tx_rate     = ixgbe_ndo_set_vf_bw,
        .ndo_get_vf_config      = ixgbe_ndo_get_vf_config,
+       .ndo_get_stats64        = ixgbe_get_stats64,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = ixgbe_netpoll,
 #endif