]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
Merge branch 'kbuild' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild
[karo-tx-linux.git] / drivers / net / ethernet / intel / ixgbe / ixgbe_main.c
index fee1f2918eadc1217cbf8fc96b438651c71dd223..1e2f39ebd82495495c872fc310c0aec637f3c5fd 100644 (file)
@@ -54,6 +54,7 @@
 #include <net/pkt_cls.h>
 #include <net/tc_act/tc_gact.h>
 #include <net/tc_act/tc_mirred.h>
+#include <net/vxlan.h>
 
 #include "ixgbe.h"
 #include "ixgbe_common.h"
@@ -3070,6 +3071,9 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
                return;
        }
 
+       if (!adapter->msix_entries)
+               return;
+
        for (vector = 0; vector < adapter->num_q_vectors; vector++) {
                struct ixgbe_q_vector *q_vector = adapter->q_vector[vector];
                struct msix_entry *entry = &adapter->msix_entries[vector];
@@ -5012,24 +5016,23 @@ fwd_queue_err:
        return err;
 }
 
-static void ixgbe_configure_dfwd(struct ixgbe_adapter *adapter)
+static int ixgbe_upper_dev_walk(struct net_device *upper, void *data)
 {
-       struct net_device *upper;
-       struct list_head *iter;
-       int err;
+       if (netif_is_macvlan(upper)) {
+               struct macvlan_dev *dfwd = netdev_priv(upper);
+               struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
 
-       netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
-               if (netif_is_macvlan(upper)) {
-                       struct macvlan_dev *dfwd = netdev_priv(upper);
-                       struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
-
-                       if (dfwd->fwd_priv) {
-                               err = ixgbe_fwd_ring_up(upper, vadapter);
-                               if (err)
-                                       continue;
-                       }
-               }
+               if (dfwd->fwd_priv)
+                       ixgbe_fwd_ring_up(upper, vadapter);
        }
+
+       return 0;
+}
+
+static void ixgbe_configure_dfwd(struct ixgbe_adapter *adapter)
+{
+       netdev_walk_all_upper_dev_rcu(adapter->netdev,
+                                     ixgbe_upper_dev_walk, NULL);
 }
 
 static void ixgbe_configure(struct ixgbe_adapter *adapter)
@@ -5448,12 +5451,25 @@ static void ixgbe_fdir_filter_exit(struct ixgbe_adapter *adapter)
        spin_unlock(&adapter->fdir_perfect_lock);
 }
 
+static int ixgbe_disable_macvlan(struct net_device *upper, void *data)
+{
+       if (netif_is_macvlan(upper)) {
+               struct macvlan_dev *vlan = netdev_priv(upper);
+
+               if (vlan->fwd_priv) {
+                       netif_tx_stop_all_queues(upper);
+                       netif_carrier_off(upper);
+                       netif_tx_disable(upper);
+               }
+       }
+
+       return 0;
+}
+
 void ixgbe_down(struct ixgbe_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
        struct ixgbe_hw *hw = &adapter->hw;
-       struct net_device *upper;
-       struct list_head *iter;
        int i;
 
        /* signal that we are down to the interrupt handler */
@@ -5477,17 +5493,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
        netif_tx_disable(netdev);
 
        /* disable any upper devices */
-       netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
-               if (netif_is_macvlan(upper)) {
-                       struct macvlan_dev *vlan = netdev_priv(upper);
-
-                       if (vlan->fwd_priv) {
-                               netif_tx_stop_all_queues(upper);
-                               netif_carrier_off(upper);
-                               netif_tx_disable(upper);
-                       }
-               }
-       }
+       netdev_walk_all_upper_dev_rcu(adapter->netdev,
+                                     ixgbe_disable_macvlan, NULL);
 
        ixgbe_irq_disable(adapter);
 
@@ -5618,7 +5625,8 @@ static void ixgbe_init_dcb(struct ixgbe_adapter *adapter)
  * Fields are initialized based on PCI device information and
  * OS network device settings (MTU size).
  **/
-static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
+static int ixgbe_sw_init(struct ixgbe_adapter *adapter,
+                        const struct ixgbe_info *ii)
 {
        struct ixgbe_hw *hw = &adapter->hw;
        struct pci_dev *pdev = adapter->pdev;
@@ -5634,6 +5642,9 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
        hw->subsystem_vendor_id = pdev->subsystem_vendor;
        hw->subsystem_device_id = pdev->subsystem_device;
 
+       /* get_invariants needs the device IDs */
+       ii->get_invariants(hw);
+
        /* Set common capability flags and settings */
        rss = min_t(int, ixgbe_max_rss_indices(adapter), num_online_cpus());
        adapter->ring_feature[RING_F_RSS].limit = rss;
@@ -6049,11 +6060,6 @@ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter)
 static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
-       int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
-
-       /* MTU < 68 is an error and causes problems on some kernels */
-       if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE))
-               return -EINVAL;
 
        /*
         * For 82599EB we cannot allow legacy VFs to enable their receive
@@ -6062,7 +6068,7 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
         */
        if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) &&
            (adapter->hw.mac.type == ixgbe_mac_82599EB) &&
-           (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)))
+           (new_mtu > ETH_DATA_LEN))
                e_warn(probe, "Setting MTU > 1500 will disable legacy VFs\n");
 
        e_info(probe, "changing MTU from %d to %d\n", netdev->mtu, new_mtu);
@@ -6728,6 +6734,18 @@ static void ixgbe_update_default_up(struct ixgbe_adapter *adapter)
 #endif
 }
 
+static int ixgbe_enable_macvlan(struct net_device *upper, void *data)
+{
+       if (netif_is_macvlan(upper)) {
+               struct macvlan_dev *vlan = netdev_priv(upper);
+
+               if (vlan->fwd_priv)
+                       netif_tx_wake_all_queues(upper);
+       }
+
+       return 0;
+}
+
 /**
  * ixgbe_watchdog_link_is_up - update netif_carrier status and
  *                             print link up message
@@ -6737,8 +6755,6 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
        struct ixgbe_hw *hw = &adapter->hw;
-       struct net_device *upper;
-       struct list_head *iter;
        u32 link_speed = adapter->link_speed;
        const char *speed_str;
        bool flow_rx, flow_tx;
@@ -6809,14 +6825,8 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
 
        /* enable any upper devices */
        rtnl_lock();
-       netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
-               if (netif_is_macvlan(upper)) {
-                       struct macvlan_dev *vlan = netdev_priv(upper);
-
-                       if (vlan->fwd_priv)
-                               netif_tx_wake_all_queues(upper);
-               }
-       }
+       netdev_walk_all_upper_dev_rcu(adapter->netdev,
+                                     ixgbe_enable_macvlan, NULL);
        rtnl_unlock();
 
        /* update the default user priority for VFs */
@@ -7655,11 +7665,17 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
        /* snag network header to get L4 type and address */
        skb = first->skb;
        hdr.network = skb_network_header(skb);
+       if (unlikely(hdr.network <= skb->data))
+               return;
        if (skb->encapsulation &&
            first->protocol == htons(ETH_P_IP) &&
-           hdr.ipv4->protocol != IPPROTO_UDP) {
+           hdr.ipv4->protocol == IPPROTO_UDP) {
                struct ixgbe_adapter *adapter = q_vector->adapter;
 
+               if (unlikely(skb_tail_pointer(skb) < hdr.network +
+                            VXLAN_HEADROOM))
+                       return;
+
                /* verify the port is recognized as VXLAN */
                if (adapter->vxlan_port &&
                    udp_hdr(skb)->dest == adapter->vxlan_port)
@@ -7670,6 +7686,12 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
                        hdr.network = skb_inner_network_header(skb);
        }
 
+       /* Make sure we have at least [minimum IPv4 header + TCP]
+        * or [IPv6 header] bytes
+        */
+       if (unlikely(skb_tail_pointer(skb) < hdr.network + 40))
+               return;
+
        /* Currently only IPv4/IPv6 with TCP is supported */
        switch (hdr.ipv4->version) {
        case IPVERSION:
@@ -7689,6 +7711,10 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
        if (l4_proto != IPPROTO_TCP)
                return;
 
+       if (unlikely(skb_tail_pointer(skb) < hdr.network +
+                    hlen + sizeof(struct tcphdr)))
+               return;
+
        th = (struct tcphdr *)(hdr.network + hlen);
 
        /* skip this packet since the socket is closing */
@@ -8354,12 +8380,38 @@ static int ixgbe_configure_clsu32_del_hnode(struct ixgbe_adapter *adapter,
 }
 
 #ifdef CONFIG_NET_CLS_ACT
+struct upper_walk_data {
+       struct ixgbe_adapter *adapter;
+       u64 action;
+       int ifindex;
+       u8 queue;
+};
+
+static int get_macvlan_queue(struct net_device *upper, void *_data)
+{
+       if (netif_is_macvlan(upper)) {
+               struct macvlan_dev *dfwd = netdev_priv(upper);
+               struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
+               struct upper_walk_data *data = _data;
+               struct ixgbe_adapter *adapter = data->adapter;
+               int ifindex = data->ifindex;
+
+               if (vadapter && vadapter->netdev->ifindex == ifindex) {
+                       data->queue = adapter->rx_ring[vadapter->rx_base_queue]->reg_idx;
+                       data->action = data->queue;
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
 static int handle_redirect_action(struct ixgbe_adapter *adapter, int ifindex,
                                  u8 *queue, u64 *action)
 {
        unsigned int num_vfs = adapter->num_vfs, vf;
+       struct upper_walk_data data;
        struct net_device *upper;
-       struct list_head *iter;
 
        /* redirect to a SRIOV VF */
        for (vf = 0; vf < num_vfs; ++vf) {
@@ -8377,17 +8429,16 @@ static int handle_redirect_action(struct ixgbe_adapter *adapter, int ifindex,
        }
 
        /* redirect to a offloaded macvlan netdev */
-       netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
-               if (netif_is_macvlan(upper)) {
-                       struct macvlan_dev *dfwd = netdev_priv(upper);
-                       struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
-
-                       if (vadapter && vadapter->netdev->ifindex == ifindex) {
-                               *queue = adapter->rx_ring[vadapter->rx_base_queue]->reg_idx;
-                               *action = *queue;
-                               return 0;
-                       }
-               }
+       data.adapter = adapter;
+       data.ifindex = ifindex;
+       data.action = 0;
+       data.queue = 0;
+       if (netdev_walk_all_upper_dev_rcu(adapter->netdev,
+                                         get_macvlan_queue, &data)) {
+               *action = data.action;
+               *queue = data.queue;
+
+               return 0;
        }
 
        return -EINVAL;
@@ -8414,7 +8465,7 @@ static int parse_tc_actions(struct ixgbe_adapter *adapter,
                }
 
                /* Redirect to a VF or a offloaded macvlan */
-               if (is_tcf_mirred_redirect(a)) {
+               if (is_tcf_mirred_egress_redirect(a)) {
                        int ifindex = tcf_mirred_ifindex(a);
 
                        err = handle_redirect_action(adapter, ifindex, queue,
@@ -9481,6 +9532,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        hw->mac.ops   = *ii->mac_ops;
        hw->mac.type  = ii->mac;
        hw->mvals     = ii->mvals;
+       if (ii->link_ops)
+               hw->link.ops  = *ii->link_ops;
 
        /* EEPROM */
        hw->eeprom.ops = *ii->eeprom_ops;
@@ -9504,10 +9557,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        hw->phy.mdio.mdio_read = ixgbe_mdio_read;
        hw->phy.mdio.mdio_write = ixgbe_mdio_write;
 
-       ii->get_invariants(hw);
-
        /* setup the private structure */
-       err = ixgbe_sw_init(adapter);
+       err = ixgbe_sw_init(adapter, ii);
        if (err)
                goto err_sw_init;
 
@@ -9616,6 +9667,10 @@ skip_sriov:
        netdev->priv_flags |= IFF_UNICAST_FLT;
        netdev->priv_flags |= IFF_SUPP_NOFCS;
 
+       /* MTU range: 68 - 9710 */
+       netdev->min_mtu = ETH_MIN_MTU;
+       netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN);
+
 #ifdef CONFIG_IXGBE_DCB
        if (adapter->flags & IXGBE_FLAG_DCB_CAPABLE)
                netdev->dcbnl_ops = &dcbnl_ops;