1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2020 Mellanox Technologies Ltd. */
4 #include <linux/mlx5/driver.h>
8 mlx5_esw_get_port_parent_id(struct mlx5_core_dev *dev, struct netdev_phys_item_id *ppid)
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));
18 mlx5_esw_devlink_port_supported(const struct mlx5_eswitch *esw, u16 vport_num)
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);
25 static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16 vport_num)
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;
35 dl_port = kzalloc(sizeof(*dl_port), GFP_KERNEL);
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);
43 controller_num = dev->priv.eswitch->offloads.host_number + 1;
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);
64 static void mlx5_esw_dl_port_free(struct devlink_port *dl_port)
69 int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_num)
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;
78 if (!mlx5_esw_devlink_port_supported(esw, vport_num))
81 vport = mlx5_eswitch_get_vport(esw, vport_num);
83 return PTR_ERR(vport);
85 dl_port = mlx5_esw_dl_port_alloc(esw, vport_num);
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);
95 vport->dl_port = dl_port;
99 mlx5_esw_dl_port_free(dl_port);
103 void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, u16 vport_num)
105 struct mlx5_vport *vport;
107 if (!mlx5_esw_devlink_port_supported(esw, vport_num))
110 vport = mlx5_eswitch_get_vport(esw, vport_num);
113 devlink_port_unregister(vport->dl_port);
114 mlx5_esw_dl_port_free(vport->dl_port);
115 vport->dl_port = NULL;
118 struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u16 vport_num)
120 struct mlx5_vport *vport;
122 vport = mlx5_eswitch_get_vport(esw, vport_num);
123 return vport->dl_port;