1  /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
2  /*
3   * Copyright (c) 2017, Mellanox Technologies inc.  All rights reserved.
4   */
5  
6  #ifndef _UVERBS_STD_TYPES__
7  #define _UVERBS_STD_TYPES__
8  
9  #include <rdma/uverbs_types.h>
10  #include <rdma/uverbs_ioctl.h>
11  #include <rdma/ib_user_ioctl_verbs.h>
12  
13  /* Returns _id, or causes a compile error if _id is not a u32.
14   *
15   * The uobj APIs should only be used with the write based uAPI to access
16   * object IDs. The write API must use a u32 for the object handle, which is
17   * checked by this macro.
18   */
19  #define _uobj_check_id(_id) ((_id) * typecheck(u32, _id))
20  
21  #define uobj_get_type(_attrs, _object)                                         \
22  	uapi_get_object((_attrs)->ufile->device->uapi, _object)
23  
24  #define uobj_get_read(_type, _id, _attrs)                                      \
25  	rdma_lookup_get_uobject(uobj_get_type(_attrs, _type), (_attrs)->ufile, \
26  				_uobj_check_id(_id), UVERBS_LOOKUP_READ,       \
27  				_attrs)
28  
29  #define ufd_get_read(_type, _fdnum, _attrs)                                    \
30  	rdma_lookup_get_uobject(uobj_get_type(_attrs, _type), (_attrs)->ufile, \
31  				(_fdnum)*typecheck(s32, _fdnum),               \
32  				UVERBS_LOOKUP_READ, _attrs)
33  
_uobj_get_obj_read(struct ib_uobject * uobj)34  static inline void *_uobj_get_obj_read(struct ib_uobject *uobj)
35  {
36  	if (IS_ERR(uobj))
37  		return NULL;
38  	return uobj->object;
39  }
40  #define uobj_get_obj_read(_object, _type, _id, _attrs)                         \
41  	((struct ib_##_object *)_uobj_get_obj_read(                            \
42  		uobj_get_read(_type, _id, _attrs)))
43  
44  #define uobj_get_write(_type, _id, _attrs)                                     \
45  	rdma_lookup_get_uobject(uobj_get_type(_attrs, _type), (_attrs)->ufile, \
46  				_uobj_check_id(_id), UVERBS_LOOKUP_WRITE,      \
47  				_attrs)
48  
49  int __uobj_perform_destroy(const struct uverbs_api_object *obj, u32 id,
50  			   struct uverbs_attr_bundle *attrs);
51  #define uobj_perform_destroy(_type, _id, _attrs)                               \
52  	__uobj_perform_destroy(uobj_get_type(_attrs, _type),                   \
53  			       _uobj_check_id(_id), _attrs)
54  
55  struct ib_uobject *__uobj_get_destroy(const struct uverbs_api_object *obj,
56  				      u32 id, struct uverbs_attr_bundle *attrs);
57  
58  #define uobj_get_destroy(_type, _id, _attrs)                                   \
59  	__uobj_get_destroy(uobj_get_type(_attrs, _type), _uobj_check_id(_id),  \
60  			   _attrs)
61  
uobj_put_destroy(struct ib_uobject * uobj)62  static inline void uobj_put_destroy(struct ib_uobject *uobj)
63  {
64  	rdma_lookup_put_uobject(uobj, UVERBS_LOOKUP_DESTROY);
65  }
66  
uobj_put_read(struct ib_uobject * uobj)67  static inline void uobj_put_read(struct ib_uobject *uobj)
68  {
69  	rdma_lookup_put_uobject(uobj, UVERBS_LOOKUP_READ);
70  }
71  
72  #define uobj_put_obj_read(_obj)					\
73  	uobj_put_read((_obj)->uobject)
74  
uobj_put_write(struct ib_uobject * uobj)75  static inline void uobj_put_write(struct ib_uobject *uobj)
76  {
77  	rdma_lookup_put_uobject(uobj, UVERBS_LOOKUP_WRITE);
78  }
79  
uobj_alloc_abort(struct ib_uobject * uobj,struct uverbs_attr_bundle * attrs)80  static inline void uobj_alloc_abort(struct ib_uobject *uobj,
81  				    struct uverbs_attr_bundle *attrs)
82  {
83  	rdma_alloc_abort_uobject(uobj, attrs, false);
84  }
85  
uobj_finalize_uobj_create(struct ib_uobject * uobj,struct uverbs_attr_bundle * attrs)86  static inline void uobj_finalize_uobj_create(struct ib_uobject *uobj,
87  					     struct uverbs_attr_bundle *attrs)
88  {
89  	/*
90  	 * Tell the core code that the write() handler has completed
91  	 * initializing the object and that the core should commit or
92  	 * abort this object based upon the return code from the write()
93  	 * method. Similar to what uverbs_finalize_uobj_create() does for
94  	 * ioctl()
95  	 */
96  	WARN_ON(attrs->uobject);
97  	attrs->uobject = uobj;
98  }
99  
100  static inline struct ib_uobject *
__uobj_alloc(const struct uverbs_api_object * obj,struct uverbs_attr_bundle * attrs,struct ib_device ** ib_dev)101  __uobj_alloc(const struct uverbs_api_object *obj,
102  	     struct uverbs_attr_bundle *attrs, struct ib_device **ib_dev)
103  {
104  	struct ib_uobject *uobj = rdma_alloc_begin_uobject(obj, attrs);
105  
106  	if (!IS_ERR(uobj))
107  		*ib_dev = attrs->context->device;
108  	return uobj;
109  }
110  
111  #define uobj_alloc(_type, _attrs, _ib_dev)                                     \
112  	__uobj_alloc(uobj_get_type(_attrs, _type), _attrs, _ib_dev)
113  
uverbs_flow_action_fill_action(struct ib_flow_action * action,struct ib_uobject * uobj,struct ib_device * ib_dev,enum ib_flow_action_type type)114  static inline void uverbs_flow_action_fill_action(struct ib_flow_action *action,
115  						  struct ib_uobject *uobj,
116  						  struct ib_device *ib_dev,
117  						  enum ib_flow_action_type type)
118  {
119  	atomic_set(&action->usecnt, 0);
120  	action->device = ib_dev;
121  	action->type = type;
122  	action->uobject = uobj;
123  	uobj->object = action;
124  }
125  
126  struct ib_uflow_resources {
127  	size_t			max;
128  	size_t			num;
129  	size_t			collection_num;
130  	size_t			counters_num;
131  	struct ib_counters	**counters;
132  	struct ib_flow_action	**collection;
133  };
134  
135  struct ib_uflow_object {
136  	struct ib_uobject		uobject;
137  	struct ib_uflow_resources	*resources;
138  };
139  
140  struct ib_uflow_resources *flow_resources_alloc(size_t num_specs);
141  void flow_resources_add(struct ib_uflow_resources *uflow_res,
142  			enum ib_flow_spec_type type,
143  			void *ibobj);
144  void ib_uverbs_flow_resources_free(struct ib_uflow_resources *uflow_res);
145  
ib_set_flow(struct ib_uobject * uobj,struct ib_flow * ibflow,struct ib_qp * qp,struct ib_device * device,struct ib_uflow_resources * uflow_res)146  static inline void ib_set_flow(struct ib_uobject *uobj, struct ib_flow *ibflow,
147  			       struct ib_qp *qp, struct ib_device *device,
148  			       struct ib_uflow_resources *uflow_res)
149  {
150  	struct ib_uflow_object *uflow;
151  
152  	uobj->object = ibflow;
153  	ibflow->uobject = uobj;
154  
155  	if (qp) {
156  		atomic_inc(&qp->usecnt);
157  		ibflow->qp = qp;
158  	}
159  
160  	ibflow->device = device;
161  	uflow = container_of(uobj, typeof(*uflow), uobject);
162  	uflow->resources = uflow_res;
163  }
164  
165  struct uverbs_api_object {
166  	const struct uverbs_obj_type *type_attrs;
167  	const struct uverbs_obj_type_class *type_class;
168  	u8 disabled:1;
169  	u32 id;
170  };
171  
uobj_get_object_id(struct ib_uobject * uobj)172  static inline u32 uobj_get_object_id(struct ib_uobject *uobj)
173  {
174  	return uobj->uapi_object->id;
175  }
176  
177  #endif
178  
179