11// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
22/* Copyright (c) 2025 NVIDIA Corporation & Affiliates */
33
4+ #include <linux/mlx5/vport.h>
45#include <mlx5_core.h>
56#include <fs_core.h>
67#include <fs_cmd.h>
@@ -63,6 +64,8 @@ static int mlx5_fs_init_hws_actions_pool(struct mlx5_core_dev *dev,
6364 xa_init (& hws_pool -> el2tol2tnl_pools );
6465 xa_init (& hws_pool -> mh_pools );
6566 xa_init (& hws_pool -> table_dests );
67+ xa_init (& hws_pool -> vport_dests );
68+ xa_init (& hws_pool -> vport_vhca_dests );
6669 return 0 ;
6770
6871cleanup_insert_hdr :
@@ -85,9 +88,16 @@ static int mlx5_fs_init_hws_actions_pool(struct mlx5_core_dev *dev,
8588static void mlx5_fs_cleanup_hws_actions_pool (struct mlx5_fs_hws_context * fs_ctx )
8689{
8790 struct mlx5_fs_hws_actions_pool * hws_pool = & fs_ctx -> hws_pool ;
91+ struct mlx5hws_action * action ;
8892 struct mlx5_fs_pool * pool ;
8993 unsigned long i ;
9094
95+ xa_for_each (& hws_pool -> vport_vhca_dests , i , action )
96+ mlx5hws_action_destroy (action );
97+ xa_destroy (& hws_pool -> vport_vhca_dests );
98+ xa_for_each (& hws_pool -> vport_dests , i , action )
99+ mlx5hws_action_destroy (action );
100+ xa_destroy (& hws_pool -> vport_dests );
91101 xa_destroy (& hws_pool -> table_dests );
92102 xa_for_each (& hws_pool -> mh_pools , i , pool )
93103 mlx5_fs_destroy_mh_pool (pool , & hws_pool -> mh_pools , i );
@@ -387,6 +397,52 @@ mlx5_fs_create_dest_action_table_num(struct mlx5_fs_hws_context *fs_ctx,
387397 return mlx5hws_action_create_dest_table_num (ctx , table_num , flags );
388398}
389399
400+ static struct mlx5hws_action *
401+ mlx5_fs_get_dest_action_vport (struct mlx5_fs_hws_context * fs_ctx ,
402+ struct mlx5_flow_rule * dst ,
403+ bool is_dest_type_uplink )
404+ {
405+ u32 flags = MLX5HWS_ACTION_FLAG_HWS_FDB | MLX5HWS_ACTION_FLAG_SHARED ;
406+ struct mlx5_flow_destination * dest_attr = & dst -> dest_attr ;
407+ struct mlx5hws_context * ctx = fs_ctx -> hws_ctx ;
408+ struct mlx5hws_action * dest ;
409+ struct xarray * dests_xa ;
410+ bool vhca_id_valid ;
411+ unsigned long idx ;
412+ u16 vport_num ;
413+ int err ;
414+
415+ vhca_id_valid = is_dest_type_uplink ||
416+ (dest_attr -> vport .flags & MLX5_FLOW_DEST_VPORT_VHCA_ID );
417+ vport_num = is_dest_type_uplink ? MLX5_VPORT_UPLINK : dest_attr -> vport .num ;
418+ if (vhca_id_valid ) {
419+ dests_xa = & fs_ctx -> hws_pool .vport_vhca_dests ;
420+ idx = dest_attr -> vport .vhca_id << 16 | vport_num ;
421+ } else {
422+ dests_xa = & fs_ctx -> hws_pool .vport_dests ;
423+ idx = vport_num ;
424+ }
425+ dest_load :
426+ dest = xa_load (dests_xa , idx );
427+ if (dest )
428+ return dest ;
429+
430+ dest = mlx5hws_action_create_dest_vport (ctx , vport_num , vhca_id_valid ,
431+ dest_attr -> vport .vhca_id , flags );
432+
433+ err = xa_insert (dests_xa , idx , dest , GFP_KERNEL );
434+ if (err ) {
435+ mlx5hws_action_destroy (dest );
436+ dest = NULL ;
437+
438+ if (err == - EBUSY )
439+ /* xarray entry was already stored by another thread */
440+ goto dest_load ;
441+ }
442+
443+ return dest ;
444+ }
445+
390446static struct mlx5hws_action *
391447mlx5_fs_create_dest_action_range (struct mlx5hws_context * ctx ,
392448 struct mlx5_flow_rule * dst )
@@ -695,6 +751,8 @@ static int mlx5_fs_fte_get_hws_actions(struct mlx5_flow_root_namespace *ns,
695751 if (fte_action -> action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST ) {
696752 list_for_each_entry (dst , & fte -> node .children , node .list ) {
697753 struct mlx5_flow_destination * attr = & dst -> dest_attr ;
754+ bool type_uplink =
755+ attr -> type == MLX5_FLOW_DESTINATION_TYPE_UPLINK ;
698756
699757 if (num_fs_actions == MLX5_FLOW_CONTEXT_ACTION_MAX ||
700758 num_dest_actions == MLX5_FLOW_CONTEXT_ACTION_MAX ) {
@@ -721,6 +779,11 @@ static int mlx5_fs_fte_get_hws_actions(struct mlx5_flow_root_namespace *ns,
721779 dest_action = mlx5_fs_create_dest_action_range (ctx , dst );
722780 fs_actions [num_fs_actions ++ ].action = dest_action ;
723781 break ;
782+ case MLX5_FLOW_DESTINATION_TYPE_UPLINK :
783+ case MLX5_FLOW_DESTINATION_TYPE_VPORT :
784+ dest_action = mlx5_fs_get_dest_action_vport (fs_ctx , dst ,
785+ type_uplink );
786+ break ;
724787 default :
725788 err = - EOPNOTSUPP ;
726789 goto free_actions ;
0 commit comments