0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <linux/mlx5/driver.h>
0034 #include <linux/etherdevice.h>
0035 #include <linux/idr.h>
0036 #include "mlx5_core.h"
0037 #include "lib/mlx5.h"
0038
0039 void mlx5_init_reserved_gids(struct mlx5_core_dev *dev)
0040 {
0041 unsigned int tblsz = MLX5_CAP_ROCE(dev, roce_address_table_size);
0042
0043 ida_init(&dev->roce.reserved_gids.ida);
0044 dev->roce.reserved_gids.start = tblsz;
0045 dev->roce.reserved_gids.count = 0;
0046 }
0047
0048 void mlx5_cleanup_reserved_gids(struct mlx5_core_dev *dev)
0049 {
0050 WARN_ON(!ida_is_empty(&dev->roce.reserved_gids.ida));
0051 dev->roce.reserved_gids.start = 0;
0052 dev->roce.reserved_gids.count = 0;
0053 ida_destroy(&dev->roce.reserved_gids.ida);
0054 }
0055
0056 int mlx5_core_reserve_gids(struct mlx5_core_dev *dev, unsigned int count)
0057 {
0058 if (dev->roce.reserved_gids.start < count) {
0059 mlx5_core_warn(dev, "GID table exhausted attempting to reserve %d more GIDs\n",
0060 count);
0061 return -ENOMEM;
0062 }
0063 if (dev->roce.reserved_gids.count + count > MLX5_MAX_RESERVED_GIDS) {
0064 mlx5_core_warn(dev, "Unable to reserve %d more GIDs\n", count);
0065 return -ENOMEM;
0066 }
0067
0068 dev->roce.reserved_gids.start -= count;
0069 dev->roce.reserved_gids.count += count;
0070 mlx5_core_dbg(dev, "Reserved %u GIDs starting at %u\n",
0071 dev->roce.reserved_gids.count,
0072 dev->roce.reserved_gids.start);
0073 return 0;
0074 }
0075
0076 void mlx5_core_unreserve_gids(struct mlx5_core_dev *dev, unsigned int count)
0077 {
0078 WARN(count > dev->roce.reserved_gids.count, "Unreserving %u GIDs when only %u reserved",
0079 count, dev->roce.reserved_gids.count);
0080
0081 dev->roce.reserved_gids.start += count;
0082 dev->roce.reserved_gids.count -= count;
0083 mlx5_core_dbg(dev, "%u GIDs starting at %u left reserved\n",
0084 dev->roce.reserved_gids.count,
0085 dev->roce.reserved_gids.start);
0086 }
0087
0088 int mlx5_core_reserved_gid_alloc(struct mlx5_core_dev *dev, int *gid_index)
0089 {
0090 int end = dev->roce.reserved_gids.start +
0091 dev->roce.reserved_gids.count - 1;
0092 int index = 0;
0093
0094 index = ida_alloc_range(&dev->roce.reserved_gids.ida,
0095 dev->roce.reserved_gids.start, end,
0096 GFP_KERNEL);
0097 if (index < 0)
0098 return index;
0099
0100 mlx5_core_dbg(dev, "Allocating reserved GID %u\n", index);
0101 *gid_index = index;
0102 return 0;
0103 }
0104
0105 void mlx5_core_reserved_gid_free(struct mlx5_core_dev *dev, int gid_index)
0106 {
0107 mlx5_core_dbg(dev, "Freeing reserved GID %u\n", gid_index);
0108 ida_free(&dev->roce.reserved_gids.ida, gid_index);
0109 }
0110
0111 unsigned int mlx5_core_reserved_gids_count(struct mlx5_core_dev *dev)
0112 {
0113 return dev->roce.reserved_gids.count;
0114 }
0115 EXPORT_SYMBOL_GPL(mlx5_core_reserved_gids_count);
0116
0117 int mlx5_core_roce_gid_set(struct mlx5_core_dev *dev, unsigned int index,
0118 u8 roce_version, u8 roce_l3_type, const u8 *gid,
0119 const u8 *mac, bool vlan, u16 vlan_id, u8 port_num)
0120 {
0121 #define MLX5_SET_RA(p, f, v) MLX5_SET(roce_addr_layout, p, f, v)
0122 u32 in[MLX5_ST_SZ_DW(set_roce_address_in)] = {};
0123 void *in_addr = MLX5_ADDR_OF(set_roce_address_in, in, roce_address);
0124 char *addr_l3_addr = MLX5_ADDR_OF(roce_addr_layout, in_addr,
0125 source_l3_address);
0126 void *addr_mac = MLX5_ADDR_OF(roce_addr_layout, in_addr,
0127 source_mac_47_32);
0128 int gidsz = MLX5_FLD_SZ_BYTES(roce_addr_layout, source_l3_address);
0129
0130 if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
0131 return -EINVAL;
0132
0133 if (gid) {
0134 if (vlan) {
0135 MLX5_SET_RA(in_addr, vlan_valid, 1);
0136 MLX5_SET_RA(in_addr, vlan_id, vlan_id);
0137 }
0138
0139 ether_addr_copy(addr_mac, mac);
0140 memcpy(addr_l3_addr, gid, gidsz);
0141 }
0142 MLX5_SET_RA(in_addr, roce_version, roce_version);
0143 MLX5_SET_RA(in_addr, roce_l3_type, roce_l3_type);
0144
0145 if (MLX5_CAP_GEN(dev, num_vhca_ports) > 0)
0146 MLX5_SET(set_roce_address_in, in, vhca_port_num, port_num);
0147
0148 MLX5_SET(set_roce_address_in, in, roce_address_index, index);
0149 MLX5_SET(set_roce_address_in, in, opcode, MLX5_CMD_OP_SET_ROCE_ADDRESS);
0150 return mlx5_cmd_exec_in(dev, set_roce_address, in);
0151 }
0152 EXPORT_SYMBOL(mlx5_core_roce_gid_set);