| 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 ERR_CAST(ptr: uobj); |
| 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 | |