Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next...
[linux-block.git] / drivers / net / ethernet / intel / ice / ice_main.c
index 4ecaf40cf946b317779ff856edc7b003765716fe..223a7507af7b74c44697a76a146df02b4a09acd4 100644 (file)
@@ -3376,6 +3376,11 @@ static void ice_set_netdev_features(struct net_device *netdev)
        if (is_dvm_ena)
                netdev->hw_features |= NETIF_F_HW_VLAN_STAG_RX |
                        NETIF_F_HW_VLAN_STAG_TX;
+
+       /* Leave CRC / FCS stripping enabled by default, but allow the value to
+        * be changed at runtime
+        */
+       netdev->hw_features |= NETIF_F_RXFCS;
 }
 
 /**
@@ -4667,8 +4672,6 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
                ice_set_safe_mode_caps(hw);
        }
 
-       hw->ucast_shared = true;
-
        err = ice_init_pf(pf);
        if (err) {
                dev_err(dev, "ice_init_pf failed: %d\n", err);
@@ -5727,6 +5730,9 @@ ice_fdb_del(struct ndmsg *ndm, __always_unused struct nlattr *tb[],
                                         NETIF_F_HW_VLAN_STAG_RX | \
                                         NETIF_F_HW_VLAN_STAG_TX)
 
+#define NETIF_VLAN_STRIPPING_FEATURES  (NETIF_F_HW_VLAN_CTAG_RX | \
+                                        NETIF_F_HW_VLAN_STAG_RX)
+
 #define NETIF_VLAN_FILTERING_FEATURES  (NETIF_F_HW_VLAN_CTAG_FILTER | \
                                         NETIF_F_HW_VLAN_STAG_FILTER)
 
@@ -5813,6 +5819,14 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
                              NETIF_F_HW_VLAN_STAG_TX);
        }
 
+       if (!(netdev->features & NETIF_F_RXFCS) &&
+           (features & NETIF_F_RXFCS) &&
+           (features & NETIF_VLAN_STRIPPING_FEATURES) &&
+           !ice_vsi_has_non_zero_vlans(np->vsi)) {
+               netdev_warn(netdev, "Disabling VLAN stripping as FCS/CRC stripping is also disabled and there is no VLAN configured\n");
+               features &= ~NETIF_VLAN_STRIPPING_FEATURES;
+       }
+
        return features;
 }
 
@@ -5906,6 +5920,13 @@ ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
        current_vlan_features = netdev->features & NETIF_VLAN_OFFLOAD_FEATURES;
        requested_vlan_features = features & NETIF_VLAN_OFFLOAD_FEATURES;
        if (current_vlan_features ^ requested_vlan_features) {
+               if ((features & NETIF_F_RXFCS) &&
+                   (features & NETIF_VLAN_STRIPPING_FEATURES)) {
+                       dev_err(ice_pf_to_dev(vsi->back),
+                               "To enable VLAN stripping, you must first enable FCS/CRC stripping\n");
+                       return -EIO;
+               }
+
                err = ice_set_vlan_offload_features(vsi, features);
                if (err)
                        return err;
@@ -5987,6 +6008,23 @@ ice_set_features(struct net_device *netdev, netdev_features_t features)
        if (ret)
                return ret;
 
+       /* Turn on receive of FCS aka CRC, and after setting this
+        * flag the packet data will have the 4 byte CRC appended
+        */
+       if (changed & NETIF_F_RXFCS) {
+               if ((features & NETIF_F_RXFCS) &&
+                   (features & NETIF_VLAN_STRIPPING_FEATURES)) {
+                       dev_err(ice_pf_to_dev(vsi->back),
+                               "To disable FCS/CRC stripping, you must first disable VLAN stripping\n");
+                       return -EIO;
+               }
+
+               ice_vsi_cfg_crc_strip(vsi, !!(features & NETIF_F_RXFCS));
+               ret = ice_down_up(vsi);
+               if (ret)
+                       return ret;
+       }
+
        if (changed & NETIF_F_NTUPLE) {
                bool ena = !!(features & NETIF_F_NTUPLE);
 
@@ -6690,6 +6728,31 @@ int ice_down(struct ice_vsi *vsi)
        return 0;
 }
 
+/**
+ * ice_down_up - shutdown the VSI connection and bring it up
+ * @vsi: the VSI to be reconnected
+ */
+int ice_down_up(struct ice_vsi *vsi)
+{
+       int ret;
+
+       /* if DOWN already set, nothing to do */
+       if (test_and_set_bit(ICE_VSI_DOWN, vsi->state))
+               return 0;
+
+       ret = ice_down(vsi);
+       if (ret)
+               return ret;
+
+       ret = ice_up(vsi);
+       if (ret) {
+               netdev_err(vsi->netdev, "reallocating resources failed during netdev features change, may need to reload driver\n");
+               return ret;
+       }
+
+       return 0;
+}
+
 /**
  * ice_vsi_setup_tx_rings - Allocate VSI Tx queue resources
  * @vsi: VSI having resources allocated