File Index
Files and directories
Sign in
FILE

devlink_port.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c C
  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
  7static void
  8mlx5_esw_get_port_parent_id(struct mlx5_core_dev *dev, struct netdev_phys_item_id *ppid)
  9{
 10	mlx5_query_nic_sw_system_image_guid(dev, ppid->id, &ppid->id_len);
 11}
 12
 13static bool mlx5_esw_devlink_port_supported(struct mlx5_eswitch *esw, u16 vport_num)
 14{
 15	return (mlx5_core_is_ecpf(esw->dev) && vport_num == MLX5_VPORT_PF) ||
 16	       mlx5_eswitch_is_vf_vport(esw, vport_num) ||
 17	       mlx5_core_is_ec_vf_vport(esw->dev, vport_num);
 18}
 19
 20static void mlx5_esw_offloads_pf_vf_devlink_port_attrs_set(struct mlx5_eswitch *esw,
 21							   u16 vport_num,
 22							   struct devlink_port *dl_port)
 23{
 24	struct mlx5_core_dev *dev = esw->dev;
 25	struct netdev_phys_item_id ppid = {};
 26	struct mlx5_vport *vport;
 27	u32 controller_num = 0;
 28	bool external;
 29	u16 pfnum;
 30
 31	mlx5_esw_get_port_parent_id(dev, &ppid);
 32	pfnum = PCI_FUNC(dev->pdev->devfn);
 33	external = mlx5_core_is_ecpf_esw_manager(dev);
 34	if (external)
 35		controller_num = dev->priv.eswitch->offloads.host_number + 1;
 36
 37	if (vport_num == MLX5_VPORT_PF) {
 38		memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len);
 39		dl_port->attrs.switch_id.id_len = ppid.id_len;
 40		devlink_port_attrs_pci_pf_set(dl_port, controller_num, pfnum, external);
 41	} else if (mlx5_eswitch_is_vf_vport(esw, vport_num)) {
 42		u16 func_id = vport_num - 1;
 43
 44		vport = mlx5_eswitch_get_vport(esw, vport_num);
 45		memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len);
 46		dl_port->attrs.switch_id.id_len = ppid.id_len;
 47		if (vport->adjacent) {
 48			func_id = vport->adj_info.function_id;
 49			pfnum = vport->adj_info.parent_pci_devfn;
 50		}
 51
 52		devlink_port_attrs_pci_vf_set(dl_port, controller_num, pfnum,
 53					      func_id, external);
 54	}  else if (mlx5_core_is_ec_vf_vport(esw->dev, vport_num)) {
 55		u16 base_vport = mlx5_core_ec_vf_vport_base(dev);
 56
 57		memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len);
 58		dl_port->attrs.switch_id.id_len = ppid.id_len;
 59		devlink_port_attrs_pci_vf_set(dl_port, 0, pfnum,
 60					      vport_num - base_vport, false);
 61	}
 62}
 63
 64int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw,
 65					      struct mlx5_vport *vport)
 66{
 67	struct mlx5_devlink_port *dl_port;
 68	u16 vport_num = vport->vport;
 69
 70	if (!mlx5_esw_devlink_port_supported(esw, vport_num))
 71		return 0;
 72
 73	dl_port = kzalloc(sizeof(*dl_port), GFP_KERNEL);
 74	if (!dl_port)
 75		return -ENOMEM;
 76
 77	mlx5_esw_offloads_pf_vf_devlink_port_attrs_set(esw, vport_num,
 78						       &dl_port->dl_port);
 79
 80	vport->dl_port = dl_port;
 81	mlx5_devlink_port_init(dl_port, vport);
 82	return 0;
 83}
 84
 85void mlx5_esw_offloads_pf_vf_devlink_port_cleanup(struct mlx5_eswitch *esw,
 86						  struct mlx5_vport *vport)
 87{
 88	if (!vport->dl_port)
 89		return;
 90
 91	kfree(vport->dl_port);
 92	vport->dl_port = NULL;
 93}
 94
 95static const struct devlink_port_ops mlx5_esw_pf_vf_dl_port_ops = {
 96	.port_fn_hw_addr_get = mlx5_devlink_port_fn_hw_addr_get,
 97	.port_fn_hw_addr_set = mlx5_devlink_port_fn_hw_addr_set,
 98	.port_fn_roce_get = mlx5_devlink_port_fn_roce_get,
 99	.port_fn_roce_set = mlx5_devlink_port_fn_roce_set,
100	.port_fn_migratable_get = mlx5_devlink_port_fn_migratable_get,
101	.port_fn_migratable_set = mlx5_devlink_port_fn_migratable_set,
102#ifdef CONFIG_XFRM_OFFLOAD
103	.port_fn_ipsec_crypto_get = mlx5_devlink_port_fn_ipsec_crypto_get,
104	.port_fn_ipsec_crypto_set = mlx5_devlink_port_fn_ipsec_crypto_set,
105	.port_fn_ipsec_packet_get = mlx5_devlink_port_fn_ipsec_packet_get,
106	.port_fn_ipsec_packet_set = mlx5_devlink_port_fn_ipsec_packet_set,
107#endif /* CONFIG_XFRM_OFFLOAD */
108	.port_fn_max_io_eqs_get = mlx5_devlink_port_fn_max_io_eqs_get,
109	.port_fn_max_io_eqs_set = mlx5_devlink_port_fn_max_io_eqs_set,
110};
111
112static void mlx5_esw_offloads_sf_devlink_port_attrs_set(struct mlx5_eswitch *esw,
113							struct devlink_port *dl_port,
114							u32 controller, u32 sfnum)
115{
116	struct mlx5_core_dev *dev = esw->dev;
117	struct netdev_phys_item_id ppid = {};
118	u16 pfnum;
119
120	pfnum = PCI_FUNC(dev->pdev->devfn);
121	mlx5_esw_get_port_parent_id(dev, &ppid);
122	memcpy(dl_port->attrs.switch_id.id, &ppid.id[0], ppid.id_len);
123	dl_port->attrs.switch_id.id_len = ppid.id_len;
124	devlink_port_attrs_pci_sf_set(dl_port, controller, pfnum, sfnum, !!controller);
125}
126
127int mlx5_esw_offloads_sf_devlink_port_init(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
128					   struct mlx5_devlink_port *dl_port,
129					   u32 controller, u32 sfnum)
130{
131	mlx5_esw_offloads_sf_devlink_port_attrs_set(esw, &dl_port->dl_port, controller, sfnum);
132
133	vport->dl_port = dl_port;
134	mlx5_devlink_port_init(dl_port, vport);
135	return 0;
136}
137
138void mlx5_esw_offloads_sf_devlink_port_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
139{
140	vport->dl_port = NULL;
141}
142
143static const struct devlink_port_ops mlx5_esw_dl_sf_port_ops = {
144#ifdef CONFIG_MLX5_SF_MANAGER
145	.port_del = mlx5_devlink_sf_port_del,
146#endif
147	.port_fn_hw_addr_get = mlx5_devlink_port_fn_hw_addr_get,
148	.port_fn_hw_addr_set = mlx5_devlink_port_fn_hw_addr_set,
149	.port_fn_roce_get = mlx5_devlink_port_fn_roce_get,
150	.port_fn_roce_set = mlx5_devlink_port_fn_roce_set,
151#ifdef CONFIG_MLX5_SF_MANAGER
152	.port_fn_state_get = mlx5_devlink_sf_port_fn_state_get,
153	.port_fn_state_set = mlx5_devlink_sf_port_fn_state_set,
154#endif
155	.port_fn_max_io_eqs_get = mlx5_devlink_port_fn_max_io_eqs_get,
156	.port_fn_max_io_eqs_set = mlx5_devlink_port_fn_max_io_eqs_set,
157};
158
159int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
160{
161	struct mlx5_core_dev *dev = esw->dev;
162	const struct devlink_port_ops *ops;
163	struct mlx5_devlink_port *dl_port;
164	u16 vport_num = vport->vport;
165	unsigned int dl_port_index;
166	struct devlink *devlink;
167	int err;
168
169	dl_port = vport->dl_port;
170	if (!dl_port)
171		return 0;
172
173	if (mlx5_esw_is_sf_vport(esw, vport_num))
174		ops = &mlx5_esw_dl_sf_port_ops;
175	else if (mlx5_eswitch_is_pf_vf_vport(esw, vport_num))
176		ops = &mlx5_esw_pf_vf_dl_port_ops;
177	else
178		ops = NULL;
179
180	devlink = priv_to_devlink(dev);
181	dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num);
182	err = devl_port_register_with_ops(devlink, &dl_port->dl_port, dl_port_index, ops);
183	if (err)
184		return err;
185
186	err = devl_rate_leaf_create(&dl_port->dl_port, vport, NULL);
187	if (err)
188		goto rate_err;
189
190	return 0;
191
192rate_err:
193	devl_port_unregister(&dl_port->dl_port);
194	return err;
195}
196
197void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_vport *vport)
198{
199	struct mlx5_devlink_port *dl_port;
200
201	if (!vport->dl_port)
202		return;
203	dl_port = vport->dl_port;
204
205	mlx5_esw_qos_vport_update_parent(vport, NULL, NULL);
206	devl_rate_leaf_destroy(&dl_port->dl_port);
207
208	devl_port_unregister(&dl_port->dl_port);
209}
210
211struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u16 vport_num)
212{
213	struct mlx5_vport *vport;
214
215	vport = mlx5_eswitch_get_vport(esw, vport_num);
216	return IS_ERR(vport) ? ERR_CAST(vport) : &vport->dl_port->dl_port;
217}
~/ Read-only file preview.