iavf: refactor add/del FDIR filters
authorAhmed Zaki <ahmed.zaki@intel.com>
Thu, 25 Jul 2024 22:08:08 +0000 (16:08 -0600)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Tue, 13 Aug 2024 21:51:29 +0000 (14:51 -0700)
In preparation for a second type of FDIR filters that can be added by
tc-u32, move the add/del of the FDIR logic to be entirely contained in
iavf_fdir.c.

The iavf_find_fdir_fltr_by_loc() is renamed to iavf_find_fdir_fltr()
to be more agnostic to the filter ID parameter (for now @loc, which is
relevant only to current FDIR filters added via ethtool).

The FDIR filter deletion is moved from iavf_del_fdir_ethtool() in
ethtool.c to iavf_fdir_del_fltr(). While at it, fix a minor bug where
the "fltr" is accessed out of the fdir_fltr_lock spinlock protection.

Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
Reviewed-by: Marcin Szycik <marcin.szycik@linux.intel.com>
Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/iavf/iavf.h
drivers/net/ethernet/intel/iavf/iavf_ethtool.c
drivers/net/ethernet/intel/iavf/iavf_fdir.c
drivers/net/ethernet/intel/iavf/iavf_fdir.h

index 23a6557fc3db2bd0621a3a92264c761171e7b7af..dfed22baebf8d5aad9fdb586f203f82afb0c2680 100644 (file)
@@ -444,6 +444,11 @@ struct iavf_adapter {
        spinlock_t adv_rss_lock;        /* protect the RSS management list */
 };
 
+/* Must be called with fdir_fltr_lock lock held */
+static inline bool iavf_fdir_max_reached(struct iavf_adapter *adapter)
+{
+       return adapter->fdir_active_fltr >= IAVF_MAX_FDIR_FILTERS;
+}
 
 /* Ethtool Private Flags */
 
index 52273f7eab2c4eeab5ebbb3b5876809cd552a374..7ab445eeee18cba8781dc456c2507a9bb5a9bc5c 100644 (file)
@@ -927,7 +927,7 @@ iavf_get_ethtool_fdir_entry(struct iavf_adapter *adapter,
 
        spin_lock_bh(&adapter->fdir_fltr_lock);
 
-       rule = iavf_find_fdir_fltr_by_loc(adapter, fsp->location);
+       rule = iavf_find_fdir_fltr(adapter, fsp->location);
        if (!rule) {
                ret = -EINVAL;
                goto release_lock;
@@ -1263,15 +1263,7 @@ static int iavf_add_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
                return -EINVAL;
 
        spin_lock_bh(&adapter->fdir_fltr_lock);
-       if (adapter->fdir_active_fltr >= IAVF_MAX_FDIR_FILTERS) {
-               spin_unlock_bh(&adapter->fdir_fltr_lock);
-               dev_err(&adapter->pdev->dev,
-                       "Unable to add Flow Director filter because VF reached the limit of max allowed filters (%u)\n",
-                       IAVF_MAX_FDIR_FILTERS);
-               return -ENOSPC;
-       }
-
-       if (iavf_find_fdir_fltr_by_loc(adapter, fsp->location)) {
+       if (iavf_find_fdir_fltr(adapter, fsp->location)) {
                dev_err(&adapter->pdev->dev, "Failed to add Flow Director filter, it already exists\n");
                spin_unlock_bh(&adapter->fdir_fltr_lock);
                return -EEXIST;
@@ -1291,23 +1283,10 @@ static int iavf_add_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
        }
 
        err = iavf_add_fdir_fltr_info(adapter, fsp, fltr);
-       if (err)
-               goto ret;
-
-       spin_lock_bh(&adapter->fdir_fltr_lock);
-       iavf_fdir_list_add_fltr(adapter, fltr);
-       adapter->fdir_active_fltr++;
-
-       if (adapter->link_up)
-               fltr->state = IAVF_FDIR_FLTR_ADD_REQUEST;
-       else
-               fltr->state = IAVF_FDIR_FLTR_INACTIVE;
-       spin_unlock_bh(&adapter->fdir_fltr_lock);
+       if (!err)
+               err = iavf_fdir_add_fltr(adapter, fltr);
 
-       if (adapter->link_up)
-               iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_ADD_FDIR_FILTER);
-ret:
-       if (err && fltr)
+       if (err)
                kfree(fltr);
 
        mutex_unlock(&adapter->crit_lock);
@@ -1324,34 +1303,11 @@ ret:
 static int iavf_del_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rxnfc *cmd)
 {
        struct ethtool_rx_flow_spec *fsp = (struct ethtool_rx_flow_spec *)&cmd->fs;
-       struct iavf_fdir_fltr *fltr = NULL;
-       int err = 0;
 
        if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED))
                return -EOPNOTSUPP;
 
-       spin_lock_bh(&adapter->fdir_fltr_lock);
-       fltr = iavf_find_fdir_fltr_by_loc(adapter, fsp->location);
-       if (fltr) {
-               if (fltr->state == IAVF_FDIR_FLTR_ACTIVE) {
-                       fltr->state = IAVF_FDIR_FLTR_DEL_REQUEST;
-               } else if (fltr->state == IAVF_FDIR_FLTR_INACTIVE) {
-                       list_del(&fltr->list);
-                       kfree(fltr);
-                       adapter->fdir_active_fltr--;
-                       fltr = NULL;
-               } else {
-                       err = -EBUSY;
-               }
-       } else if (adapter->fdir_active_fltr) {
-               err = -EINVAL;
-       }
-       spin_unlock_bh(&adapter->fdir_fltr_lock);
-
-       if (fltr && fltr->state == IAVF_FDIR_FLTR_DEL_REQUEST)
-               iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_DEL_FDIR_FILTER);
-
-       return err;
+       return iavf_fdir_del_fltr(adapter, fsp->location);
 }
 
 /**
index 2d47b0b4640e4a05c116a5fb5e4b6644b490cc47..1e1daf71dfa049db17e1efc7f234935658d43003 100644 (file)
@@ -815,13 +815,14 @@ bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *
 }
 
 /**
- * iavf_find_fdir_fltr_by_loc - find filter with location
+ * iavf_find_fdir_fltr - find FDIR filter
  * @adapter: pointer to the VF adapter structure
  * @loc: location to find.
  *
- * Returns pointer to Flow Director filter if found or null
+ * Returns: pointer to Flow Director filter if found or NULL. Lock must be held.
  */
-struct iavf_fdir_fltr *iavf_find_fdir_fltr_by_loc(struct iavf_adapter *adapter, u32 loc)
+struct iavf_fdir_fltr *iavf_find_fdir_fltr(struct iavf_adapter *adapter,
+                                          u32 loc)
 {
        struct iavf_fdir_fltr *rule;
 
@@ -833,14 +834,26 @@ struct iavf_fdir_fltr *iavf_find_fdir_fltr_by_loc(struct iavf_adapter *adapter,
 }
 
 /**
- * iavf_fdir_list_add_fltr - add a new node to the flow director filter list
+ * iavf_fdir_add_fltr - add a new node to the flow director filter list
  * @adapter: pointer to the VF adapter structure
  * @fltr: filter node to add to structure
+ *
+ * Return: 0 on success or negative errno on failure.
  */
-void iavf_fdir_list_add_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr)
+int iavf_fdir_add_fltr(struct iavf_adapter *adapter,
+                      struct iavf_fdir_fltr *fltr)
 {
        struct iavf_fdir_fltr *rule, *parent = NULL;
 
+       spin_lock_bh(&adapter->fdir_fltr_lock);
+       if (iavf_fdir_max_reached(adapter)) {
+               spin_unlock_bh(&adapter->fdir_fltr_lock);
+               dev_err(&adapter->pdev->dev,
+                       "Unable to add Flow Director filter (limit (%u) reached)\n",
+                       IAVF_MAX_FDIR_FILTERS);
+               return -ENOSPC;
+       }
+
        list_for_each_entry(rule, &adapter->fdir_list_head, list) {
                if (rule->loc >= fltr->loc)
                        break;
@@ -851,4 +864,53 @@ void iavf_fdir_list_add_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr
                list_add(&fltr->list, &parent->list);
        else
                list_add(&fltr->list, &adapter->fdir_list_head);
+       adapter->fdir_active_fltr++;
+
+       if (adapter->link_up)
+               fltr->state = IAVF_FDIR_FLTR_ADD_REQUEST;
+       else
+               fltr->state = IAVF_FDIR_FLTR_INACTIVE;
+       spin_unlock_bh(&adapter->fdir_fltr_lock);
+
+       if (adapter->link_up)
+               iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_ADD_FDIR_FILTER);
+
+       return 0;
+}
+
+/**
+ * iavf_fdir_del_fltr - delete a flow director filter from the list
+ * @adapter: pointer to the VF adapter structure
+ * @loc: location to delete.
+ *
+ * Return: 0 on success or negative errno on failure.
+ */
+int iavf_fdir_del_fltr(struct iavf_adapter *adapter, u32 loc)
+{
+       struct iavf_fdir_fltr *fltr = NULL;
+       int err = 0;
+
+       spin_lock_bh(&adapter->fdir_fltr_lock);
+       fltr = iavf_find_fdir_fltr(adapter, loc);
+
+       if (fltr) {
+               if (fltr->state == IAVF_FDIR_FLTR_ACTIVE) {
+                       fltr->state = IAVF_FDIR_FLTR_DEL_REQUEST;
+               } else if (fltr->state == IAVF_FDIR_FLTR_INACTIVE) {
+                       list_del(&fltr->list);
+                       kfree(fltr);
+                       adapter->fdir_active_fltr--;
+                       fltr = NULL;
+               } else {
+                       err = -EBUSY;
+               }
+       } else if (adapter->fdir_active_fltr) {
+               err = -EINVAL;
+       }
+
+       if (fltr && fltr->state == IAVF_FDIR_FLTR_DEL_REQUEST)
+               iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_DEL_FDIR_FILTER);
+
+       spin_unlock_bh(&adapter->fdir_fltr_lock);
+       return err;
 }
index d31bd923ba8cbf2d86272f6955847cc92d2db5e6..5c85eb25fa2a899fca2480c3e907352c0db6a78c 100644 (file)
@@ -128,6 +128,9 @@ int iavf_validate_fdir_fltr_masks(struct iavf_adapter *adapter,
 int iavf_fill_fdir_add_msg(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
 void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
 bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
-void iavf_fdir_list_add_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
-struct iavf_fdir_fltr *iavf_find_fdir_fltr_by_loc(struct iavf_adapter *adapter, u32 loc);
+int iavf_fdir_add_fltr(struct iavf_adapter *adapter,
+                      struct iavf_fdir_fltr *fltr);
+int iavf_fdir_del_fltr(struct iavf_adapter *adapter, u32 loc);
+struct iavf_fdir_fltr *iavf_find_fdir_fltr(struct iavf_adapter *adapter,
+                                          u32 loc);
 #endif /* _IAVF_FDIR_H_ */