summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c')
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
index 933a7772a7a3..bb7f86c993e5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
@@ -135,6 +135,16 @@ static void arfs_del_rules(struct mlx5e_flow_steering *fs);
int mlx5e_arfs_disable(struct mlx5e_flow_steering *fs)
{
+ /* Moving to switchdev mode, fs->arfs is freed by mlx5e_nic_profile
+ * cleanup_rx callback and it is not recreated when
+ * mlx5e_uplink_rep_profile is loaded as mlx5e_create_flow_steering()
+ * is not called by the uplink_rep profile init_rx callback. Thus, if
+ * ntuple is set, moving to switchdev flow will enter this function
+ * with fs->arfs nullified.
+ */
+ if (!mlx5e_fs_get_arfs(fs))
+ return 0;
+
arfs_del_rules(fs);
return arfs_disable(fs);
@@ -422,8 +432,10 @@ static void arfs_may_expire_flow(struct mlx5e_priv *priv)
}
spin_unlock_bh(&arfs->arfs_lock);
hlist_for_each_entry_safe(arfs_rule, htmp, &del_list, hlist) {
- if (arfs_rule->rule)
+ if (arfs_rule->rule) {
mlx5_del_flow_rules(arfs_rule->rule);
+ priv->channel_stats[arfs_rule->rxq]->rq.arfs_expired++;
+ }
hlist_del(&arfs_rule->hlist);
kfree(arfs_rule);
}
@@ -499,6 +511,7 @@ static struct mlx5_flow_handle *arfs_add_rule(struct mlx5e_priv *priv,
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec) {
+ priv->channel_stats[arfs_rule->rxq]->rq.arfs_err++;
err = -ENOMEM;
goto out;
}
@@ -509,6 +522,8 @@ static struct mlx5_flow_handle *arfs_add_rule(struct mlx5e_priv *priv,
ntohs(tuple->etype));
arfs_table = arfs_get_table(arfs, tuple->ip_proto, tuple->etype);
if (!arfs_table) {
+ WARN_ONCE(1, "arfs table does not exist for etype %u and ip_proto %u\n",
+ tuple->etype, tuple->ip_proto);
err = -EINVAL;
goto out;
}
@@ -590,9 +605,11 @@ static void arfs_modify_rule_rq(struct mlx5e_priv *priv,
dst.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
dst.tir_num = mlx5e_rx_res_get_tirn_direct(priv->rx_res, rxq);
err = mlx5_modify_rule_destination(rule, &dst, NULL);
- if (err)
+ if (err) {
+ priv->channel_stats[rxq]->rq.arfs_err++;
netdev_warn(priv->netdev,
"Failed to modify aRFS rule destination to rq=%d\n", rxq);
+ }
}
static void arfs_handle_work(struct work_struct *work)
@@ -622,6 +639,7 @@ static void arfs_handle_work(struct work_struct *work)
if (IS_ERR(rule))
goto out;
arfs_rule->rule = rule;
+ priv->channel_stats[arfs_rule->rxq]->rq.arfs_add++;
} else {
arfs_modify_rule_rq(priv, arfs_rule->rule,
arfs_rule->rxq);
@@ -640,8 +658,10 @@ static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
struct arfs_tuple *tuple;
rule = kzalloc(sizeof(*rule), GFP_ATOMIC);
- if (!rule)
+ if (!rule) {
+ priv->channel_stats[rxq]->rq.arfs_err++;
return NULL;
+ }
rule->priv = priv;
rule->rxq = rxq;
@@ -730,10 +750,13 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
spin_lock_bh(&arfs->arfs_lock);
arfs_rule = arfs_find_rule(arfs_t, &fk);
if (arfs_rule) {
- if (arfs_rule->rxq == rxq_index) {
+ if (arfs_rule->rxq == rxq_index || work_busy(&arfs_rule->arfs_work)) {
spin_unlock_bh(&arfs->arfs_lock);
return arfs_rule->filter_id;
}
+
+ priv->channel_stats[rxq_index]->rq.arfs_request_in++;
+ priv->channel_stats[arfs_rule->rxq]->rq.arfs_request_out++;
arfs_rule->rxq = rxq_index;
} else {
arfs_rule = arfs_alloc_rule(priv, arfs_t, &fk, rxq_index, flow_id);