diff options
Diffstat (limited to 'drivers/net/ethernet/netronome')
| -rw-r--r-- | drivers/net/ethernet/netronome/nfp/bpf/cmsg.c | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/netronome/nfp/flower/main.h | 8 | ||||
| -rw-r--r-- | drivers/net/ethernet/netronome/nfp/flower/metadata.c | 16 | ||||
| -rw-r--r-- | drivers/net/ethernet/netronome/nfp/flower/offload.c | 48 | 
4 files changed, 70 insertions, 3 deletions
| diff --git a/drivers/net/ethernet/netronome/nfp/bpf/cmsg.c b/drivers/net/ethernet/netronome/nfp/bpf/cmsg.c index 0e2db6ea79e9..2ec62c8d86e1 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/cmsg.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/cmsg.c @@ -454,6 +454,7 @@ void nfp_bpf_ctrl_msg_rx(struct nfp_app *app, struct sk_buff *skb)  			dev_consume_skb_any(skb);  		else  			dev_kfree_skb_any(skb); +		return;  	}  	nfp_ccm_rx(&bpf->ccm, skb); diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index caf12eec9945..56833a41f3d2 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -190,6 +190,7 @@ struct nfp_fl_internal_ports {   * @qos_rate_limiters:	Current active qos rate limiters   * @qos_stats_lock:	Lock on qos stats updates   * @pre_tun_rule_cnt:	Number of pre-tunnel rules offloaded + * @merge_table:	Hash table to store merged flows   */  struct nfp_flower_priv {  	struct nfp_app *app; @@ -223,6 +224,7 @@ struct nfp_flower_priv {  	unsigned int qos_rate_limiters;  	spinlock_t qos_stats_lock; /* Protect the qos stats */  	int pre_tun_rule_cnt; +	struct rhashtable merge_table;  };  /** @@ -350,6 +352,12 @@ struct nfp_fl_payload_link {  };  extern const struct rhashtable_params nfp_flower_table_params; +extern const struct rhashtable_params merge_table_params; + +struct nfp_merge_info { +	u64 parent_ctx; +	struct rhash_head ht_node; +};  struct nfp_fl_stats_frame {  	__be32 stats_con_id; diff --git a/drivers/net/ethernet/netronome/nfp/flower/metadata.c b/drivers/net/ethernet/netronome/nfp/flower/metadata.c index aa06fcb38f8b..327bb56b3ef5 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/metadata.c +++ b/drivers/net/ethernet/netronome/nfp/flower/metadata.c @@ -490,6 +490,12 @@ const struct rhashtable_params nfp_flower_table_params = {  	.automatic_shrinking	= true,  }; +const struct rhashtable_params merge_table_params = { +	.key_offset	= offsetof(struct nfp_merge_info, parent_ctx), +	.head_offset	= offsetof(struct nfp_merge_info, ht_node), +	.key_len	= sizeof(u64), +}; +  int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,  			     unsigned int host_num_mems)  { @@ -506,6 +512,10 @@ int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,  	if (err)  		goto err_free_flow_table; +	err = rhashtable_init(&priv->merge_table, &merge_table_params); +	if (err) +		goto err_free_stats_ctx_table; +  	get_random_bytes(&priv->mask_id_seed, sizeof(priv->mask_id_seed));  	/* Init ring buffer and unallocated mask_ids. */ @@ -513,7 +523,7 @@ int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,  		kmalloc_array(NFP_FLOWER_MASK_ENTRY_RS,  			      NFP_FLOWER_MASK_ELEMENT_RS, GFP_KERNEL);  	if (!priv->mask_ids.mask_id_free_list.buf) -		goto err_free_stats_ctx_table; +		goto err_free_merge_table;  	priv->mask_ids.init_unallocated = NFP_FLOWER_MASK_ENTRY_RS - 1; @@ -550,6 +560,8 @@ err_free_last_used:  	kfree(priv->mask_ids.last_used);  err_free_mask_id:  	kfree(priv->mask_ids.mask_id_free_list.buf); +err_free_merge_table: +	rhashtable_destroy(&priv->merge_table);  err_free_stats_ctx_table:  	rhashtable_destroy(&priv->stats_ctx_table);  err_free_flow_table: @@ -568,6 +580,8 @@ void nfp_flower_metadata_cleanup(struct nfp_app *app)  				    nfp_check_rhashtable_empty, NULL);  	rhashtable_free_and_destroy(&priv->stats_ctx_table,  				    nfp_check_rhashtable_empty, NULL); +	rhashtable_free_and_destroy(&priv->merge_table, +				    nfp_check_rhashtable_empty, NULL);  	kvfree(priv->stats);  	kfree(priv->mask_ids.mask_id_free_list.buf);  	kfree(priv->mask_ids.last_used); diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index d72225d64a75..e95969c462e4 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@ -1009,6 +1009,8 @@ int nfp_flower_merge_offloaded_flows(struct nfp_app *app,  	struct netlink_ext_ack *extack = NULL;  	struct nfp_fl_payload *merge_flow;  	struct nfp_fl_key_ls merge_key_ls; +	struct nfp_merge_info *merge_info; +	u64 parent_ctx = 0;  	int err;  	ASSERT_RTNL(); @@ -1019,6 +1021,15 @@ int nfp_flower_merge_offloaded_flows(struct nfp_app *app,  	    nfp_flower_is_merge_flow(sub_flow2))  		return -EINVAL; +	/* check if the two flows are already merged */ +	parent_ctx = (u64)(be32_to_cpu(sub_flow1->meta.host_ctx_id)) << 32; +	parent_ctx |= (u64)(be32_to_cpu(sub_flow2->meta.host_ctx_id)); +	if (rhashtable_lookup_fast(&priv->merge_table, +				   &parent_ctx, merge_table_params)) { +		nfp_flower_cmsg_warn(app, "The two flows are already merged.\n"); +		return 0; +	} +  	err = nfp_flower_can_merge(sub_flow1, sub_flow2);  	if (err)  		return err; @@ -1060,16 +1071,33 @@ int nfp_flower_merge_offloaded_flows(struct nfp_app *app,  	if (err)  		goto err_release_metadata; +	merge_info = kmalloc(sizeof(*merge_info), GFP_KERNEL); +	if (!merge_info) { +		err = -ENOMEM; +		goto err_remove_rhash; +	} +	merge_info->parent_ctx = parent_ctx; +	err = rhashtable_insert_fast(&priv->merge_table, &merge_info->ht_node, +				     merge_table_params); +	if (err) +		goto err_destroy_merge_info; +  	err = nfp_flower_xmit_flow(app, merge_flow,  				   NFP_FLOWER_CMSG_TYPE_FLOW_MOD);  	if (err) -		goto err_remove_rhash; +		goto err_remove_merge_info;  	merge_flow->in_hw = true;  	sub_flow1->in_hw = false;  	return 0; +err_remove_merge_info: +	WARN_ON_ONCE(rhashtable_remove_fast(&priv->merge_table, +					    &merge_info->ht_node, +					    merge_table_params)); +err_destroy_merge_info: +	kfree(merge_info);  err_remove_rhash:  	WARN_ON_ONCE(rhashtable_remove_fast(&priv->flow_table,  					    &merge_flow->fl_node, @@ -1359,7 +1387,9 @@ nfp_flower_remove_merge_flow(struct nfp_app *app,  {  	struct nfp_flower_priv *priv = app->priv;  	struct nfp_fl_payload_link *link, *temp; +	struct nfp_merge_info *merge_info;  	struct nfp_fl_payload *origin; +	u64 parent_ctx = 0;  	bool mod = false;  	int err; @@ -1396,8 +1426,22 @@ nfp_flower_remove_merge_flow(struct nfp_app *app,  err_free_links:  	/* Clean any links connected with the merged flow. */  	list_for_each_entry_safe(link, temp, &merge_flow->linked_flows, -				 merge_flow.list) +				 merge_flow.list) { +		u32 ctx_id = be32_to_cpu(link->sub_flow.flow->meta.host_ctx_id); + +		parent_ctx = (parent_ctx << 32) | (u64)(ctx_id);  		nfp_flower_unlink_flow(link); +	} + +	merge_info = rhashtable_lookup_fast(&priv->merge_table, +					    &parent_ctx, +					    merge_table_params); +	if (merge_info) { +		WARN_ON_ONCE(rhashtable_remove_fast(&priv->merge_table, +						    &merge_info->ht_node, +						    merge_table_params)); +		kfree(merge_info); +	}  	kfree(merge_flow->action_data);  	kfree(merge_flow->mask_data); |