@@ -121,6 +121,18 @@ static void dr_domain_uninit_resources(struct mlx5dr_domain *dmn)
121
121
mlx5_core_dealloc_pd (dmn -> mdev , dmn -> pdn );
122
122
}
123
123
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
+
124
136
static int dr_domain_query_vport (struct mlx5dr_domain * dmn ,
125
137
u16 vport_number ,
126
138
struct mlx5dr_cmd_vport_cap * vport_caps )
@@ -129,6 +141,11 @@ static int dr_domain_query_vport(struct mlx5dr_domain *dmn,
129
141
bool other_vport = true;
130
142
int ret ;
131
143
144
+ if (vport_number == MLX5_VPORT_UPLINK ) {
145
+ dr_domain_fill_uplink_caps (dmn , vport_caps );
146
+ return 0 ;
147
+ }
148
+
132
149
if (dmn -> info .caps .is_ecpf && vport_number == MLX5_VPORT_ECPF ) {
133
150
other_vport = false;
134
151
cmd_vport = 0 ;
@@ -159,36 +176,78 @@ static int dr_domain_query_esw_mngr(struct mlx5dr_domain *dmn)
159
176
{
160
177
return dr_domain_query_vport (dmn ,
161
178
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 );
163
180
}
164
181
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 )
166
184
{
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 ;
170
187
int ret ;
171
188
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 ;
175
192
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 ;
183
197
}
184
198
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 ;
192
251
193
252
return 0 ;
194
253
}
@@ -210,25 +269,29 @@ static int dr_domain_query_fdb_caps(struct mlx5_core_dev *mdev,
210
269
dmn -> info .caps .esw_rx_drop_address = dmn -> info .caps .esw_caps .drop_icm_address_rx ;
211
270
dmn -> info .caps .esw_tx_drop_address = dmn -> info .caps .esw_caps .drop_icm_address_tx ;
212
271
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
+ */
218
277
219
- ret = dr_domain_query_vports (dmn );
278
+ ret = dr_domain_query_esw_mngr (dmn );
220
279
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 ;
223
282
}
224
283
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
+ }
226
289
227
290
return 0 ;
228
291
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
+
232
295
return ret ;
233
296
}
234
297
@@ -243,8 +306,6 @@ static int dr_domain_caps_init(struct mlx5_core_dev *mdev,
243
306
return - EOPNOTSUPP ;
244
307
}
245
308
246
- dmn -> info .caps .num_esw_ports = mlx5_eswitch_get_total_vports (mdev );
247
-
248
309
ret = mlx5dr_cmd_query_device (mdev , & dmn -> info .caps );
249
310
if (ret )
250
311
return ret ;
@@ -281,7 +342,7 @@ static int dr_domain_caps_init(struct mlx5_core_dev *mdev,
281
342
282
343
dmn -> info .rx .type = DR_DOMAIN_NIC_TYPE_RX ;
283
344
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 ;
285
346
286
347
dmn -> info .supp_sw_steering = true;
287
348
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,
300
361
301
362
static void dr_domain_caps_uninit (struct mlx5dr_domain * dmn )
302
363
{
303
- kfree (dmn -> info .caps .vports_caps );
364
+ dr_domain_clear_vports (dmn );
365
+ xa_destroy (& dmn -> info .caps .vports .vports_caps_xa );
304
366
}
305
367
306
368
struct mlx5dr_domain *
0 commit comments