mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	While creating a uobject every create reaches a point where the uobject is fully initialized. For ioctls that go on to copy_to_user this means they need to open code the destruction of a fully created uobject - ie the RDMA_REMOVE_DESTROY sort of flow. Open coding this creates bugs, eg the CQ does not properly flush the events list when it does its error unwind. Provide a uverbs_finalize_uobj_create() function which indicates that the uobject is fully initialized and that abort should call to destroy_hw to destroy the uobj->object and related. Methods can call this function if they go on to have error cases after setting uobj->object. Once done those error cases can simply do return, without an error unwind. Link: https://lore.kernel.org/r/20200519072711.257271-2-leon@kernel.org Signed-off-by: Yishai Hadas <yishaih@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
		
			
				
	
	
		
			133 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
 | 
						|
/*
 | 
						|
 * Copyright (c) 2020, Mellanox Technologies inc.  All rights reserved.
 | 
						|
 */
 | 
						|
 | 
						|
#include <rdma/uverbs_ioctl.h>
 | 
						|
#include <rdma/mlx5_user_ioctl_cmds.h>
 | 
						|
#include <rdma/mlx5_user_ioctl_verbs.h>
 | 
						|
#include <linux/mlx5/driver.h>
 | 
						|
#include "mlx5_ib.h"
 | 
						|
 | 
						|
#define UVERBS_MODULE_NAME mlx5_ib
 | 
						|
#include <rdma/uverbs_named_ioctl.h>
 | 
						|
 | 
						|
static bool pp_is_supported(struct ib_device *device)
 | 
						|
{
 | 
						|
	struct mlx5_ib_dev *dev = to_mdev(device);
 | 
						|
 | 
						|
	return (MLX5_CAP_GEN(dev->mdev, qos) &&
 | 
						|
		MLX5_CAP_QOS(dev->mdev, packet_pacing) &&
 | 
						|
		MLX5_CAP_QOS(dev->mdev, packet_pacing_uid));
 | 
						|
}
 | 
						|
 | 
						|
static int UVERBS_HANDLER(MLX5_IB_METHOD_PP_OBJ_ALLOC)(
 | 
						|
	struct uverbs_attr_bundle *attrs)
 | 
						|
{
 | 
						|
	u8 rl_raw[MLX5_ST_SZ_BYTES(set_pp_rate_limit_context)] = {};
 | 
						|
	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
 | 
						|
		MLX5_IB_ATTR_PP_OBJ_ALLOC_HANDLE);
 | 
						|
	struct mlx5_ib_dev *dev;
 | 
						|
	struct mlx5_ib_ucontext *c;
 | 
						|
	struct mlx5_ib_pp *pp_entry;
 | 
						|
	void *in_ctx;
 | 
						|
	u16 uid;
 | 
						|
	int inlen;
 | 
						|
	u32 flags;
 | 
						|
	int err;
 | 
						|
 | 
						|
	c = to_mucontext(ib_uverbs_get_ucontext(attrs));
 | 
						|
	if (IS_ERR(c))
 | 
						|
		return PTR_ERR(c);
 | 
						|
 | 
						|
	/* The allocated entry can be used only by a DEVX context */
 | 
						|
	if (!c->devx_uid)
 | 
						|
		return -EINVAL;
 | 
						|
 | 
						|
	dev = to_mdev(c->ibucontext.device);
 | 
						|
	pp_entry = kzalloc(sizeof(*pp_entry), GFP_KERNEL);
 | 
						|
	if (!pp_entry)
 | 
						|
		return -ENOMEM;
 | 
						|
 | 
						|
	in_ctx = uverbs_attr_get_alloced_ptr(attrs,
 | 
						|
					     MLX5_IB_ATTR_PP_OBJ_ALLOC_CTX);
 | 
						|
	inlen = uverbs_attr_get_len(attrs,
 | 
						|
				    MLX5_IB_ATTR_PP_OBJ_ALLOC_CTX);
 | 
						|
	memcpy(rl_raw, in_ctx, inlen);
 | 
						|
	err = uverbs_get_flags32(&flags, attrs,
 | 
						|
		MLX5_IB_ATTR_PP_OBJ_ALLOC_FLAGS,
 | 
						|
		MLX5_IB_UAPI_PP_ALLOC_FLAGS_DEDICATED_INDEX);
 | 
						|
	if (err)
 | 
						|
		goto err;
 | 
						|
 | 
						|
	uid = (flags & MLX5_IB_UAPI_PP_ALLOC_FLAGS_DEDICATED_INDEX) ?
 | 
						|
		c->devx_uid : MLX5_SHARED_RESOURCE_UID;
 | 
						|
 | 
						|
	err = mlx5_rl_add_rate_raw(dev->mdev, rl_raw, uid,
 | 
						|
			(flags & MLX5_IB_UAPI_PP_ALLOC_FLAGS_DEDICATED_INDEX),
 | 
						|
			&pp_entry->index);
 | 
						|
	if (err)
 | 
						|
		goto err;
 | 
						|
 | 
						|
	pp_entry->mdev = dev->mdev;
 | 
						|
	uobj->object = pp_entry;
 | 
						|
	uverbs_finalize_uobj_create(attrs, MLX5_IB_ATTR_PP_OBJ_ALLOC_HANDLE);
 | 
						|
 | 
						|
	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_PP_OBJ_ALLOC_INDEX,
 | 
						|
			     &pp_entry->index, sizeof(pp_entry->index));
 | 
						|
	return err;
 | 
						|
 | 
						|
err:
 | 
						|
	kfree(pp_entry);
 | 
						|
	return err;
 | 
						|
}
 | 
						|
 | 
						|
static int pp_obj_cleanup(struct ib_uobject *uobject,
 | 
						|
			  enum rdma_remove_reason why,
 | 
						|
			  struct uverbs_attr_bundle *attrs)
 | 
						|
{
 | 
						|
	struct mlx5_ib_pp *pp_entry = uobject->object;
 | 
						|
 | 
						|
	mlx5_rl_remove_rate_raw(pp_entry->mdev, pp_entry->index);
 | 
						|
	kfree(pp_entry);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
DECLARE_UVERBS_NAMED_METHOD(
 | 
						|
	MLX5_IB_METHOD_PP_OBJ_ALLOC,
 | 
						|
	UVERBS_ATTR_IDR(MLX5_IB_ATTR_PP_OBJ_ALLOC_HANDLE,
 | 
						|
			MLX5_IB_OBJECT_PP,
 | 
						|
			UVERBS_ACCESS_NEW,
 | 
						|
			UA_MANDATORY),
 | 
						|
	UVERBS_ATTR_PTR_IN(
 | 
						|
		MLX5_IB_ATTR_PP_OBJ_ALLOC_CTX,
 | 
						|
		UVERBS_ATTR_SIZE(1,
 | 
						|
			MLX5_ST_SZ_BYTES(set_pp_rate_limit_context)),
 | 
						|
		UA_MANDATORY,
 | 
						|
		UA_ALLOC_AND_COPY),
 | 
						|
	UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_PP_OBJ_ALLOC_FLAGS,
 | 
						|
			enum mlx5_ib_uapi_pp_alloc_flags,
 | 
						|
			UA_MANDATORY),
 | 
						|
	UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_PP_OBJ_ALLOC_INDEX,
 | 
						|
			   UVERBS_ATTR_TYPE(u16),
 | 
						|
			   UA_MANDATORY));
 | 
						|
 | 
						|
DECLARE_UVERBS_NAMED_METHOD_DESTROY(
 | 
						|
	MLX5_IB_METHOD_PP_OBJ_DESTROY,
 | 
						|
	UVERBS_ATTR_IDR(MLX5_IB_ATTR_PP_OBJ_DESTROY_HANDLE,
 | 
						|
			MLX5_IB_OBJECT_PP,
 | 
						|
			UVERBS_ACCESS_DESTROY,
 | 
						|
			UA_MANDATORY));
 | 
						|
 | 
						|
DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_PP,
 | 
						|
			    UVERBS_TYPE_ALLOC_IDR(pp_obj_cleanup),
 | 
						|
			    &UVERBS_METHOD(MLX5_IB_METHOD_PP_OBJ_ALLOC),
 | 
						|
			    &UVERBS_METHOD(MLX5_IB_METHOD_PP_OBJ_DESTROY));
 | 
						|
 | 
						|
 | 
						|
const struct uapi_definition mlx5_ib_qos_defs[] = {
 | 
						|
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
 | 
						|
		MLX5_IB_OBJECT_PP,
 | 
						|
		UAPI_DEF_IS_OBJ_SUPPORTED(pp_is_supported)),
 | 
						|
	{},
 | 
						|
};
 |