Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next...
authorJakub Kicinski <kuba@kernel.org>
Tue, 23 Aug 2022 03:10:49 +0000 (20:10 -0700)
committerJakub Kicinski <kuba@kernel.org>
Tue, 23 Aug 2022 03:10:50 +0000 (20:10 -0700)
Tony Nguyen says:

====================
Intel Wired LAN Driver Updates 2022-08-18 (ice)

This series contains updates to ice driver only.

Jesse and Anatolii add support for controlling FCS/CRC stripping via
ethtool.

Anirudh allows for 100M speeds on devices which support it.

Sylwester removes ucast_shared field and the associated dead code related
to it.

Mikael removes non-inclusive language from the driver.

* '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue:
  ice: remove non-inclusive language
  ice: Remove ucast_shared
  ice: Allow 100M speeds for some devices
  ice: Implement FCS/CRC and VLAN stripping co-existence policy
  ice: Implement control of FCS/CRC stripping
====================

Link: https://lore.kernel.org/r/20220818155207.996297-1-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1  2 
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ice/ice_switch.c

@@@ -1563,6 -1563,22 +1563,22 @@@ void ice_vsi_manage_rss_lut(struct ice_
  }
  
  /**
+  * ice_vsi_cfg_crc_strip - Configure CRC stripping for a VSI
+  * @vsi: VSI to be configured
+  * @disable: set to true to have FCS / CRC in the frame data
+  */
+ void ice_vsi_cfg_crc_strip(struct ice_vsi *vsi, bool disable)
+ {
+       int i;
+       ice_for_each_rxq(vsi, i)
+               if (disable)
+                       vsi->rx_rings[i]->flags |= ICE_RX_FLAGS_CRC_STRIP_DIS;
+               else
+                       vsi->rx_rings[i]->flags &= ~ICE_RX_FLAGS_CRC_STRIP_DIS;
+ }
+ /**
   * ice_vsi_cfg_rss_lut_key - Configure RSS params for a VSI
   * @vsi: VSI to be configured
   */
@@@ -3182,7 -3198,7 +3198,7 @@@ int ice_vsi_rebuild(struct ice_vsi *vsi
  
        pf = vsi->back;
        vtype = vsi->type;
 -      if (WARN_ON(vtype == ICE_VSI_VF) && !vsi->vf)
 +      if (WARN_ON(vtype == ICE_VSI_VF && !vsi->vf))
                return -EINVAL;
  
        ice_vsi_init_vlan_ops(vsi);
                         */
                        if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
                                ice_vsi_cfg_rss_lut_key(vsi);
+               /* disable or enable CRC stripping */
+               if (vsi->netdev)
+                       ice_vsi_cfg_crc_strip(vsi, !!(vsi->netdev->features &
+                                             NETIF_F_RXFCS));
                break;
        case ICE_VSI_VF:
                ret = ice_vsi_alloc_q_vectors(vsi);
@@@ -4063,11 -4085,7 +4085,11 @@@ int ice_vsi_del_vlan_zero(struct ice_vs
        if (err && err != -EEXIST)
                return err;
  
 -      return 0;
 +      /* when deleting the last VLAN filter, make sure to disable the VLAN
 +       * promisc mode so the filter isn't left by accident
 +       */
 +      return ice_clear_vsi_promisc(&vsi->back->hw, vsi->idx,
 +                                  ICE_MCAST_VLAN_PROMISC_BITS, 0);
  }
  
  /**
@@@ -267,10 -267,8 +267,10 @@@ static int ice_set_promisc(struct ice_v
                status = ice_fltr_set_vsi_promisc(&vsi->back->hw, vsi->idx,
                                                  promisc_m, 0);
        }
 +      if (status && status != -EEXIST)
 +              return status;
  
 -      return status;
 +      return 0;
  }
  
  /**
@@@ -3376,6 -3374,11 +3376,11 @@@ static void ice_set_netdev_features(str
        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;
  }
  
  /**
@@@ -3575,14 -3578,6 +3580,14 @@@ ice_vlan_rx_kill_vid(struct net_device 
        while (test_and_set_bit(ICE_CFG_BUSY, vsi->state))
                usleep_range(1000, 2000);
  
 +      ret = ice_clear_vsi_promisc(&vsi->back->hw, vsi->idx,
 +                                  ICE_MCAST_VLAN_PROMISC_BITS, vid);
 +      if (ret) {
 +              netdev_err(netdev, "Error clearing multicast promiscuous mode on VSI %i\n",
 +                         vsi->vsi_num);
 +              vsi->current_netdev_flags |= IFF_ALLMULTI;
 +      }
 +
        vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
  
        /* Make sure VLAN delete is successful before updating VLAN
@@@ -4667,8 -4662,6 +4672,6 @@@ ice_probe(struct pci_dev *pdev, const s
                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 -5720,9 +5730,9 @@@ ice_fdb_del(struct ndmsg *ndm, __always
                                         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 -5809,14 +5819,14 @@@ ice_fix_features(struct net_device *net
                              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 -5910,13 +5920,13 @@@ ice_set_vlan_features(struct net_devic
        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 -5998,23 +6008,23 @@@ ice_set_features(struct net_device *net
        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);
  
@@@ -6691,6 -6719,31 +6729,31 @@@ int ice_down(struct ice_vsi *vsi
  }
  
  /**
+  * 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
   *
@@@ -3449,31 -3449,15 +3449,15 @@@ bool ice_vlan_fltr_exist(struct ice_hw 
   * ice_add_mac - Add a MAC address based filter rule
   * @hw: pointer to the hardware structure
   * @m_list: list of MAC addresses and forwarding information
-  *
-  * IMPORTANT: When the ucast_shared flag is set to false and m_list has
-  * multiple unicast addresses, the function assumes that all the
-  * addresses are unique in a given add_mac call. It doesn't
-  * check for duplicates in this case, removing duplicates from a given
-  * list should be taken care of in the caller of this function.
   */
  int ice_add_mac(struct ice_hw *hw, struct list_head *m_list)
  {
-       struct ice_sw_rule_lkup_rx_tx *s_rule, *r_iter;
        struct ice_fltr_list_entry *m_list_itr;
-       struct list_head *rule_head;
-       u16 total_elem_left, s_rule_size;
-       struct ice_switch_info *sw;
-       struct mutex *rule_lock; /* Lock to protect filter rule list */
-       u16 num_unicast = 0;
        int status = 0;
-       u8 elem_sent;
  
        if (!m_list || !hw)
                return -EINVAL;
  
-       s_rule = NULL;
-       sw = hw->switch_info;
-       rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
        list_for_each_entry(m_list_itr, m_list, list_entry) {
                u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
                u16 vsi_handle;
                if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC ||
                    is_zero_ether_addr(add))
                        return -EINVAL;
-               if (is_unicast_ether_addr(add) && !hw->ucast_shared) {
-                       /* Don't overwrite the unicast address */
-                       mutex_lock(rule_lock);
-                       if (ice_find_rule_entry(hw, ICE_SW_LKUP_MAC,
-                                               &m_list_itr->fltr_info)) {
-                               mutex_unlock(rule_lock);
-                               return -EEXIST;
-                       }
-                       mutex_unlock(rule_lock);
-                       num_unicast++;
-               } else if (is_multicast_ether_addr(add) ||
-                          (is_unicast_ether_addr(add) && hw->ucast_shared)) {
-                       m_list_itr->status =
-                               ice_add_rule_internal(hw, ICE_SW_LKUP_MAC,
-                                                     m_list_itr);
-                       if (m_list_itr->status)
-                               return m_list_itr->status;
-               }
-       }
-       mutex_lock(rule_lock);
-       /* Exit if no suitable entries were found for adding bulk switch rule */
-       if (!num_unicast) {
-               status = 0;
-               goto ice_add_mac_exit;
-       }
-       rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
-       /* Allocate switch rule buffer for the bulk update for unicast */
-       s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule);
-       s_rule = devm_kcalloc(ice_hw_to_dev(hw), num_unicast, s_rule_size,
-                             GFP_KERNEL);
-       if (!s_rule) {
-               status = -ENOMEM;
-               goto ice_add_mac_exit;
-       }
-       r_iter = s_rule;
-       list_for_each_entry(m_list_itr, m_list, list_entry) {
-               struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
-               u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
-               if (is_unicast_ether_addr(mac_addr)) {
-                       ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter,
-                                        ice_aqc_opc_add_sw_rules);
-                       r_iter = (typeof(s_rule))((u8 *)r_iter + s_rule_size);
-               }
-       }
-       /* Call AQ bulk switch rule update for all unicast addresses */
-       r_iter = s_rule;
-       /* Call AQ switch rule in AQ_MAX chunk */
-       for (total_elem_left = num_unicast; total_elem_left > 0;
-            total_elem_left -= elem_sent) {
-               struct ice_sw_rule_lkup_rx_tx *entry = r_iter;
-               elem_sent = min_t(u8, total_elem_left,
-                                 (ICE_AQ_MAX_BUF_LEN / s_rule_size));
-               status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size,
-                                        elem_sent, ice_aqc_opc_add_sw_rules,
-                                        NULL);
-               if (status)
-                       goto ice_add_mac_exit;
-               r_iter = (typeof(s_rule))
-                       ((u8 *)r_iter + (elem_sent * s_rule_size));
-       }
-       /* Fill up rule ID based on the value returned from FW */
-       r_iter = s_rule;
-       list_for_each_entry(m_list_itr, m_list, list_entry) {
-               struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
-               u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
-               struct ice_fltr_mgmt_list_entry *fm_entry;
-               if (is_unicast_ether_addr(mac_addr)) {
-                       f_info->fltr_rule_id = le16_to_cpu(r_iter->index);
-                       f_info->fltr_act = ICE_FWD_TO_VSI;
-                       /* Create an entry to track this MAC address */
-                       fm_entry = devm_kzalloc(ice_hw_to_dev(hw),
-                                               sizeof(*fm_entry), GFP_KERNEL);
-                       if (!fm_entry) {
-                               status = -ENOMEM;
-                               goto ice_add_mac_exit;
-                       }
-                       fm_entry->fltr_info = *f_info;
-                       fm_entry->vsi_count = 1;
-                       /* The book keeping entries will get removed when
-                        * base driver calls remove filter AQ command
-                        */
  
-                       list_add(&fm_entry->list_entry, rule_head);
-                       r_iter = (typeof(s_rule))((u8 *)r_iter + s_rule_size);
-               }
+               m_list_itr->status = ice_add_rule_internal(hw, ICE_SW_LKUP_MAC,
+                                                          m_list_itr);
+               if (m_list_itr->status)
+                       return m_list_itr->status;
        }
  
- ice_add_mac_exit:
-       mutex_unlock(rule_lock);
-       if (s_rule)
-               devm_kfree(ice_hw_to_dev(hw), s_rule);
        return status;
  }
  
@@@ -3979,38 -3870,6 +3870,6 @@@ ice_check_if_dflt_vsi(struct ice_port_i
  }
  
  /**
-  * ice_find_ucast_rule_entry - Search for a unicast MAC filter rule entry
-  * @hw: pointer to the hardware structure
-  * @recp_id: lookup type for which the specified rule needs to be searched
-  * @f_info: rule information
-  *
-  * Helper function to search for a unicast rule entry - this is to be used
-  * to remove unicast MAC filter that is not shared with other VSIs on the
-  * PF switch.
-  *
-  * Returns pointer to entry storing the rule if found
-  */
- static struct ice_fltr_mgmt_list_entry *
- ice_find_ucast_rule_entry(struct ice_hw *hw, u8 recp_id,
-                         struct ice_fltr_info *f_info)
- {
-       struct ice_switch_info *sw = hw->switch_info;
-       struct ice_fltr_mgmt_list_entry *list_itr;
-       struct list_head *list_head;
-       list_head = &sw->recp_list[recp_id].filt_rules;
-       list_for_each_entry(list_itr, list_head, list_entry) {
-               if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
-                           sizeof(f_info->l_data)) &&
-                   f_info->fwd_id.hw_vsi_id ==
-                   list_itr->fltr_info.fwd_id.hw_vsi_id &&
-                   f_info->flag == list_itr->fltr_info.flag)
-                       return list_itr;
-       }
-       return NULL;
- }
- /**
   * ice_remove_mac - remove a MAC address based filter rule
   * @hw: pointer to the hardware structure
   * @m_list: list of MAC addresses and forwarding information
  int ice_remove_mac(struct ice_hw *hw, struct list_head *m_list)
  {
        struct ice_fltr_list_entry *list_itr, *tmp;
-       struct mutex *rule_lock; /* Lock to protect filter rule list */
  
        if (!m_list)
                return -EINVAL;
  
-       rule_lock = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
        list_for_each_entry_safe(list_itr, tmp, m_list, list_entry) {
                enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type;
-               u8 *add = &list_itr->fltr_info.l_data.mac.mac_addr[0];
                u16 vsi_handle;
  
                if (l_type != ICE_SW_LKUP_MAC)
  
                list_itr->fltr_info.fwd_id.hw_vsi_id =
                                        ice_get_hw_vsi_num(hw, vsi_handle);
-               if (is_unicast_ether_addr(add) && !hw->ucast_shared) {
-                       /* Don't remove the unicast address that belongs to
-                        * another VSI on the switch, since it is not being
-                        * shared...
-                        */
-                       mutex_lock(rule_lock);
-                       if (!ice_find_ucast_rule_entry(hw, ICE_SW_LKUP_MAC,
-                                                      &list_itr->fltr_info)) {
-                               mutex_unlock(rule_lock);
-                               return -ENOENT;
-                       }
-                       mutex_unlock(rule_lock);
-               }
                list_itr->status = ice_remove_rule_internal(hw,
                                                            ICE_SW_LKUP_MAC,
                                                            list_itr);
@@@ -4445,13 -4289,6 +4289,13 @@@ ice_set_vlan_vsi_promisc(struct ice_hw 
                goto free_fltr_list;
  
        list_for_each_entry(list_itr, &vsi_list_head, list_entry) {
 +              /* Avoid enabling or disabling VLAN zero twice when in double
 +               * VLAN mode
 +               */
 +              if (ice_is_dvm_ena(hw) &&
 +                  list_itr->fltr_info.l_data.vlan.tpid == 0)
 +                      continue;
 +
                vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id;
                if (rm_vlan_promisc)
                        status = ice_clear_vsi_promisc(hw, vsi_handle,
                else
                        status = ice_set_vsi_promisc(hw, vsi_handle,
                                                     promisc_mask, vlan_id);
 -              if (status)
 +              if (status && status != -EEXIST)
                        break;
        }