IB/mlx5: Add steering SW ICM device memory type
This patch adds support for allocating, deallocating and registering a new device memory type, STEERING_SW_ICM. This memory can be allocated and used by a privileged user for direct rule insertion and management of the device's steering tables. The type is provided by the user via the dedicated attribute in the alloc_dm ioctl command. Signed-off-by: Ariel Levkovich <lariel@mellanox.com> Reviewed-by: Eli Cohen <eli@mellanox.com> Reviewed-by: Mark Bloch <markb@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:

committed by
Jason Gunthorpe

parent
4056b12efd
commit
25c13324d0
@@ -2264,6 +2264,28 @@ static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vm
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int check_dm_type_support(struct mlx5_ib_dev *dev,
|
||||
u32 type)
|
||||
{
|
||||
switch (type) {
|
||||
case MLX5_IB_UAPI_DM_TYPE_MEMIC:
|
||||
if (!MLX5_CAP_DEV_MEM(dev->mdev, memic))
|
||||
return -EOPNOTSUPP;
|
||||
break;
|
||||
case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
|
||||
if (!capable(CAP_SYS_RAWIO) ||
|
||||
!capable(CAP_NET_RAW))
|
||||
return -EPERM;
|
||||
|
||||
if (!(MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, sw_owner) ||
|
||||
MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, sw_owner)))
|
||||
return -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_alloc_dm_memic(struct ib_ucontext *ctx,
|
||||
struct mlx5_ib_dm *dm,
|
||||
struct ib_dm_alloc_attr *attr,
|
||||
@@ -2309,6 +2331,40 @@ err_dealloc:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int handle_alloc_dm_sw_icm(struct ib_ucontext *ctx,
|
||||
struct mlx5_ib_dm *dm,
|
||||
struct ib_dm_alloc_attr *attr,
|
||||
struct uverbs_attr_bundle *attrs,
|
||||
int type)
|
||||
{
|
||||
struct mlx5_dm *dm_db = &to_mdev(ctx->device)->dm;
|
||||
u64 act_size;
|
||||
int err;
|
||||
|
||||
/* Allocation size must a multiple of the basic block size
|
||||
* and a power of 2.
|
||||
*/
|
||||
act_size = roundup(attr->length, MLX5_SW_ICM_BLOCK_SIZE(dm_db->dev));
|
||||
act_size = roundup_pow_of_two(act_size);
|
||||
|
||||
dm->size = act_size;
|
||||
err = mlx5_cmd_alloc_sw_icm(dm_db, type, act_size,
|
||||
to_mucontext(ctx)->devx_uid, &dm->dev_addr,
|
||||
&dm->icm_dm.obj_id);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = uverbs_copy_to(attrs,
|
||||
MLX5_IB_ATTR_ALLOC_DM_RESP_START_OFFSET,
|
||||
&dm->dev_addr, sizeof(dm->dev_addr));
|
||||
if (err)
|
||||
mlx5_cmd_dealloc_sw_icm(dm_db, type, dm->size,
|
||||
to_mucontext(ctx)->devx_uid,
|
||||
dm->dev_addr, dm->icm_dm.obj_id);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
struct ib_dm *mlx5_ib_alloc_dm(struct ib_device *ibdev,
|
||||
struct ib_ucontext *context,
|
||||
struct ib_dm_alloc_attr *attr,
|
||||
@@ -2327,6 +2383,10 @@ struct ib_dm *mlx5_ib_alloc_dm(struct ib_device *ibdev,
|
||||
mlx5_ib_dbg(to_mdev(ibdev), "alloc_dm req: dm_type=%d user_length=0x%llx log_alignment=%d\n",
|
||||
type, attr->length, attr->alignment);
|
||||
|
||||
err = check_dm_type_support(to_mdev(ibdev), type);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
dm = kzalloc(sizeof(*dm), GFP_KERNEL);
|
||||
if (!dm)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
@@ -2339,6 +2399,10 @@ struct ib_dm *mlx5_ib_alloc_dm(struct ib_device *ibdev,
|
||||
attr,
|
||||
attrs);
|
||||
break;
|
||||
case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
|
||||
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_SW_ICM:
|
||||
err = handle_alloc_dm_sw_icm(context, dm, attr, attrs, type);
|
||||
break;
|
||||
default:
|
||||
err = -EOPNOTSUPP;
|
||||
}
|
||||
@@ -2355,6 +2419,8 @@ err_free:
|
||||
|
||||
int mlx5_ib_dealloc_dm(struct ib_dm *ibdm, struct uverbs_attr_bundle *attrs)
|
||||
{
|
||||
struct mlx5_ib_ucontext *ctx = rdma_udata_to_drv_context(
|
||||
&attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
|
||||
struct mlx5_dm *dm_db = &to_mdev(ibdm->device)->dm;
|
||||
struct mlx5_ib_dm *dm = to_mdm(ibdm);
|
||||
u32 page_idx;
|
||||
@@ -2371,11 +2437,16 @@ int mlx5_ib_dealloc_dm(struct ib_dm *ibdm, struct uverbs_attr_bundle *attrs)
|
||||
MLX5_CAP64_DEV_MEM(dm_db->dev,
|
||||
memic_bar_start_addr)) >>
|
||||
PAGE_SHIFT;
|
||||
bitmap_clear(rdma_udata_to_drv_context(&attrs->driver_udata,
|
||||
struct mlx5_ib_ucontext,
|
||||
ibucontext)
|
||||
->dm_pages,
|
||||
page_idx, DIV_ROUND_UP(dm->size, PAGE_SIZE));
|
||||
bitmap_clear(ctx->dm_pages, page_idx,
|
||||
DIV_ROUND_UP(dm->size, PAGE_SIZE));
|
||||
break;
|
||||
case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
|
||||
case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_SW_ICM:
|
||||
ret = mlx5_cmd_dealloc_sw_icm(dm_db, dm->type, dm->size,
|
||||
ctx->devx_uid, dm->dev_addr,
|
||||
dm->icm_dm.obj_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
@@ -5902,6 +5973,8 @@ static struct ib_counters *mlx5_ib_create_counters(struct ib_device *device,
|
||||
|
||||
static void mlx5_ib_stage_init_cleanup(struct mlx5_ib_dev *dev)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = dev->mdev;
|
||||
|
||||
mlx5_ib_cleanup_multiport_master(dev);
|
||||
if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING)) {
|
||||
srcu_barrier(&dev->mr_srcu);
|
||||
@@ -5909,11 +5982,29 @@ static void mlx5_ib_stage_init_cleanup(struct mlx5_ib_dev *dev)
|
||||
}
|
||||
|
||||
WARN_ON(!bitmap_empty(dev->dm.memic_alloc_pages, MLX5_MAX_MEMIC_PAGES));
|
||||
|
||||
WARN_ON(dev->dm.steering_sw_icm_alloc_blocks &&
|
||||
!bitmap_empty(
|
||||
dev->dm.steering_sw_icm_alloc_blocks,
|
||||
BIT(MLX5_CAP_DEV_MEM(mdev, log_steering_sw_icm_size) -
|
||||
MLX5_LOG_SW_ICM_BLOCK_SIZE(mdev))));
|
||||
|
||||
kfree(dev->dm.steering_sw_icm_alloc_blocks);
|
||||
|
||||
WARN_ON(dev->dm.header_modify_sw_icm_alloc_blocks &&
|
||||
!bitmap_empty(dev->dm.header_modify_sw_icm_alloc_blocks,
|
||||
BIT(MLX5_CAP_DEV_MEM(
|
||||
mdev, log_header_modify_sw_icm_size) -
|
||||
MLX5_LOG_SW_ICM_BLOCK_SIZE(mdev))));
|
||||
|
||||
kfree(dev->dm.header_modify_sw_icm_alloc_blocks);
|
||||
}
|
||||
|
||||
static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = dev->mdev;
|
||||
u64 header_modify_icm_blocks = 0;
|
||||
u64 steering_icm_blocks = 0;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
@@ -5959,16 +6050,51 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
|
||||
INIT_LIST_HEAD(&dev->qp_list);
|
||||
spin_lock_init(&dev->reset_flow_resource_lock);
|
||||
|
||||
if (MLX5_CAP_GEN_64(mdev, general_obj_types) &
|
||||
MLX5_GENERAL_OBJ_TYPES_CAP_SW_ICM) {
|
||||
if (MLX5_CAP64_DEV_MEM(mdev, steering_sw_icm_start_address)) {
|
||||
steering_icm_blocks =
|
||||
BIT(MLX5_CAP_DEV_MEM(mdev,
|
||||
log_steering_sw_icm_size) -
|
||||
MLX5_LOG_SW_ICM_BLOCK_SIZE(mdev));
|
||||
|
||||
dev->dm.steering_sw_icm_alloc_blocks =
|
||||
kcalloc(BITS_TO_LONGS(steering_icm_blocks),
|
||||
sizeof(unsigned long), GFP_KERNEL);
|
||||
if (!dev->dm.steering_sw_icm_alloc_blocks)
|
||||
goto err_mp;
|
||||
}
|
||||
|
||||
if (MLX5_CAP64_DEV_MEM(mdev,
|
||||
header_modify_sw_icm_start_address)) {
|
||||
header_modify_icm_blocks = BIT(
|
||||
MLX5_CAP_DEV_MEM(
|
||||
mdev, log_header_modify_sw_icm_size) -
|
||||
MLX5_LOG_SW_ICM_BLOCK_SIZE(mdev));
|
||||
|
||||
dev->dm.header_modify_sw_icm_alloc_blocks =
|
||||
kcalloc(BITS_TO_LONGS(header_modify_icm_blocks),
|
||||
sizeof(unsigned long), GFP_KERNEL);
|
||||
if (!dev->dm.header_modify_sw_icm_alloc_blocks)
|
||||
goto err_dm;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_init(&dev->dm.lock);
|
||||
dev->dm.dev = mdev;
|
||||
|
||||
if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING)) {
|
||||
err = init_srcu_struct(&dev->mr_srcu);
|
||||
if (err)
|
||||
goto err_mp;
|
||||
goto err_dm;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_dm:
|
||||
kfree(dev->dm.steering_sw_icm_alloc_blocks);
|
||||
kfree(dev->dm.header_modify_sw_icm_alloc_blocks);
|
||||
|
||||
err_mp:
|
||||
mlx5_ib_cleanup_multiport_master(dev);
|
||||
|
||||
@@ -6151,7 +6277,9 @@ static int mlx5_ib_stage_caps_init(struct mlx5_ib_dev *dev)
|
||||
ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_xrc_ops);
|
||||
}
|
||||
|
||||
if (MLX5_CAP_DEV_MEM(mdev, memic))
|
||||
if (MLX5_CAP_DEV_MEM(mdev, memic) ||
|
||||
MLX5_CAP_GEN_64(dev->mdev, general_obj_types) &
|
||||
MLX5_GENERAL_OBJ_TYPES_CAP_SW_ICM)
|
||||
ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_dm_ops);
|
||||
|
||||
if (mlx5_accel_ipsec_device_caps(dev->mdev) &
|
||||
|
Reference in New Issue
Block a user