• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2020 Mellanox Technologies Ltd. */
3 
4 #include <linux/mlx5/driver.h>
5 #include "eswitch.h"
6 
7 static void
mlx5_esw_get_port_parent_id(struct mlx5_core_dev * dev,struct netdev_phys_item_id * ppid)8 mlx5_esw_get_port_parent_id(struct mlx5_core_dev *dev, struct netdev_phys_item_id *ppid)
9 {
10 	u64 parent_id;
11 
12 	parent_id = mlx5_query_nic_system_image_guid(dev);
13 	ppid->id_len = sizeof(parent_id);
14 	memcpy(ppid->id, &parent_id, sizeof(parent_id));
15 }
16 
17 static bool
mlx5_esw_devlink_port_supported(const struct mlx5_eswitch * esw,u16 vport_num)18 mlx5_esw_devlink_port_supported(const struct mlx5_eswitch *esw, u16 vport_num)
19 {
20 	return vport_num == MLX5_VPORT_UPLINK ||
21 	       (mlx5_core_is_ecpf(esw->dev) && vport_num == MLX5_VPORT_PF) ||
22 	       mlx5_eswitch_is_vf_vport(esw, vport_num);
23 }
24 
mlx5_esw_dl_port_alloc(struct mlx5_eswitch * esw,u16 vport_num)25 static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16 vport_num)
26 {
27 	struct mlx5_core_dev *dev = esw->dev;
28 	struct devlink_port_attrs attrs = {};
29 	struct netdev_phys_item_id ppid = {};
30 	struct devlink_port *dl_port;
31 	u32 controller_num = 0;
32 	bool external;
33 	u16 pfnum;
34 
35 	dl_port = kzalloc(sizeof(*dl_port), GFP_KERNEL);
36 	if (!dl_port)
37 		return NULL;
38 
39 	mlx5_esw_get_port_parent_id(dev, &ppid);
40 	pfnum = PCI_FUNC(dev->pdev->devfn);
41 	external = mlx5_core_is_ecpf_esw_manager(dev);
42 	if (external)
43 		controller_num = dev->priv.eswitch->offloads.host_number + 1;
44 
45 	if (vport_num == MLX5_VPORT_UPLINK) {
46 		attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
47 		attrs.phys.port_number = pfnum;
48 		memcpy(attrs.switch_id.id, ppid.id, ppid.id_len);
49 		attrs.switch_id.id_len = ppid.id_len;
50 		devlink_port_attrs_set(dl_port, &attrs);
51 	} else if (vport_num == MLX5_VPORT_PF) {
52 		memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len);
53 		dl_port->attrs.switch_id.id_len = ppid.id_len;
54 		devlink_port_attrs_pci_pf_set(dl_port, controller_num, pfnum, external);
55 	} else if (mlx5_eswitch_is_vf_vport(esw, vport_num)) {
56 		memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len);
57 		dl_port->attrs.switch_id.id_len = ppid.id_len;
58 		devlink_port_attrs_pci_vf_set(dl_port, controller_num, pfnum,
59 					      vport_num - 1, external);
60 	}
61 	return dl_port;
62 }
63 
mlx5_esw_dl_port_free(struct devlink_port * dl_port)64 static void mlx5_esw_dl_port_free(struct devlink_port *dl_port)
65 {
66 	kfree(dl_port);
67 }
68 
mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch * esw,u16 vport_num)69 int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_num)
70 {
71 	struct mlx5_core_dev *dev = esw->dev;
72 	struct devlink_port *dl_port;
73 	unsigned int dl_port_index;
74 	struct mlx5_vport *vport;
75 	struct devlink *devlink;
76 	int err;
77 
78 	if (!mlx5_esw_devlink_port_supported(esw, vport_num))
79 		return 0;
80 
81 	vport = mlx5_eswitch_get_vport(esw, vport_num);
82 	if (IS_ERR(vport))
83 		return PTR_ERR(vport);
84 
85 	dl_port = mlx5_esw_dl_port_alloc(esw, vport_num);
86 	if (!dl_port)
87 		return -ENOMEM;
88 
89 	devlink = priv_to_devlink(dev);
90 	dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num);
91 	err = devlink_port_register(devlink, dl_port, dl_port_index);
92 	if (err)
93 		goto reg_err;
94 
95 	vport->dl_port = dl_port;
96 	return 0;
97 
98 reg_err:
99 	mlx5_esw_dl_port_free(dl_port);
100 	return err;
101 }
102 
mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch * esw,u16 vport_num)103 void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, u16 vport_num)
104 {
105 	struct mlx5_vport *vport;
106 
107 	if (!mlx5_esw_devlink_port_supported(esw, vport_num))
108 		return;
109 
110 	vport = mlx5_eswitch_get_vport(esw, vport_num);
111 	if (IS_ERR(vport))
112 		return;
113 	devlink_port_unregister(vport->dl_port);
114 	mlx5_esw_dl_port_free(vport->dl_port);
115 	vport->dl_port = NULL;
116 }
117 
mlx5_esw_offloads_devlink_port(struct mlx5_eswitch * esw,u16 vport_num)118 struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u16 vport_num)
119 {
120 	struct mlx5_vport *vport;
121 
122 	vport = mlx5_eswitch_get_vport(esw, vport_num);
123 	return vport->dl_port;
124 }
125