]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
ixgbe: Re-enable ability to toggle VLAN filtering
[mirror_ubuntu-artful-kernel.git] / drivers / net / ethernet / intel / ixgbe / ixgbe_main.c
index 8bebd862a54ccd7f4f3defe4fd1a1035188294d6..ee57a89252bbcfd952cab3db2d8b7a4450be75f5 100644 (file)
@@ -50,7 +50,7 @@
 #include <linux/if_bridge.h>
 #include <linux/prefetch.h>
 #include <scsi/fc/fc_fcoe.h>
-#include <net/vxlan.h>
+#include <net/udp_tunnel.h>
 #include <net/pkt_cls.h>
 #include <net/tc_act/tc_gact.h>
 #include <net/tc_act/tc_mirred.h>
@@ -3084,7 +3084,7 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
                free_irq(entry->vector, q_vector);
        }
 
-       free_irq(adapter->msix_entries[vector++].vector, adapter);
+       free_irq(adapter->msix_entries[vector].vector, adapter);
 }
 
 /**
@@ -4100,6 +4100,8 @@ static void ixgbe_vlan_promisc_enable(struct ixgbe_adapter *adapter)
        struct ixgbe_hw *hw = &adapter->hw;
        u32 vlnctrl, i;
 
+       vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+
        switch (hw->mac.type) {
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
@@ -4112,8 +4114,7 @@ static void ixgbe_vlan_promisc_enable(struct ixgbe_adapter *adapter)
                /* fall through */
        case ixgbe_mac_82598EB:
                /* legacy case, we can just disable VLAN filtering */
-               vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
-               vlnctrl &= ~(IXGBE_VLNCTRL_VFE | IXGBE_VLNCTRL_CFIEN);
+               vlnctrl &= ~IXGBE_VLNCTRL_VFE;
                IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
                return;
        }
@@ -4125,6 +4126,10 @@ static void ixgbe_vlan_promisc_enable(struct ixgbe_adapter *adapter)
        /* Set flag so we don't redo unnecessary work */
        adapter->flags2 |= IXGBE_FLAG2_VLAN_PROMISC;
 
+       /* For VMDq and SR-IOV we must leave VLAN filtering enabled */
+       vlnctrl |= IXGBE_VLNCTRL_VFE;
+       IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
+
        /* Add PF to all active pools */
        for (i = IXGBE_VLVF_ENTRIES; --i;) {
                u32 reg_offset = IXGBE_VLVFB(i * 2 + VMDQ_P(0) / 32);
@@ -4191,6 +4196,11 @@ static void ixgbe_vlan_promisc_disable(struct ixgbe_adapter *adapter)
        struct ixgbe_hw *hw = &adapter->hw;
        u32 vlnctrl, i;
 
+       /* Set VLAN filtering to enabled */
+       vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+       vlnctrl |= IXGBE_VLNCTRL_VFE;
+       IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
+
        switch (hw->mac.type) {
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
@@ -4202,10 +4212,6 @@ static void ixgbe_vlan_promisc_disable(struct ixgbe_adapter *adapter)
                        break;
                /* fall through */
        case ixgbe_mac_82598EB:
-               vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
-               vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
-               vlnctrl |= IXGBE_VLNCTRL_VFE;
-               IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
                return;
        }
 
@@ -5625,7 +5631,6 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
        struct pci_dev *pdev = adapter->pdev;
        unsigned int rss, fdir;
        u32 fwsm;
-       u16 device_caps;
        int i;
 
        /* PCI config space info */
@@ -5722,9 +5727,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
 #ifdef CONFIG_IXGBE_DCA
                adapter->flags &= ~IXGBE_FLAG_DCA_CAPABLE;
 #endif
-#ifdef CONFIG_IXGBE_VXLAN
                adapter->flags |= IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE;
-#endif
                break;
        default:
                break;
@@ -5773,22 +5776,6 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
        adapter->tx_ring_count = IXGBE_DEFAULT_TXD;
        adapter->rx_ring_count = IXGBE_DEFAULT_RXD;
 
-       /* Cache bit indicating need for crosstalk fix */
-       switch (hw->mac.type) {
-       case ixgbe_mac_82599EB:
-       case ixgbe_mac_X550EM_x:
-       case ixgbe_mac_x550em_a:
-               hw->mac.ops.get_device_caps(hw, &device_caps);
-               if (device_caps & IXGBE_DEVICE_CAPS_NO_CROSSTALK_WR)
-                       adapter->need_crosstalk_fix = false;
-               else
-                       adapter->need_crosstalk_fix = true;
-               break;
-       default:
-               adapter->need_crosstalk_fix = false;
-               break;
-       }
-
        /* set default work limits */
        adapter->tx_work_limit = IXGBE_DEFAULT_TX_WORK;
 
@@ -6158,9 +6145,7 @@ int ixgbe_open(struct net_device *netdev)
        ixgbe_up_complete(adapter);
 
        ixgbe_clear_vxlan_port(adapter);
-#ifdef CONFIG_IXGBE_VXLAN
-       vxlan_get_rx_port(netdev);
-#endif
+       udp_tunnel_get_rx_info(netdev);
 
        return 0;
 
@@ -6711,18 +6696,6 @@ static void ixgbe_watchdog_update_link(struct ixgbe_adapter *adapter)
                link_up = true;
        }
 
-       /* If Crosstalk fix enabled do the sanity check of making sure
-        * the SFP+ cage is empty.
-        */
-       if (adapter->need_crosstalk_fix) {
-               u32 sfp_cage_full;
-
-               sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
-                               IXGBE_ESDP_SDP2;
-               if (ixgbe_is_sfp(hw) && link_up && !sfp_cage_full)
-                       link_up = false;
-       }
-
        if (adapter->ixgbe_ieee_pfc)
                pfc_en |= !!(adapter->ixgbe_ieee_pfc->pfc_en);
 
@@ -7069,16 +7042,6 @@ static void ixgbe_sfp_detection_subtask(struct ixgbe_adapter *adapter)
        struct ixgbe_hw *hw = &adapter->hw;
        s32 err;
 
-       /* If crosstalk fix enabled verify the SFP+ cage is full */
-       if (adapter->need_crosstalk_fix) {
-               u32 sfp_cage_full;
-
-               sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
-                               IXGBE_ESDP_SDP2;
-               if (!sfp_cage_full)
-                       return;
-       }
-
        /* not searching for SFP so there is nothing to do here */
        if (!(adapter->flags2 & IXGBE_FLAG2_SEARCH_FOR_SFP) &&
            !(adapter->flags2 & IXGBE_FLAG2_SFP_NEEDS_RESET))
@@ -7262,14 +7225,12 @@ static void ixgbe_service_task(struct work_struct *work)
                ixgbe_service_event_complete(adapter);
                return;
        }
-#ifdef CONFIG_IXGBE_VXLAN
-       rtnl_lock();
        if (adapter->flags2 & IXGBE_FLAG2_VXLAN_REREG_NEEDED) {
+               rtnl_lock();
                adapter->flags2 &= ~IXGBE_FLAG2_VXLAN_REREG_NEEDED;
-               vxlan_get_rx_port(adapter->netdev);
+               udp_tunnel_get_rx_info(adapter->netdev);
+               rtnl_unlock();
        }
-       rtnl_unlock();
-#endif /* CONFIG_IXGBE_VXLAN */
        ixgbe_reset_subtask(adapter);
        ixgbe_phy_interrupt_subtask(adapter);
        ixgbe_sfp_detection_subtask(adapter);
@@ -7697,7 +7658,6 @@ 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);
-#ifdef CONFIG_IXGBE_VXLAN
        if (skb->encapsulation &&
            first->protocol == htons(ETH_P_IP) &&
            hdr.ipv4->protocol != IPPROTO_UDP) {
@@ -7708,7 +7668,6 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
                    udp_hdr(skb)->dest == adapter->vxlan_port)
                        hdr.network = skb_inner_network_header(skb);
        }
-#endif /* CONFIG_IXGBE_VXLAN */
 
        /* Currently only IPv4/IPv6 with TCP is supported */
        switch (hdr.ipv4->version) {
@@ -8308,14 +8267,53 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
 static int ixgbe_delete_clsu32(struct ixgbe_adapter *adapter,
                               struct tc_cls_u32_offload *cls)
 {
+       u32 hdl = cls->knode.handle;
        u32 uhtid = TC_U32_USERHTID(cls->knode.handle);
-       u32 loc;
-       int err;
+       u32 loc = cls->knode.handle & 0xfffff;
+       int err = 0, i, j;
+       struct ixgbe_jump_table *jump = NULL;
+
+       if (loc > IXGBE_MAX_HW_ENTRIES)
+               return -EINVAL;
 
        if ((uhtid != 0x800) && (uhtid >= IXGBE_MAX_LINK_HANDLE))
                return -EINVAL;
 
-       loc = cls->knode.handle & 0xfffff;
+       /* Clear this filter in the link data it is associated with */
+       if (uhtid != 0x800) {
+               jump = adapter->jump_tables[uhtid];
+               if (!jump)
+                       return -EINVAL;
+               if (!test_bit(loc - 1, jump->child_loc_map))
+                       return -EINVAL;
+               clear_bit(loc - 1, jump->child_loc_map);
+       }
+
+       /* Check if the filter being deleted is a link */
+       for (i = 1; i < IXGBE_MAX_LINK_HANDLE; i++) {
+               jump = adapter->jump_tables[i];
+               if (jump && jump->link_hdl == hdl) {
+                       /* Delete filters in the hardware in the child hash
+                        * table associated with this link
+                        */
+                       for (j = 0; j < IXGBE_MAX_HW_ENTRIES; j++) {
+                               if (!test_bit(j, jump->child_loc_map))
+                                       continue;
+                               spin_lock(&adapter->fdir_perfect_lock);
+                               err = ixgbe_update_ethtool_fdir_entry(adapter,
+                                                                     NULL,
+                                                                     j + 1);
+                               spin_unlock(&adapter->fdir_perfect_lock);
+                               clear_bit(j, jump->child_loc_map);
+                       }
+                       /* Remove resources for this link */
+                       kfree(jump->input);
+                       kfree(jump->mask);
+                       kfree(jump);
+                       adapter->jump_tables[i] = NULL;
+                       return err;
+               }
+       }
 
        spin_lock(&adapter->fdir_perfect_lock);
        err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, loc);
@@ -8549,6 +8547,18 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
                if (!test_bit(link_uhtid - 1, &adapter->tables))
                        return err;
 
+               /* Multiple filters as links to the same hash table are not
+                * supported. To add a new filter with the same next header
+                * but different match/jump conditions, create a new hash table
+                * and link to it.
+                */
+               if (adapter->jump_tables[link_uhtid] &&
+                   (adapter->jump_tables[link_uhtid])->link_hdl) {
+                       e_err(drv, "Link filter exists for link: %x\n",
+                             link_uhtid);
+                       return err;
+               }
+
                for (i = 0; nexthdr[i].jump; i++) {
                        if (nexthdr[i].o != cls->knode.sel->offoff ||
                            nexthdr[i].s != cls->knode.sel->offshift ||
@@ -8570,6 +8580,8 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
                        }
                        jump->input = input;
                        jump->mask = mask;
+                       jump->link_hdl = cls->knode.handle;
+
                        err = ixgbe_clsu32_build_input(input, mask, cls,
                                                       field_ptr, &nexthdr[i]);
                        if (!err) {
@@ -8597,6 +8609,20 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
                if ((adapter->jump_tables[uhtid])->mask)
                        memcpy(mask, (adapter->jump_tables[uhtid])->mask,
                               sizeof(*mask));
+
+               /* Lookup in all child hash tables if this location is already
+                * filled with a filter
+                */
+               for (i = 1; i < IXGBE_MAX_LINK_HANDLE; i++) {
+                       struct ixgbe_jump_table *link = adapter->jump_tables[i];
+
+                       if (link && (test_bit(loc - 1, link->child_loc_map))) {
+                               e_err(drv, "Filter exists in location: %x\n",
+                                     loc);
+                               err = -EINVAL;
+                               goto err_out;
+                       }
+               }
        }
        err = ixgbe_clsu32_build_input(input, mask, cls, field_ptr, NULL);
        if (err)
@@ -8628,6 +8654,9 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
                ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
        spin_unlock(&adapter->fdir_perfect_lock);
 
+       if ((uhtid != 0x800) && (adapter->jump_tables[uhtid]))
+               set_bit(loc - 1, (adapter->jump_tables[uhtid])->child_loc_map);
+
        kfree(mask);
        return err;
 err_out_w_lock:
@@ -8770,14 +8799,12 @@ static int ixgbe_set_features(struct net_device *netdev,
 
        netdev->features = features;
 
-#ifdef CONFIG_IXGBE_VXLAN
        if ((adapter->flags & IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE)) {
                if (features & NETIF_F_RXCSUM)
                        adapter->flags2 |= IXGBE_FLAG2_VXLAN_REREG_NEEDED;
                else
                        ixgbe_clear_vxlan_port(adapter);
        }
-#endif /* CONFIG_IXGBE_VXLAN */
 
        if (need_reset)
                ixgbe_do_reset(netdev);
@@ -8788,23 +8815,25 @@ static int ixgbe_set_features(struct net_device *netdev,
        return 0;
 }
 
-#ifdef CONFIG_IXGBE_VXLAN
 /**
  * ixgbe_add_vxlan_port - Get notifications about VXLAN ports that come up
  * @dev: The port's netdev
- * @sa_family: Socket Family that VXLAN is notifiying us about
- * @port: New UDP port number that VXLAN started listening to
+ * @ti: Tunnel endpoint information
  **/
-static void ixgbe_add_vxlan_port(struct net_device *dev, sa_family_t sa_family,
-                                __be16 port)
+static void ixgbe_add_vxlan_port(struct net_device *dev,
+                                struct udp_tunnel_info *ti)
 {
        struct ixgbe_adapter *adapter = netdev_priv(dev);
        struct ixgbe_hw *hw = &adapter->hw;
+       __be16 port = ti->port;
 
-       if (!(adapter->flags & IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE))
+       if (ti->type != UDP_TUNNEL_TYPE_VXLAN)
+               return;
+
+       if (ti->sa_family != AF_INET)
                return;
 
-       if (sa_family == AF_INET6)
+       if (!(adapter->flags & IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE))
                return;
 
        if (adapter->vxlan_port == port)
@@ -8824,30 +8853,31 @@ static void ixgbe_add_vxlan_port(struct net_device *dev, sa_family_t sa_family,
 /**
  * ixgbe_del_vxlan_port - Get notifications about VXLAN ports that go away
  * @dev: The port's netdev
- * @sa_family: Socket Family that VXLAN is notifying us about
- * @port: UDP port number that VXLAN stopped listening to
+ * @ti: Tunnel endpoint information
  **/
-static void ixgbe_del_vxlan_port(struct net_device *dev, sa_family_t sa_family,
-                                __be16 port)
+static void ixgbe_del_vxlan_port(struct net_device *dev,
+                                struct udp_tunnel_info *ti)
 {
        struct ixgbe_adapter *adapter = netdev_priv(dev);
 
-       if (!(adapter->flags & IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE))
+       if (ti->type != UDP_TUNNEL_TYPE_VXLAN)
+               return;
+
+       if (ti->sa_family != AF_INET)
                return;
 
-       if (sa_family == AF_INET6)
+       if (!(adapter->flags & IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE))
                return;
 
-       if (adapter->vxlan_port != port) {
+       if (adapter->vxlan_port != ti->port) {
                netdev_info(dev, "Port %d was not found, not deleting\n",
-                           ntohs(port));
+                           ntohs(ti->port));
                return;
        }
 
        ixgbe_clear_vxlan_port(adapter);
        adapter->flags2 |= IXGBE_FLAG2_VXLAN_REREG_NEEDED;
 }
-#endif /* CONFIG_IXGBE_VXLAN */
 
 static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
                             struct net_device *dev,
@@ -9160,10 +9190,8 @@ static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_bridge_getlink     = ixgbe_ndo_bridge_getlink,
        .ndo_dfwd_add_station   = ixgbe_fwd_add,
        .ndo_dfwd_del_station   = ixgbe_fwd_del,
-#ifdef CONFIG_IXGBE_VXLAN
-       .ndo_add_vxlan_port     = ixgbe_add_vxlan_port,
-       .ndo_del_vxlan_port     = ixgbe_del_vxlan_port,
-#endif /* CONFIG_IXGBE_VXLAN */
+       .ndo_udp_tunnel_add     = ixgbe_add_vxlan_port,
+       .ndo_udp_tunnel_del     = ixgbe_del_vxlan_port,
        .ndo_features_check     = ixgbe_features_check,
 };
 
@@ -9331,8 +9359,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                pci_using_dac = 0;
        }
 
-       err = pci_request_selected_regions(pdev, pci_select_bars(pdev,
-                                          IORESOURCE_MEM), ixgbe_driver_name);
+       err = pci_request_mem_regions(pdev, ixgbe_driver_name);
        if (err) {
                dev_err(&pdev->dev,
                        "pci_request_selected_regions failed 0x%x\n", err);
@@ -9496,6 +9523,7 @@ skip_sriov:
 
        /* copy netdev features into list of user selectable features */
        netdev->hw_features |= netdev->features |
+                              NETIF_F_HW_VLAN_CTAG_FILTER |
                               NETIF_F_HW_VLAN_CTAG_RX |
                               NETIF_F_HW_VLAN_CTAG_TX |
                               NETIF_F_RXALL |
@@ -9718,8 +9746,7 @@ err_ioremap:
        disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state);
        free_netdev(netdev);
 err_alloc_etherdev:
-       pci_release_selected_regions(pdev,
-                                    pci_select_bars(pdev, IORESOURCE_MEM));
+       pci_release_mem_regions(pdev);
 err_pci_reg:
 err_dma:
        if (!adapter || disable_dev)
@@ -9786,8 +9813,7 @@ static void ixgbe_remove(struct pci_dev *pdev)
 
 #endif
        iounmap(adapter->io_addr);
-       pci_release_selected_regions(pdev, pci_select_bars(pdev,
-                                    IORESOURCE_MEM));
+       pci_release_mem_regions(pdev);
 
        e_dev_info("complete\n");
 
@@ -10051,6 +10077,7 @@ static int __init ixgbe_init_module(void)
 
        ret = pci_register_driver(&ixgbe_driver);
        if (ret) {
+               destroy_workqueue(ixgbe_wq);
                ixgbe_dbg_exit();
                return ret;
        }