mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 10:33:41 +02:00
iavf: refactor add/del FDIR filters
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>
This commit is contained in:
parent
99f419df8a
commit
995617dccc
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
err = iavf_fdir_add_fltr(adapter, 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 (adapter->link_up)
|
||||
iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_ADD_FDIR_FILTER);
|
||||
ret:
|
||||
if (err && fltr)
|
||||
kfree(fltr);
|
||||
|
||||
mutex_unlock(&adapter->crit_lock);
|
||||
|
|
@ -1324,34 +1303,11 @@ static int iavf_add_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
|
|||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user