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 | |
34 | static inline void *_uobj_get_obj_read(struct ib_uobject *uobj) |
35 | { |
36 | if (IS_ERR(ptr: 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 | |
62 | static inline void uobj_put_destroy(struct ib_uobject *uobj) |
63 | { |
64 | rdma_lookup_put_uobject(uobj, mode: UVERBS_LOOKUP_DESTROY); |
65 | } |
66 | |
67 | static inline void uobj_put_read(struct ib_uobject *uobj) |
68 | { |
69 | rdma_lookup_put_uobject(uobj, mode: UVERBS_LOOKUP_READ); |
70 | } |
71 | |
72 | #define uobj_put_obj_read(_obj) \ |
73 | uobj_put_read((_obj)->uobject) |
74 | |
75 | static inline void uobj_put_write(struct ib_uobject *uobj) |
76 | { |
77 | rdma_lookup_put_uobject(uobj, mode: UVERBS_LOOKUP_WRITE); |
78 | } |
79 | |
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, hw_obj_valid: false); |
84 | } |
85 | |
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 * |
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(ptr: 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 | |
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(v: &action->usecnt, i: 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 | |
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(v: &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 | |
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 | |