xref: /linux/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
3 
4 #include "lib/sd.h"
5 #include "../lag/lag.h"
6 #include "mlx5_core.h"
7 #include "lib/mlx5.h"
8 #include "devlink.h"
9 #include "eswitch.h"
10 #include "fs_cmd.h"
11 #include <linux/mlx5/eswitch.h>
12 #include <linux/mlx5/vport.h>
13 #include <linux/debugfs.h>
14 
15 #define sd_info(__dev, format, ...) \
16 	dev_info((__dev)->device, "Socket-Direct: " format, ##__VA_ARGS__)
17 #define sd_warn(__dev, format, ...) \
18 	dev_warn((__dev)->device, "Socket-Direct: " format, ##__VA_ARGS__)
19 
20 struct mlx5_sd {
21 	u32 group_id;
22 	u8 group_size;
23 	struct mlx5_devcom_comp_dev *devcom;
24 	struct dentry *dfs;
25 	u8 state;
26 	bool primary;
27 	bool fw_silents_secondaries;
28 	union {
29 		struct { /* primary */
30 			struct mlx5_core_dev *secondaries[MLX5_SD_MAX_GROUP_SZ - 1];
31 			struct mlx5_flow_table *tx_ft;
32 			/* Next index for secondary registration */
33 			u8 next_secondary_idx;
34 		};
35 		struct { /* secondary */
36 			struct mlx5_core_dev *primary_dev;
37 			u32 alias_obj_id;
38 			/* TX flow table root in switchdev (silent) config */
39 			bool tx_root_silent;
40 		};
41 	};
42 };
43 
44 enum mlx5_sd_state {
45 	MLX5_SD_STATE_DOWN = 0,
46 	MLX5_SD_STATE_UP,
47 };
48 
mlx5_sd_get_group_size(struct mlx5_core_dev * dev)49 static int mlx5_sd_get_group_size(struct mlx5_core_dev *dev)
50 {
51 	struct mlx5_sd *sd = mlx5_get_sd(dev);
52 
53 	if (!sd)
54 		return 1;
55 
56 	return sd->group_size;
57 }
58 
mlx5_sd_get_primary(struct mlx5_core_dev * dev)59 struct mlx5_core_dev *mlx5_sd_get_primary(struct mlx5_core_dev *dev)
60 {
61 	struct mlx5_sd *sd = mlx5_get_sd(dev);
62 
63 	if (!sd)
64 		return dev;
65 
66 	if (!mlx5_devcom_comp_is_ready(sd->devcom))
67 		return NULL;
68 
69 	return sd->primary ? dev : sd->primary_dev;
70 }
71 
mlx5_sd_get_devcom(struct mlx5_core_dev * dev)72 struct mlx5_devcom_comp_dev *mlx5_sd_get_devcom(struct mlx5_core_dev *dev)
73 {
74 	struct mlx5_sd *sd = mlx5_get_sd(dev);
75 
76 	if (!sd)
77 		return NULL;
78 
79 	return sd->devcom;
80 }
81 
mlx5_sd_is_primary(struct mlx5_core_dev * dev)82 bool mlx5_sd_is_primary(struct mlx5_core_dev *dev)
83 {
84 	struct mlx5_sd *sd = mlx5_get_sd(dev);
85 
86 	if (!sd)
87 		return true;
88 
89 	return sd->primary;
90 }
91 
mlx5_sd_pf_num_get(struct mlx5_core_dev * dev)92 int mlx5_sd_pf_num_get(struct mlx5_core_dev *dev)
93 {
94 	struct mlx5_sd *sd = mlx5_get_sd(dev);
95 	int pf_num = mlx5_get_dev_index(dev);
96 	struct mlx5_core_dev *pos;
97 	int i;
98 
99 	if (!sd)
100 		return pf_num;
101 
102 	mlx5_devcom_comp_assert_locked(sd->devcom);
103 	if (!mlx5_devcom_comp_is_ready(sd->devcom))
104 		return -ENODEV;
105 
106 	mlx5_sd_for_each_dev(i, mlx5_sd_get_primary(dev), pos)
107 		if (pos == dev)
108 			break;
109 
110 	return pf_num * sd->group_size + i;
111 }
112 
113 struct mlx5_core_dev *
mlx5_sd_primary_get_peer(struct mlx5_core_dev * primary,int idx)114 mlx5_sd_primary_get_peer(struct mlx5_core_dev *primary, int idx)
115 {
116 	struct mlx5_sd *sd;
117 
118 	if (idx == 0)
119 		return primary;
120 
121 	if (idx >= mlx5_sd_get_group_size(primary))
122 		return NULL;
123 
124 	sd = mlx5_get_sd(primary);
125 	return sd->secondaries[idx - 1];
126 }
127 
mlx5_sd_ch_ix_get_dev_ix(struct mlx5_core_dev * dev,int ch_ix)128 int mlx5_sd_ch_ix_get_dev_ix(struct mlx5_core_dev *dev, int ch_ix)
129 {
130 	if (is_mdev_switchdev_mode(dev))
131 		return 0;
132 
133 	return ch_ix % mlx5_sd_get_group_size(dev);
134 }
135 
mlx5_sd_ch_ix_get_vec_ix(struct mlx5_core_dev * dev,int ch_ix)136 int mlx5_sd_ch_ix_get_vec_ix(struct mlx5_core_dev *dev, int ch_ix)
137 {
138 	if (is_mdev_switchdev_mode(dev))
139 		return ch_ix;
140 
141 	return ch_ix / mlx5_sd_get_group_size(dev);
142 }
143 
mlx5_sd_ch_ix_get_dev(struct mlx5_core_dev * primary,int ch_ix)144 struct mlx5_core_dev *mlx5_sd_ch_ix_get_dev(struct mlx5_core_dev *primary, int ch_ix)
145 {
146 	int mdev_idx = mlx5_sd_ch_ix_get_dev_ix(primary, ch_ix);
147 
148 	return mlx5_sd_primary_get_peer(primary, mdev_idx);
149 }
150 
ft_create_alias_supported(struct mlx5_core_dev * dev)151 static bool ft_create_alias_supported(struct mlx5_core_dev *dev)
152 {
153 	u64 obj_allowed = MLX5_CAP_GEN_2_64(dev, allowed_object_for_other_vhca_access);
154 	u32 obj_supp = MLX5_CAP_GEN_2(dev, cross_vhca_object_to_object_supported);
155 
156 	if (!(obj_supp &
157 	    MLX5_CROSS_VHCA_OBJ_TO_OBJ_SUPPORTED_LOCAL_FLOW_TABLE_ROOT_TO_REMOTE_FLOW_TABLE))
158 		return false;
159 
160 	if (!(obj_allowed & MLX5_ALLOWED_OBJ_FOR_OTHER_VHCA_ACCESS_FLOW_TABLE))
161 		return false;
162 
163 	return true;
164 }
165 
mlx5_query_sd(struct mlx5_core_dev * dev,bool * sdm,u8 * group_size)166 static int mlx5_query_sd(struct mlx5_core_dev *dev, bool *sdm,
167 			 u8 *group_size)
168 {
169 	u32 out[MLX5_ST_SZ_DW(mpir_reg)];
170 	int err;
171 
172 	err = mlx5_query_mpir_reg(dev, out);
173 	if (err)
174 		return err;
175 
176 	*sdm = MLX5_GET(mpir_reg, out, sdm);
177 	*group_size = MLX5_GET(mpir_reg, out, host_buses);
178 
179 	return 0;
180 }
181 
mlx5_sd_group_id(struct mlx5_core_dev * dev,u8 sd_group)182 static u32 mlx5_sd_group_id(struct mlx5_core_dev *dev, u8 sd_group)
183 {
184 	return (u32)((MLX5_CAP_GEN(dev, native_port_num) << 8) | sd_group);
185 }
186 
mlx5_sd_caps_supported(struct mlx5_core_dev * dev,u8 group_size)187 static bool mlx5_sd_caps_supported(struct mlx5_core_dev *dev, u8 group_size)
188 {
189 	/* Honor the SW implementation limit */
190 	if (group_size > MLX5_SD_MAX_GROUP_SZ)
191 		return false;
192 
193 	/* Disconnect secondaries from the network */
194 	if (!MLX5_CAP_GEN(dev, eswitch_manager))
195 		return false;
196 	if (!MLX5_CAP_GEN(dev, silent_mode_set) &&
197 	    !MLX5_CAP_GEN(dev, silent_mode_query))
198 		return false;
199 
200 	/* RX steering from primary to secondaries */
201 	if (!MLX5_CAP_GEN(dev, cross_vhca_rqt))
202 		return false;
203 	if (group_size > MLX5_CAP_GEN_2(dev, max_rqt_vhca_id))
204 		return false;
205 
206 	/* TX steering from secondaries to primary */
207 	if (!ft_create_alias_supported(dev))
208 		return false;
209 	if (!MLX5_CAP_FLOWTABLE_NIC_TX(dev, reset_root_to_default))
210 		return false;
211 
212 	return true;
213 }
214 
mlx5_sd_is_supported(struct mlx5_core_dev * dev)215 bool mlx5_sd_is_supported(struct mlx5_core_dev *dev)
216 {
217 	u8 group_size = U8_MAX, sd_group;
218 	bool sdm;
219 	int err;
220 
221 	/* Feature is currently implemented for PFs only */
222 	if (!mlx5_core_is_pf(dev))
223 		return false;
224 
225 	err = mlx5_query_nic_vport_sd_group(dev, &sd_group, &group_size);
226 	if (err || !sd_group || group_size < MLX5_SD_MIN_GROUP_SZ)
227 		return false;
228 
229 	if (group_size == U8_MAX) {
230 		if (!MLX5_CAP_MCAM_REG(dev, mpir))
231 			return false;
232 
233 		err = mlx5_query_sd(dev, &sdm, &group_size);
234 		if (err || !sdm)
235 			return false;
236 	}
237 
238 	return mlx5_sd_caps_supported(dev, group_size);
239 }
240 
sd_init(struct mlx5_core_dev * dev)241 static int sd_init(struct mlx5_core_dev *dev)
242 {
243 	u8 group_size = U8_MAX, sd_group;
244 	struct mlx5_sd *sd;
245 	u32 group_id;
246 	bool sdm;
247 	int err;
248 
249 	/* Feature is currently implemented for PFs only */
250 	if (!mlx5_core_is_pf(dev))
251 		return 0;
252 
253 	err = mlx5_query_nic_vport_sd_group(dev, &sd_group, &group_size);
254 	if (err)
255 		return err;
256 
257 	if (!sd_group || group_size < MLX5_SD_MIN_GROUP_SZ)
258 		return 0;
259 
260 	if (group_size == U8_MAX) {
261 		if (!MLX5_CAP_MCAM_REG(dev, mpir))
262 			return 0;
263 
264 		err = mlx5_query_sd(dev, &sdm, &group_size);
265 		if (err)
266 			return err;
267 
268 		if (!sdm)
269 			return 0;
270 	}
271 	group_id = mlx5_sd_group_id(dev, sd_group);
272 
273 	if (!mlx5_sd_caps_supported(dev, group_size)) {
274 		sd_warn(dev, "can't support requested netdev combining for group id 0x%x, skipping\n",
275 			group_id);
276 		return 0;
277 	}
278 
279 	sd = kzalloc_obj(*sd);
280 	if (!sd)
281 		return -ENOMEM;
282 
283 	sd->group_size = group_size;
284 	sd->group_id = group_id;
285 
286 	mlx5_set_sd(dev, sd);
287 
288 	return 0;
289 }
290 
sd_cleanup(struct mlx5_core_dev * dev)291 static void sd_cleanup(struct mlx5_core_dev *dev)
292 {
293 	struct mlx5_sd *sd = mlx5_get_sd(dev);
294 
295 	mlx5_set_sd(dev, NULL);
296 	kfree(sd);
297 }
298 
sd_lag_state_show(struct seq_file * file,void * priv)299 static int sd_lag_state_show(struct seq_file *file, void *priv)
300 {
301 	struct mlx5_core_dev *dev = file->private;
302 	struct mlx5_lag *ldev;
303 	struct lag_func *pf;
304 	bool active = false;
305 	int i;
306 
307 	ldev = mlx5_lag_dev(dev);
308 	if (!ldev)
309 		return -EINVAL;
310 
311 	mutex_lock(&ldev->lock);
312 	mlx5_ldev_for_each(i, 0, ldev) {
313 		pf = mlx5_lag_pf(ldev, i);
314 		if (pf->dev == dev) {
315 			active = pf->sd_fdb_active;
316 			break;
317 		}
318 	}
319 	mutex_unlock(&ldev->lock);
320 
321 	seq_printf(file, "%s\n", active ? "active" : "disabled");
322 	return 0;
323 }
324 
325 DEFINE_SHOW_ATTRIBUTE(sd_lag_state);
326 
327 /* SD LAG integration is optional. If LAG isn't available on this device
328  * (e.g. lag caps are off), or registering secondaries fails, just warn
329  * and continue - SD can operate without the LAG-side bookkeeping.
330  */
sd_lag_init(struct mlx5_core_dev * dev)331 static void sd_lag_init(struct mlx5_core_dev *dev)
332 {
333 	struct mlx5_core_dev *primary = mlx5_sd_get_primary(dev);
334 	struct mlx5_sd *sd = mlx5_get_sd(primary);
335 	struct mlx5_core_dev *pos, *to;
336 	struct mlx5_lag *ldev;
337 	struct lag_func *pf;
338 	int err;
339 	int i;
340 
341 	ldev = mlx5_lag_dev(primary);
342 	if (!ldev) {
343 		sd_warn(primary, "%s: no ldev (LAG caps off?), skipping\n",
344 			__func__);
345 		return;
346 	}
347 
348 	mutex_lock(&ldev->lock);
349 	pf = mlx5_lag_pf_by_dev(ldev, primary);
350 	if (!pf) {
351 		sd_warn(primary, "%s: primary not registered in ldev, skipping\n",
352 			__func__);
353 		goto out;
354 	}
355 
356 	pf->group_id = sd->group_id;
357 
358 	mlx5_sd_for_each_secondary(i, primary, pos) {
359 		err = mlx5_ldev_add_mdev(ldev, pos, sd->group_id);
360 		if (err) {
361 			sd_warn(primary, "%s: failed to add secondary %s to ldev: %d\n",
362 				__func__, dev_name(pos->device), err);
363 			goto err;
364 		}
365 	}
366 
367 out:
368 	mutex_unlock(&ldev->lock);
369 	return;
370 
371 err:
372 	to = pos;
373 	mlx5_sd_for_each_secondary_to(i, primary, to, pos)
374 		mlx5_ldev_remove_mdev(ldev, pos);
375 	pf->group_id = 0;
376 	mutex_unlock(&ldev->lock);
377 }
378 
sd_lag_cleanup(struct mlx5_core_dev * dev)379 static void sd_lag_cleanup(struct mlx5_core_dev *dev)
380 {
381 	struct mlx5_core_dev *primary = mlx5_sd_get_primary(dev);
382 	struct mlx5_core_dev *pos;
383 	struct mlx5_lag *ldev;
384 	struct lag_func *pf;
385 	int i;
386 
387 	ldev = mlx5_lag_dev(primary);
388 	if (!ldev)
389 		return;
390 
391 	mutex_lock(&ldev->lock);
392 	mlx5_sd_for_each_secondary(i, primary, pos)
393 		mlx5_ldev_remove_mdev(ldev, pos);
394 
395 	pf = mlx5_lag_pf_by_dev(ldev, primary);
396 	if (pf)
397 		pf->group_id = 0;
398 	mutex_unlock(&ldev->lock);
399 }
400 
401 enum {
402 	SD_PRIMARY_SET,
403 	SD_SECONDARIES_SET,
404 	SD_FW_SILENT_CHECK,
405 };
406 
sd_handle_fw_silent_check(struct mlx5_core_dev * dev,struct mlx5_core_dev * peer)407 static int sd_handle_fw_silent_check(struct mlx5_core_dev *dev,
408 				     struct mlx5_core_dev *peer)
409 {
410 	struct mlx5_sd *peer_sd = mlx5_get_sd(peer);
411 	struct mlx5_sd *sd = mlx5_get_sd(dev);
412 	u8 dev_silent = 0, peer_silent = 0;
413 	int err;
414 
415 	if (peer_sd->fw_silents_secondaries) {
416 		sd->fw_silents_secondaries = true;
417 		return 0;
418 	}
419 
420 	err = mlx5_fs_cmd_query_l2table_silent(dev, &dev_silent);
421 	if (err) {
422 		sd_warn(dev, "Failed to query silent mode for dev: %d\n", err);
423 		return err;
424 	}
425 
426 	err = mlx5_fs_cmd_query_l2table_silent(peer, &peer_silent);
427 	if (err) {
428 		sd_warn(dev, "Failed to query silent mode for peer: %d\n", err);
429 		return err;
430 	}
431 
432 	if (dev_silent || peer_silent) {
433 		sd->fw_silents_secondaries = true;
434 		peer_sd->fw_silents_secondaries = true;
435 		sd_info(dev, "FW indicates at least one device is silent\n");
436 	}
437 	return 0;
438 }
439 
sd_handle_primary_set(struct mlx5_core_dev * dev,struct mlx5_core_dev * peer)440 static int sd_handle_primary_set(struct mlx5_core_dev *dev,
441 				 struct mlx5_core_dev *peer)
442 {
443 	struct mlx5_sd *peer_sd = mlx5_get_sd(peer);
444 	struct mlx5_sd *sd = mlx5_get_sd(dev);
445 	struct mlx5_core_dev *candidate;
446 	struct mlx5_sd *candidate_sd;
447 	bool dev_should_be_primary;
448 
449 	/* Peer is the device that being sent to all the other devices in the
450 	 * group. Hence, use peer to get the candidate device.
451 	 */
452 	candidate = peer_sd->primary ? peer : peer_sd->primary_dev;
453 
454 	if (sd->fw_silents_secondaries) {
455 		u8 candidate_silent = 0;
456 		int err;
457 
458 		err = mlx5_fs_cmd_query_l2table_silent(candidate,
459 						       &candidate_silent);
460 		if (err) {
461 			sd_warn(candidate, "Failed to query silent mode for dev: %d\n",
462 				err);
463 			return err;
464 		}
465 		/* Candidate is silent, dev should be primary */
466 		dev_should_be_primary = candidate_silent;
467 	} else {
468 		/* No FW silent mode, use bus number */
469 		dev_should_be_primary =
470 			dev->pdev->bus->number < candidate->pdev->bus->number;
471 	}
472 
473 	if (!dev_should_be_primary)
474 		return 0;
475 
476 	candidate_sd = mlx5_get_sd(candidate);
477 
478 	sd->primary = true;
479 	candidate_sd->primary = false;
480 	candidate_sd->primary_dev = dev;
481 	peer_sd->primary = false;
482 	peer_sd->primary_dev = dev;
483 	return 0;
484 }
485 
sd_handle_secondaries_set(struct mlx5_core_dev * dev,struct mlx5_core_dev * peer)486 static void sd_handle_secondaries_set(struct mlx5_core_dev *dev,
487 				      struct mlx5_core_dev *peer)
488 {
489 	struct mlx5_sd *peer_sd = mlx5_get_sd(peer);
490 	struct mlx5_sd *sd = mlx5_get_sd(dev);
491 	u8 idx;
492 
493 	/* Primary has nothing to register with itself. */
494 	if (sd->primary)
495 		return;
496 
497 	/* dev is a secondary device, peer is the primary device.
498 	 * Secondary registers itself with the primary.
499 	 */
500 	idx = peer_sd->next_secondary_idx++;
501 	peer_sd->secondaries[idx] = dev;
502 	sd->primary_dev = peer;
503 }
504 
mlx5_sd_devcom_event(int event,void * my_data,void * event_data)505 static int mlx5_sd_devcom_event(int event, void *my_data, void *event_data)
506 {
507 	struct mlx5_core_dev *peer = event_data;
508 	struct mlx5_core_dev *dev = my_data;
509 
510 	switch (event) {
511 	case SD_FW_SILENT_CHECK:
512 		return sd_handle_fw_silent_check(dev, peer);
513 	case SD_PRIMARY_SET:
514 		return sd_handle_primary_set(dev, peer);
515 	case SD_SECONDARIES_SET:
516 		sd_handle_secondaries_set(dev, peer);
517 		return 0;
518 	}
519 
520 	return 0;
521 }
522 
sd_register(struct mlx5_core_dev * dev)523 static int sd_register(struct mlx5_core_dev *dev)
524 {
525 	struct mlx5_devcom_match_attr attr = {};
526 	struct mlx5_devcom_comp_dev *devcom;
527 	struct mlx5_core_dev *primary;
528 	struct mlx5_sd *primary_sd;
529 	struct mlx5_sd *sd;
530 	int err;
531 
532 	sd = mlx5_get_sd(dev);
533 	attr.key.val = sd->group_id;
534 	attr.flags = MLX5_DEVCOM_MATCH_FLAGS_NS;
535 	attr.net = mlx5_core_net(dev);
536 	devcom = mlx5_devcom_register_component(dev->priv.devc,
537 						MLX5_DEVCOM_SD_GROUP,
538 						&attr, mlx5_sd_devcom_event,
539 						dev);
540 	if (!devcom)
541 		return -EINVAL;
542 
543 	sd->devcom = devcom;
544 
545 	mlx5_devcom_comp_lock(devcom);
546 	if (mlx5_devcom_comp_get_size(devcom) != sd->group_size ||
547 	    mlx5_devcom_comp_is_ready(devcom))
548 		goto out;
549 
550 	/* If silent mode query is supported, ask each device whether it is
551 	 * silent and propagate the result to the whole group. In each group
552 	 * only one device is not silent
553 	 */
554 	if (MLX5_CAP_GEN(dev, silent_mode_query)) {
555 		err = mlx5_devcom_locked_send_event(devcom, SD_FW_SILENT_CHECK,
556 						    SD_FW_SILENT_CHECK, dev);
557 		if (err)
558 			goto err_devcom_unreg;
559 	}
560 
561 	/* Send SD_PRIMARY_SET event with this device.
562 	 * All peers will receive this event and compare to this device.
563 	 * If fw_silents_secondaries is set, choose non-silent device.
564 	 * Otherwise use bus number.
565 	 */
566 	sd->primary = true;
567 	err = mlx5_devcom_locked_send_event(devcom, SD_PRIMARY_SET,
568 					    SD_PRIMARY_SET, dev);
569 	if (err)
570 		goto err_devcom_unreg;
571 
572 	/* Broadcast SD_SECONDARIES_SET. Each non-sender peer's handler runs;
573 	 * the primary's handler returns early so only secondaries register.
574 	 */
575 	primary = sd->primary ? dev : sd->primary_dev;
576 	if (!sd->primary)
577 		sd_handle_secondaries_set(dev, primary);
578 	mlx5_devcom_locked_send_event(devcom, SD_SECONDARIES_SET,
579 				      DEVCOM_CANT_FAIL, primary);
580 
581 	primary_sd = mlx5_get_sd(primary);
582 	if (primary_sd->next_secondary_idx + 1 == sd->group_size)
583 		mlx5_devcom_comp_set_ready(devcom, true);
584 out:
585 	mlx5_devcom_comp_unlock(devcom);
586 	return 0;
587 
588 err_devcom_unreg:
589 	mlx5_devcom_comp_unlock(devcom);
590 	mlx5_devcom_unregister_component(devcom);
591 	return err;
592 }
593 
sd_unregister(struct mlx5_core_dev * dev)594 static void sd_unregister(struct mlx5_core_dev *dev)
595 {
596 	struct mlx5_sd *sd = mlx5_get_sd(dev);
597 
598 	mlx5_devcom_unregister_component(sd->devcom);
599 }
600 
sd_cmd_set_primary(struct mlx5_core_dev * primary,u8 * alias_key)601 static int sd_cmd_set_primary(struct mlx5_core_dev *primary, u8 *alias_key)
602 {
603 	struct mlx5_cmd_allow_other_vhca_access_attr allow_attr = {};
604 	struct mlx5_sd *sd = mlx5_get_sd(primary);
605 	struct mlx5_flow_table_attr ft_attr = {};
606 	struct mlx5_flow_namespace *nic_ns;
607 	struct mlx5_flow_table *ft;
608 	int err;
609 
610 	nic_ns = mlx5_get_flow_namespace(primary, MLX5_FLOW_NAMESPACE_EGRESS);
611 	if (!nic_ns)
612 		return -EOPNOTSUPP;
613 
614 	ft = mlx5_create_flow_table(nic_ns, &ft_attr);
615 	if (IS_ERR(ft)) {
616 		err = PTR_ERR(ft);
617 		return err;
618 	}
619 	sd->tx_ft = ft;
620 	memcpy(allow_attr.access_key, alias_key, ACCESS_KEY_LEN);
621 	allow_attr.obj_type = MLX5_GENERAL_OBJECT_TYPES_FLOW_TABLE_ALIAS;
622 	allow_attr.obj_id = (ft->type << FT_ID_FT_TYPE_OFFSET) | ft->id;
623 
624 	err = mlx5_cmd_allow_other_vhca_access(primary, &allow_attr);
625 	if (err) {
626 		mlx5_core_err(primary, "Failed to allow other vhca access err=%d\n",
627 			      err);
628 		mlx5_destroy_flow_table(ft);
629 		return err;
630 	}
631 
632 	return 0;
633 }
634 
sd_cmd_unset_primary(struct mlx5_core_dev * primary)635 static void sd_cmd_unset_primary(struct mlx5_core_dev *primary)
636 {
637 	struct mlx5_sd *sd = mlx5_get_sd(primary);
638 
639 	mlx5_destroy_flow_table(sd->tx_ft);
640 }
641 
sd_secondary_create_alias_ft(struct mlx5_core_dev * secondary,struct mlx5_core_dev * primary,struct mlx5_flow_table * ft,u32 * obj_id,u8 * alias_key)642 static int sd_secondary_create_alias_ft(struct mlx5_core_dev *secondary,
643 					struct mlx5_core_dev *primary,
644 					struct mlx5_flow_table *ft,
645 					u32 *obj_id, u8 *alias_key)
646 {
647 	u32 aliased_object_id = (ft->type << FT_ID_FT_TYPE_OFFSET) | ft->id;
648 	u16 vhca_id_to_be_accessed = MLX5_CAP_GEN(primary, vhca_id);
649 	struct mlx5_cmd_alias_obj_create_attr alias_attr = {};
650 	int ret;
651 
652 	memcpy(alias_attr.access_key, alias_key, ACCESS_KEY_LEN);
653 	alias_attr.obj_id = aliased_object_id;
654 	alias_attr.obj_type = MLX5_GENERAL_OBJECT_TYPES_FLOW_TABLE_ALIAS;
655 	alias_attr.vhca_id = vhca_id_to_be_accessed;
656 	ret = mlx5_cmd_alias_obj_create(secondary, &alias_attr, obj_id);
657 	if (ret) {
658 		mlx5_core_err(secondary, "Failed to create alias object err=%d\n",
659 			      ret);
660 		return ret;
661 	}
662 
663 	return 0;
664 }
665 
sd_secondary_destroy_alias_ft(struct mlx5_core_dev * secondary)666 static void sd_secondary_destroy_alias_ft(struct mlx5_core_dev *secondary)
667 {
668 	struct mlx5_sd *sd = mlx5_get_sd(secondary);
669 
670 	mlx5_cmd_alias_obj_destroy(secondary, sd->alias_obj_id,
671 				   MLX5_GENERAL_OBJECT_TYPES_FLOW_TABLE_ALIAS);
672 }
673 
mlx5_sd_secondary_conf_tx_root(struct mlx5_core_dev * secondary,bool disconnect)674 static int mlx5_sd_secondary_conf_tx_root(struct mlx5_core_dev *secondary,
675 					  bool disconnect)
676 {
677 	struct mlx5_sd *sd = mlx5_get_sd(secondary);
678 	int err;
679 
680 	/* Idempotent: skip if TX root is already in the requested state. */
681 	if (sd->tx_root_silent == disconnect)
682 		return 0;
683 
684 	if (disconnect)
685 		err = mlx5_fs_cmd_set_tx_flow_table_root(secondary, 0, true);
686 	else
687 		err = mlx5_fs_cmd_set_tx_flow_table_root(secondary,
688 							 sd->alias_obj_id,
689 							 false);
690 	if (err)
691 		return err;
692 
693 	sd->tx_root_silent = disconnect;
694 	return 0;
695 }
696 
sd_cmd_set_secondary(struct mlx5_core_dev * secondary,struct mlx5_core_dev * primary,u8 * alias_key)697 static int sd_cmd_set_secondary(struct mlx5_core_dev *secondary,
698 				struct mlx5_core_dev *primary,
699 				u8 *alias_key)
700 {
701 	struct mlx5_sd *primary_sd = mlx5_get_sd(primary);
702 	struct mlx5_sd *sd = mlx5_get_sd(secondary);
703 	int err;
704 
705 	if (!primary_sd->fw_silents_secondaries) {
706 		err = mlx5_fs_cmd_set_l2table_entry_silent(secondary, 1);
707 		if (err)
708 			return err;
709 	}
710 
711 	err = sd_secondary_create_alias_ft(secondary, primary, primary_sd->tx_ft,
712 					   &sd->alias_obj_id, alias_key);
713 	if (err)
714 		goto err_unset_silent;
715 
716 	err = mlx5_fs_cmd_set_tx_flow_table_root(secondary, sd->alias_obj_id,
717 						 false);
718 	if (err)
719 		goto err_destroy_alias_ft;
720 	sd->tx_root_silent = false;
721 
722 	return 0;
723 
724 err_destroy_alias_ft:
725 	sd_secondary_destroy_alias_ft(secondary);
726 err_unset_silent:
727 	if (!primary_sd->fw_silents_secondaries)
728 		mlx5_fs_cmd_set_l2table_entry_silent(secondary, 0);
729 	return err;
730 }
731 
sd_cmd_unset_secondary(struct mlx5_core_dev * secondary)732 static void sd_cmd_unset_secondary(struct mlx5_core_dev *secondary)
733 {
734 	struct mlx5_sd *primary_sd;
735 
736 	primary_sd = mlx5_get_sd(mlx5_sd_get_primary(secondary));
737 	mlx5_sd_secondary_conf_tx_root(secondary, true);
738 	sd_secondary_destroy_alias_ft(secondary);
739 	if (!primary_sd->fw_silents_secondaries)
740 		mlx5_fs_cmd_set_l2table_entry_silent(secondary, 0);
741 }
742 
sd_print_group(struct mlx5_core_dev * primary)743 static void sd_print_group(struct mlx5_core_dev *primary)
744 {
745 	struct mlx5_sd *sd = mlx5_get_sd(primary);
746 	struct mlx5_core_dev *pos;
747 	int i;
748 
749 	sd_info(primary, "group id %#x, primary %s, vhca %#x\n",
750 		sd->group_id, pci_name(primary->pdev),
751 		MLX5_CAP_GEN(primary, vhca_id));
752 	mlx5_sd_for_each_secondary(i, primary, pos)
753 		sd_info(primary, "group id %#x, secondary_%d %s, vhca %#x\n",
754 			sd->group_id, i - 1, pci_name(pos->pdev),
755 			MLX5_CAP_GEN(pos, vhca_id));
756 }
757 
dev_read(struct file * filp,char __user * buf,size_t count,loff_t * pos)758 static ssize_t dev_read(struct file *filp, char __user *buf, size_t count,
759 			loff_t *pos)
760 {
761 	struct mlx5_core_dev *dev;
762 	char tbuf[32];
763 	int ret;
764 
765 	dev = filp->private_data;
766 	ret = snprintf(tbuf, sizeof(tbuf), "%s vhca %#x\n", pci_name(dev->pdev),
767 		       MLX5_CAP_GEN(dev, vhca_id));
768 
769 	return simple_read_from_buffer(buf, count, pos, tbuf, ret);
770 }
771 
772 static const struct file_operations dev_fops = {
773 	.owner	= THIS_MODULE,
774 	.open	= simple_open,
775 	.read	= dev_read,
776 };
777 
mlx5_sd_init(struct mlx5_core_dev * dev)778 int mlx5_sd_init(struct mlx5_core_dev *dev)
779 {
780 	struct mlx5_core_dev *primary, *pos, *to;
781 	struct mlx5_sd *sd = mlx5_get_sd(dev);
782 	u8 alias_key[ACCESS_KEY_LEN];
783 	struct mlx5_sd *primary_sd;
784 	int err, i;
785 
786 	err = sd_init(dev);
787 	if (err)
788 		return err;
789 
790 	sd = mlx5_get_sd(dev);
791 	if (!sd)
792 		return 0;
793 
794 	err = sd_register(dev);
795 	if (err)
796 		goto err_sd_cleanup;
797 
798 	mlx5_devcom_comp_lock(sd->devcom);
799 	if (!mlx5_devcom_comp_is_ready(sd->devcom))
800 		goto out;
801 
802 	primary = mlx5_sd_get_primary(dev);
803 	if (!primary)
804 		goto out;
805 
806 	primary_sd = mlx5_get_sd(primary);
807 	if (primary_sd->state != MLX5_SD_STATE_DOWN)
808 		goto out;
809 
810 	for (i = 0; i < ACCESS_KEY_LEN; i++)
811 		alias_key[i] = get_random_u8();
812 
813 	err = sd_cmd_set_primary(primary, alias_key);
814 	if (err)
815 		goto err_sd_unregister;
816 
817 	mlx5_sd_for_each_secondary(i, primary, pos) {
818 		err = sd_cmd_set_secondary(pos, primary, alias_key);
819 		if (err)
820 			goto err_unset_secondaries;
821 	}
822 
823 	sd_lag_init(primary);
824 
825 	primary_sd->dfs =
826 		debugfs_create_dir("multi-pf",
827 				   mlx5_debugfs_get_dev_root(primary));
828 	mlx5_sd_for_each_secondary(i, primary, pos) {
829 		char name[32];
830 
831 		snprintf(name, sizeof(name), "secondary_%d", i - 1);
832 		debugfs_create_file(name, 0400, primary_sd->dfs, pos,
833 				    &dev_fops);
834 	}
835 
836 	debugfs_create_file("sd_lag_state", 0400, primary_sd->dfs, primary,
837 			    &sd_lag_state_fops);
838 	debugfs_create_x32("group_id", 0400, primary_sd->dfs,
839 			   &primary_sd->group_id);
840 	debugfs_create_file("primary", 0400, primary_sd->dfs, primary,
841 			    &dev_fops);
842 
843 	sd_info(primary, "group id %#x, size %d, combined\n",
844 		sd->group_id, mlx5_devcom_comp_get_size(sd->devcom));
845 	sd_print_group(primary);
846 
847 	primary_sd->state = MLX5_SD_STATE_UP;
848 out:
849 	mlx5_devcom_comp_unlock(sd->devcom);
850 	return 0;
851 
852 err_unset_secondaries:
853 	to = pos;
854 	mlx5_sd_for_each_secondary_to(i, primary, to, pos)
855 		sd_cmd_unset_secondary(pos);
856 	sd_cmd_unset_primary(primary);
857 err_sd_unregister:
858 	mlx5_sd_for_each_secondary(i, primary, pos) {
859 		struct mlx5_sd *peer_sd = mlx5_get_sd(pos);
860 
861 		primary_sd->secondaries[i - 1] = NULL;
862 		peer_sd->primary_dev = NULL;
863 	}
864 	primary_sd->primary = false;
865 	primary_sd->next_secondary_idx = 0;
866 	mlx5_devcom_comp_set_ready(sd->devcom, false);
867 	mlx5_devcom_comp_unlock(sd->devcom);
868 	sd_unregister(dev);
869 err_sd_cleanup:
870 	sd_cleanup(dev);
871 	return err;
872 }
873 
mlx5_sd_cleanup(struct mlx5_core_dev * dev)874 void mlx5_sd_cleanup(struct mlx5_core_dev *dev)
875 {
876 	struct mlx5_sd *sd = mlx5_get_sd(dev);
877 	struct mlx5_core_dev *primary, *pos;
878 	struct mlx5_sd *primary_sd;
879 	int i;
880 
881 	if (!sd)
882 		return;
883 
884 	mlx5_devcom_comp_lock(sd->devcom);
885 	if (!mlx5_devcom_comp_is_ready(sd->devcom))
886 		goto out_unlock;
887 
888 	primary = mlx5_sd_get_primary(dev);
889 	if (!primary)
890 		goto out_ready_false;
891 
892 	primary_sd = mlx5_get_sd(primary);
893 	if (primary_sd->state != MLX5_SD_STATE_UP)
894 		goto out_clear_peers;
895 
896 	debugfs_remove_recursive(primary_sd->dfs);
897 	primary_sd->dfs = NULL;
898 	sd_lag_cleanup(primary);
899 	mlx5_sd_for_each_secondary(i, primary, pos)
900 		sd_cmd_unset_secondary(pos);
901 	sd_cmd_unset_primary(primary);
902 
903 	sd_info(primary, "group id %#x, uncombined\n", sd->group_id);
904 	primary_sd->state = MLX5_SD_STATE_DOWN;
905 out_clear_peers:
906 	mlx5_sd_for_each_secondary(i, primary, pos) {
907 		struct mlx5_sd *peer_sd = mlx5_get_sd(pos);
908 
909 		primary_sd->secondaries[i - 1] = NULL;
910 		peer_sd->primary_dev = NULL;
911 	}
912 	primary_sd->primary = false;
913 	primary_sd->next_secondary_idx = 0;
914 out_ready_false:
915 	mlx5_devcom_comp_set_ready(sd->devcom, false);
916 out_unlock:
917 	mlx5_devcom_comp_unlock(sd->devcom);
918 	sd_unregister(dev);
919 	sd_cleanup(dev);
920 }
921 
922 /* Lock order:
923  *   primary:   actual_adev_lock -> SD devcom comp lock
924  *   secondary: SD devcom comp lock -> (drop) -> actual_adev_lock
925  * The two locks are never held together, so no ABBA.
926  */
mlx5_sd_get_adev(struct mlx5_core_dev * dev,struct auxiliary_device * adev,int idx)927 struct auxiliary_device *mlx5_sd_get_adev(struct mlx5_core_dev *dev,
928 					  struct auxiliary_device *adev,
929 					  int idx)
930 {
931 	struct mlx5_sd *sd = mlx5_get_sd(dev);
932 	struct mlx5_core_dev *primary;
933 	struct mlx5_adev *primary_adev;
934 
935 	if (!sd)
936 		return adev;
937 
938 	mlx5_devcom_comp_lock(sd->devcom);
939 	if (!mlx5_devcom_comp_is_ready(sd->devcom)) {
940 		mlx5_devcom_comp_unlock(sd->devcom);
941 		return NULL;
942 	}
943 
944 	primary = mlx5_sd_get_primary(dev);
945 	if (!primary || dev == primary) {
946 		mlx5_devcom_comp_unlock(sd->devcom);
947 		return adev;
948 	}
949 
950 	primary_adev = primary->priv.adev[idx];
951 	get_device(&primary_adev->adev.dev);
952 	mlx5_devcom_comp_unlock(sd->devcom);
953 
954 	device_lock(&primary_adev->adev.dev);
955 	/* Primary may have completed remove between dropping devcom and
956 	 * acquiring device_lock; recheck.
957 	 */
958 	if (!mlx5_devcom_comp_is_ready(sd->devcom)) {
959 		device_unlock(&primary_adev->adev.dev);
960 		put_device(&primary_adev->adev.dev);
961 		return NULL;
962 	}
963 	return &primary_adev->adev;
964 }
965 
966 #ifdef CONFIG_MLX5_ESWITCH
967 /* All SD members must have completed esw_offloads_enable (i.e., reached
968  * mlx5_esw_offloads_devcom_init) and become eswitch-peers of the primary.
969  * Until then, mlx5_eswitch_is_peer() returns false for the not-yet-paired
970  * member and shared_fdb_supported_filter would reject. When all PFs transition
971  * in parallel, only the last one to finish satisfies this gate; the earlier
972  * ones return 0 silently here.
973  */
mlx5_sd_all_paired(struct mlx5_core_dev * primary)974 static bool mlx5_sd_all_paired(struct mlx5_core_dev *primary)
975 {
976 	struct mlx5_eswitch *primary_esw = primary->priv.eswitch;
977 	struct mlx5_core_dev *pos;
978 	int i;
979 
980 	mlx5_sd_for_each_secondary(i, primary, pos) {
981 		if (!mlx5_eswitch_is_peer(primary_esw, pos->priv.eswitch))
982 			return false;
983 	}
984 	return true;
985 }
986 
mlx5_sd_activate_shared_fdb(struct mlx5_core_dev * primary)987 static void mlx5_sd_activate_shared_fdb(struct mlx5_core_dev *primary)
988 {
989 	struct mlx5_sd *sd = mlx5_get_sd(primary);
990 	struct mlx5_core_dev *pos;
991 	struct mlx5_lag *ldev;
992 	struct lag_func *pf;
993 	int err;
994 	int i;
995 
996 	ldev = mlx5_lag_dev(primary);
997 	if (!ldev) {
998 		sd_warn(primary, "Shared FDB MUST have ldev\n");
999 		return;
1000 	}
1001 
1002 	mutex_lock(&ldev->lock);
1003 
1004 	if (ldev->mode_changes_in_progress)
1005 		goto unlock;
1006 
1007 	if (!mlx5_sd_all_paired(primary))
1008 		goto unlock;
1009 
1010 	/* Check if SD FDB is already active for this group */
1011 	mlx5_lag_for_each(i, 0, ldev, sd->group_id) {
1012 		pf = mlx5_lag_pf(ldev, i);
1013 		if (pf->sd_fdb_active)
1014 			goto unlock;
1015 		break;
1016 	}
1017 
1018 	if (!mlx5_lag_shared_fdb_supported_filter(ldev, sd->group_id)) {
1019 		sd_warn(primary, "Shared FDB not supported\n");
1020 		goto unlock;
1021 	}
1022 
1023 	/* Initialize vport metadata for all group devices. This is deferred
1024 	 * from esw_offloads_enable() because mlx5_sd_pf_num_get() requires
1025 	 * the SD group to be ready.
1026 	 */
1027 	mlx5_sd_for_each_dev(i, primary, pos) {
1028 		struct mlx5_eswitch *esw = pos->priv.eswitch;
1029 
1030 		err = mlx5_esw_offloads_init_deferred_metadata(esw);
1031 		if (err) {
1032 			sd_warn(primary, "Failed to init metadata for %s: %d\n",
1033 				dev_name(pos->device), err);
1034 			goto unlock;
1035 		}
1036 	}
1037 
1038 	err = mlx5_lag_shared_fdb_create(ldev, NULL, 0, sd->group_id);
1039 	if (err)
1040 		sd_warn(primary, "Failed to create shared FDB: %d\n", err);
1041 	else
1042 		sd_info(primary, "Shared FDB created\n");
1043 
1044 unlock:
1045 	mutex_unlock(&ldev->lock);
1046 }
1047 
mlx5_sd_eswitch_mode_set(struct mlx5_core_dev * dev,u16 mlx5_mode)1048 void mlx5_sd_eswitch_mode_set(struct mlx5_core_dev *dev, u16 mlx5_mode)
1049 {
1050 	struct mlx5_core_dev *primary;
1051 	struct mlx5_sd *sd;
1052 	int err;
1053 
1054 	sd = mlx5_get_sd(dev);
1055 	if (!sd || !mlx5_devcom_comp_is_ready(sd->devcom))
1056 		return;
1057 
1058 	mlx5_devcom_comp_lock(sd->devcom);
1059 	if (!mlx5_devcom_comp_is_ready(sd->devcom))
1060 		goto unlock;
1061 
1062 	primary = mlx5_sd_get_primary(dev);
1063 
1064 	/* Secondary devices need TX root reconfiguration */
1065 	if (dev != primary) {
1066 		bool disconnect = (mlx5_mode == MLX5_ESWITCH_OFFLOADS);
1067 
1068 		err = mlx5_sd_secondary_conf_tx_root(dev, disconnect);
1069 		if (err) {
1070 			sd_warn(dev, "Failed to set TX root: %d\n", err);
1071 			goto unlock;
1072 		}
1073 	}
1074 
1075 	/* Try to activate shared FDB when all devices are in switchdev.
1076 	 * Shared FDB is optional - failure here doesn't fail the transition.
1077 	 */
1078 	if (mlx5_mode == MLX5_ESWITCH_OFFLOADS)
1079 		mlx5_sd_activate_shared_fdb(primary);
1080 
1081 unlock:
1082 	mlx5_devcom_comp_unlock(sd->devcom);
1083 }
1084 
1085 #endif /* CONFIG_MLX5_ESWITCH */
1086 
mlx5_sd_put_adev(struct auxiliary_device * actual_adev,struct auxiliary_device * adev)1087 void mlx5_sd_put_adev(struct auxiliary_device *actual_adev,
1088 		      struct auxiliary_device *adev)
1089 {
1090 	if (actual_adev != adev) {
1091 		device_unlock(&actual_adev->dev);
1092 		put_device(&actual_adev->dev);
1093 	}
1094 }
1095