Skip to content

Commit 11a45de

Browse files
kliteynSaeed Mahameed
authored andcommitted
net/mlx5: DR, Add support for SF vports
Move all the vport capabilities to a separate struct and store vport caps in XArray: SFs vport numbers will not come in the same range as VF vports, so the existing implementation of vport capabilities as a fixed size array is not suitable here. XArray is a perfect fit: it is efficient when the indices used are densely clustered. In addition to being a perfect fit as a dynamic data structure, XArray also provides locking - it uses RCU and an internal spinlock to synchronise access, so no additional protection needed. Now except for the eswitch manager vport, all other vports (including the uplink vport) are handled in the same way: when a new go-to-vport action is added, this vport's caps are loaded from the xarray. If it is the first time for this particular vport number, then its capabilities are queried from FW and filled in into the appropriate entry. Signed-off-by: Yevgeny Kliteynik <[email protected]> Reviewed-by: Muhammad Sammar <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent c0e90fc commit 11a45de

File tree

5 files changed

+120
-68
lines changed

5 files changed

+120
-68
lines changed

drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1767,7 +1767,7 @@ mlx5dr_action_create_dest_vport(struct mlx5dr_domain *dmn,
17671767
return NULL;
17681768
}
17691769

1770-
vport_cap = mlx5dr_get_vport_cap(&vport_dmn->info.caps, vport);
1770+
vport_cap = mlx5dr_domain_get_vport_cap(vport_dmn, vport);
17711771
if (!vport_cap) {
17721772
mlx5dr_err(dmn,
17731773
"Failed to get vport 0x%x caps - vport is disabled or invalid\n",

drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c

Lines changed: 100 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,18 @@ static void dr_domain_uninit_resources(struct mlx5dr_domain *dmn)
121121
mlx5_core_dealloc_pd(dmn->mdev, dmn->pdn);
122122
}
123123

124+
static void dr_domain_fill_uplink_caps(struct mlx5dr_domain *dmn,
125+
struct mlx5dr_cmd_vport_cap *uplink_vport)
126+
{
127+
struct mlx5dr_esw_caps *esw_caps = &dmn->info.caps.esw_caps;
128+
129+
uplink_vport->num = MLX5_VPORT_UPLINK;
130+
uplink_vport->icm_address_rx = esw_caps->uplink_icm_address_rx;
131+
uplink_vport->icm_address_tx = esw_caps->uplink_icm_address_tx;
132+
uplink_vport->vport_gvmi = 0;
133+
uplink_vport->vhca_gvmi = dmn->info.caps.gvmi;
134+
}
135+
124136
static int dr_domain_query_vport(struct mlx5dr_domain *dmn,
125137
u16 vport_number,
126138
struct mlx5dr_cmd_vport_cap *vport_caps)
@@ -129,6 +141,11 @@ static int dr_domain_query_vport(struct mlx5dr_domain *dmn,
129141
bool other_vport = true;
130142
int ret;
131143

144+
if (vport_number == MLX5_VPORT_UPLINK) {
145+
dr_domain_fill_uplink_caps(dmn, vport_caps);
146+
return 0;
147+
}
148+
132149
if (dmn->info.caps.is_ecpf && vport_number == MLX5_VPORT_ECPF) {
133150
other_vport = false;
134151
cmd_vport = 0;
@@ -159,36 +176,78 @@ static int dr_domain_query_esw_mngr(struct mlx5dr_domain *dmn)
159176
{
160177
return dr_domain_query_vport(dmn,
161178
dmn->info.caps.is_ecpf ? MLX5_VPORT_ECPF : 0,
162-
&dmn->info.caps.esw_manager_vport_caps);
179+
&dmn->info.caps.vports.esw_manager_caps);
163180
}
164181

165-
static int dr_domain_query_vports(struct mlx5dr_domain *dmn)
182+
static struct mlx5dr_cmd_vport_cap *
183+
dr_domain_add_vport_cap(struct mlx5dr_domain *dmn, u16 vport)
166184
{
167-
struct mlx5dr_esw_caps *esw_caps = &dmn->info.caps.esw_caps;
168-
struct mlx5dr_cmd_vport_cap *wire_vport;
169-
int vport;
185+
struct mlx5dr_cmd_caps *caps = &dmn->info.caps;
186+
struct mlx5dr_cmd_vport_cap *vport_caps;
170187
int ret;
171188

172-
ret = dr_domain_query_esw_mngr(dmn);
173-
if (ret)
174-
return ret;
189+
vport_caps = kvzalloc(sizeof(*vport_caps), GFP_KERNEL);
190+
if (!vport_caps)
191+
return NULL;
175192

176-
/* Query vports (except wire vport) */
177-
for (vport = 0; vport < dmn->info.caps.num_esw_ports - 1; vport++) {
178-
ret = dr_domain_query_vport(dmn,
179-
vport,
180-
&dmn->info.caps.vports_caps[vport]);
181-
if (ret)
182-
return ret;
193+
ret = dr_domain_query_vport(dmn, vport, vport_caps);
194+
if (ret) {
195+
kvfree(vport_caps);
196+
return NULL;
183197
}
184198

185-
/* Last vport is the wire port */
186-
wire_vport = &dmn->info.caps.vports_caps[vport];
187-
wire_vport->num = MLX5_VPORT_UPLINK;
188-
wire_vport->icm_address_rx = esw_caps->uplink_icm_address_rx;
189-
wire_vport->icm_address_tx = esw_caps->uplink_icm_address_tx;
190-
wire_vport->vport_gvmi = 0;
191-
wire_vport->vhca_gvmi = dmn->info.caps.gvmi;
199+
ret = xa_insert(&caps->vports.vports_caps_xa, vport,
200+
vport_caps, GFP_KERNEL);
201+
if (ret) {
202+
mlx5dr_dbg(dmn, "Couldn't insert new vport into xarray (%d)\n", ret);
203+
kvfree(vport_caps);
204+
return ERR_PTR(ret);
205+
}
206+
207+
return vport_caps;
208+
}
209+
210+
struct mlx5dr_cmd_vport_cap *
211+
mlx5dr_domain_get_vport_cap(struct mlx5dr_domain *dmn, u16 vport)
212+
{
213+
struct mlx5dr_cmd_caps *caps = &dmn->info.caps;
214+
struct mlx5dr_cmd_vport_cap *vport_caps;
215+
216+
if ((caps->is_ecpf && vport == MLX5_VPORT_ECPF) ||
217+
(!caps->is_ecpf && vport == 0))
218+
return &caps->vports.esw_manager_caps;
219+
220+
vport_load:
221+
vport_caps = xa_load(&caps->vports.vports_caps_xa, vport);
222+
if (vport_caps)
223+
return vport_caps;
224+
225+
vport_caps = dr_domain_add_vport_cap(dmn, vport);
226+
if (PTR_ERR(vport_caps) == -EBUSY)
227+
/* caps were already stored by another thread */
228+
goto vport_load;
229+
230+
return vport_caps;
231+
}
232+
233+
static void dr_domain_clear_vports(struct mlx5dr_domain *dmn)
234+
{
235+
struct mlx5dr_cmd_vport_cap *vport_caps;
236+
unsigned long i;
237+
238+
xa_for_each(&dmn->info.caps.vports.vports_caps_xa, i, vport_caps) {
239+
vport_caps = xa_erase(&dmn->info.caps.vports.vports_caps_xa, i);
240+
kvfree(vport_caps);
241+
}
242+
}
243+
244+
static int dr_domain_query_uplink(struct mlx5dr_domain *dmn)
245+
{
246+
struct mlx5dr_cmd_vport_cap *vport_caps;
247+
248+
vport_caps = mlx5dr_domain_get_vport_cap(dmn, MLX5_VPORT_UPLINK);
249+
if (!vport_caps)
250+
return -EINVAL;
192251

193252
return 0;
194253
}
@@ -210,25 +269,29 @@ static int dr_domain_query_fdb_caps(struct mlx5_core_dev *mdev,
210269
dmn->info.caps.esw_rx_drop_address = dmn->info.caps.esw_caps.drop_icm_address_rx;
211270
dmn->info.caps.esw_tx_drop_address = dmn->info.caps.esw_caps.drop_icm_address_tx;
212271

213-
dmn->info.caps.vports_caps = kcalloc(dmn->info.caps.num_esw_ports,
214-
sizeof(dmn->info.caps.vports_caps[0]),
215-
GFP_KERNEL);
216-
if (!dmn->info.caps.vports_caps)
217-
return -ENOMEM;
272+
xa_init(&dmn->info.caps.vports.vports_caps_xa);
273+
274+
/* Query eswitch manager and uplink vports only. Rest of the
275+
* vports (vport 0, VFs and SFs) will be queried dynamically.
276+
*/
218277

219-
ret = dr_domain_query_vports(dmn);
278+
ret = dr_domain_query_esw_mngr(dmn);
220279
if (ret) {
221-
mlx5dr_err(dmn, "Failed to query vports caps (err: %d)", ret);
222-
goto free_vports_caps;
280+
mlx5dr_err(dmn, "Failed to query eswitch manager vport caps (err: %d)", ret);
281+
goto free_vports_caps_xa;
223282
}
224283

225-
dmn->info.caps.num_vports = dmn->info.caps.num_esw_ports - 1;
284+
ret = dr_domain_query_uplink(dmn);
285+
if (ret) {
286+
mlx5dr_err(dmn, "Failed to query uplink vport caps (err: %d)", ret);
287+
goto free_vports_caps_xa;
288+
}
226289

227290
return 0;
228291

229-
free_vports_caps:
230-
kfree(dmn->info.caps.vports_caps);
231-
dmn->info.caps.vports_caps = NULL;
292+
free_vports_caps_xa:
293+
xa_destroy(&dmn->info.caps.vports.vports_caps_xa);
294+
232295
return ret;
233296
}
234297

@@ -243,8 +306,6 @@ static int dr_domain_caps_init(struct mlx5_core_dev *mdev,
243306
return -EOPNOTSUPP;
244307
}
245308

246-
dmn->info.caps.num_esw_ports = mlx5_eswitch_get_total_vports(mdev);
247-
248309
ret = mlx5dr_cmd_query_device(mdev, &dmn->info.caps);
249310
if (ret)
250311
return ret;
@@ -281,7 +342,7 @@ static int dr_domain_caps_init(struct mlx5_core_dev *mdev,
281342

282343
dmn->info.rx.type = DR_DOMAIN_NIC_TYPE_RX;
283344
dmn->info.tx.type = DR_DOMAIN_NIC_TYPE_TX;
284-
vport_cap = &dmn->info.caps.esw_manager_vport_caps;
345+
vport_cap = &dmn->info.caps.vports.esw_manager_caps;
285346

286347
dmn->info.supp_sw_steering = true;
287348
dmn->info.tx.default_icm_addr = vport_cap->icm_address_tx;
@@ -300,7 +361,8 @@ static int dr_domain_caps_init(struct mlx5_core_dev *mdev,
300361

301362
static void dr_domain_caps_uninit(struct mlx5dr_domain *dmn)
302363
{
303-
kfree(dmn->info.caps.vports_caps);
364+
dr_domain_clear_vports(dmn);
365+
xa_destroy(&dmn->info.caps.vports.vports_caps_xa);
304366
}
305367

306368
struct mlx5dr_domain *

drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,7 +1645,7 @@ dr_ste_v0_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
16451645
struct mlx5dr_match_misc *misc = &value->misc;
16461646
struct mlx5dr_cmd_vport_cap *vport_cap;
16471647
struct mlx5dr_domain *dmn = sb->dmn;
1648-
struct mlx5dr_cmd_caps *caps;
1648+
struct mlx5dr_domain *vport_dmn;
16491649
u8 *bit_mask = sb->bit_mask;
16501650
bool source_gvmi_set;
16511651

@@ -1654,21 +1654,22 @@ dr_ste_v0_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
16541654
if (sb->vhca_id_valid) {
16551655
/* Find port GVMI based on the eswitch_owner_vhca_id */
16561656
if (misc->source_eswitch_owner_vhca_id == dmn->info.caps.gvmi)
1657-
caps = &dmn->info.caps;
1657+
vport_dmn = dmn;
16581658
else if (dmn->peer_dmn && (misc->source_eswitch_owner_vhca_id ==
16591659
dmn->peer_dmn->info.caps.gvmi))
1660-
caps = &dmn->peer_dmn->info.caps;
1660+
vport_dmn = dmn->peer_dmn;
16611661
else
16621662
return -EINVAL;
16631663

16641664
misc->source_eswitch_owner_vhca_id = 0;
16651665
} else {
1666-
caps = &dmn->info.caps;
1666+
vport_dmn = dmn;
16671667
}
16681668

16691669
source_gvmi_set = MLX5_GET(ste_src_gvmi_qp, bit_mask, source_gvmi);
16701670
if (source_gvmi_set) {
1671-
vport_cap = mlx5dr_get_vport_cap(caps, misc->source_port);
1671+
vport_cap = mlx5dr_domain_get_vport_cap(vport_dmn,
1672+
misc->source_port);
16721673
if (!vport_cap) {
16731674
mlx5dr_err(dmn, "Vport 0x%x is disabled or invalid\n",
16741675
misc->source_port);

drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,30 +1776,30 @@ static int dr_ste_v1_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
17761776
struct mlx5dr_match_misc *misc = &value->misc;
17771777
struct mlx5dr_cmd_vport_cap *vport_cap;
17781778
struct mlx5dr_domain *dmn = sb->dmn;
1779-
struct mlx5dr_cmd_caps *caps;
1779+
struct mlx5dr_domain *vport_dmn;
17801780
u8 *bit_mask = sb->bit_mask;
17811781

17821782
DR_STE_SET_TAG(src_gvmi_qp_v1, tag, source_qp, misc, source_sqn);
17831783

17841784
if (sb->vhca_id_valid) {
17851785
/* Find port GVMI based on the eswitch_owner_vhca_id */
17861786
if (misc->source_eswitch_owner_vhca_id == dmn->info.caps.gvmi)
1787-
caps = &dmn->info.caps;
1787+
vport_dmn = dmn;
17881788
else if (dmn->peer_dmn && (misc->source_eswitch_owner_vhca_id ==
17891789
dmn->peer_dmn->info.caps.gvmi))
1790-
caps = &dmn->peer_dmn->info.caps;
1790+
vport_dmn = dmn->peer_dmn;
17911791
else
17921792
return -EINVAL;
17931793

17941794
misc->source_eswitch_owner_vhca_id = 0;
17951795
} else {
1796-
caps = &dmn->info.caps;
1796+
vport_dmn = dmn;
17971797
}
17981798

17991799
if (!MLX5_GET(ste_src_gvmi_qp_v1, bit_mask, source_gvmi))
18001800
return 0;
18011801

1802-
vport_cap = mlx5dr_get_vport_cap(caps, misc->source_port);
1802+
vport_cap = mlx5dr_domain_get_vport_cap(vport_dmn, misc->source_port);
18031803
if (!vport_cap) {
18041804
mlx5dr_err(dmn, "Vport 0x%x is disabled or invalid\n",
18051805
misc->source_port);

drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,11 @@ struct mlx5dr_roce_cap {
762762
u8 fl_rc_qp_when_roce_enabled:1;
763763
};
764764

765+
struct mlx5dr_vports {
766+
struct mlx5dr_cmd_vport_cap esw_manager_caps;
767+
struct xarray vports_caps_xa;
768+
};
769+
765770
struct mlx5dr_cmd_caps {
766771
u16 gvmi;
767772
u64 nic_rx_drop_address;
@@ -785,7 +790,6 @@ struct mlx5dr_cmd_caps {
785790
u8 flex_parser_id_gtpu_first_ext_dw_0;
786791
u8 max_ft_level;
787792
u16 roce_min_src_udp;
788-
u8 num_esw_ports;
789793
u8 sw_format_ver;
790794
bool eswitch_manager;
791795
bool rx_sw_owner;
@@ -794,10 +798,8 @@ struct mlx5dr_cmd_caps {
794798
u8 rx_sw_owner_v2:1;
795799
u8 tx_sw_owner_v2:1;
796800
u8 fdb_sw_owner_v2:1;
797-
u32 num_vports;
798801
struct mlx5dr_esw_caps esw_caps;
799-
struct mlx5dr_cmd_vport_cap *vports_caps;
800-
struct mlx5dr_cmd_vport_cap esw_manager_vport_caps;
802+
struct mlx5dr_vports vports;
801803
bool prio_tag_required;
802804
struct mlx5dr_roce_cap roce_caps;
803805
u8 is_ecpf:1;
@@ -1099,21 +1101,8 @@ mlx5dr_ste_htbl_may_grow(struct mlx5dr_ste_htbl *htbl)
10991101
return true;
11001102
}
11011103

1102-
static inline struct mlx5dr_cmd_vport_cap *
1103-
mlx5dr_get_vport_cap(struct mlx5dr_cmd_caps *caps, u16 vport)
1104-
{
1105-
if (caps->is_ecpf && vport == MLX5_VPORT_ECPF)
1106-
return &caps->esw_manager_vport_caps;
1107-
1108-
if (!caps->vports_caps ||
1109-
(vport >= caps->num_vports && vport != MLX5_VPORT_UPLINK))
1110-
return NULL;
1111-
1112-
if (vport == MLX5_VPORT_UPLINK)
1113-
vport = caps->num_vports;
1114-
1115-
return &caps->vports_caps[vport];
1116-
}
1104+
struct mlx5dr_cmd_vport_cap *
1105+
mlx5dr_domain_get_vport_cap(struct mlx5dr_domain *dmn, u16 vport);
11171106

11181107
struct mlx5dr_cmd_query_flow_table_details {
11191108
u8 status;

0 commit comments

Comments
 (0)