FILE
devlink_port.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.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.