1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* 3 * Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. 4 */ 5 6 #include <rdma/uverbs_std_types.h> 7 #include "rdma_core.h" 8 #include "uverbs.h" 9 10 static int uverbs_free_srq(struct ib_uobject *uobject, 11 enum rdma_remove_reason why, 12 struct uverbs_attr_bundle *attrs) 13 { 14 struct ib_srq *srq = uobject->object; 15 struct ib_uevent_object *uevent = 16 container_of(uobject, struct ib_uevent_object, uobject); 17 enum ib_srq_type srq_type = srq->srq_type; 18 int ret; 19 20 ret = ib_destroy_srq_user(srq, &attrs->driver_udata); 21 if (ret) 22 return ret; 23 24 if (srq_type == IB_SRQT_XRC) { 25 struct ib_usrq_object *us = 26 container_of(uobject, struct ib_usrq_object, 27 uevent.uobject); 28 29 atomic_dec(&us->uxrcd->refcnt); 30 } 31 32 ib_uverbs_release_uevent(uevent); 33 return 0; 34 } 35 36 static int UVERBS_HANDLER(UVERBS_METHOD_SRQ_CREATE)( 37 struct uverbs_attr_bundle *attrs) 38 { 39 struct ib_usrq_object *obj = container_of( 40 uverbs_attr_get_uobject(attrs, UVERBS_ATTR_CREATE_SRQ_HANDLE), 41 typeof(*obj), uevent.uobject); 42 struct ib_pd *pd = 43 uverbs_attr_get_obj(attrs, UVERBS_ATTR_CREATE_SRQ_PD_HANDLE); 44 struct ib_srq_init_attr attr = {}; 45 struct ib_uobject *xrcd_uobj; 46 struct ib_srq *srq; 47 u64 user_handle; 48 int ret; 49 50 ret = uverbs_copy_from(&attr.attr.max_sge, attrs, 51 UVERBS_ATTR_CREATE_SRQ_MAX_SGE); 52 if (!ret) 53 ret = uverbs_copy_from(&attr.attr.max_wr, attrs, 54 UVERBS_ATTR_CREATE_SRQ_MAX_WR); 55 if (!ret) 56 ret = uverbs_copy_from(&attr.attr.srq_limit, attrs, 57 UVERBS_ATTR_CREATE_SRQ_LIMIT); 58 if (!ret) 59 ret = uverbs_copy_from(&user_handle, attrs, 60 UVERBS_ATTR_CREATE_SRQ_USER_HANDLE); 61 if (!ret) 62 ret = uverbs_get_const(&attr.srq_type, attrs, 63 UVERBS_ATTR_CREATE_SRQ_TYPE); 64 if (ret) 65 return ret; 66 67 if (ib_srq_has_cq(attr.srq_type)) { 68 attr.ext.cq = uverbs_attr_get_obj(attrs, 69 UVERBS_ATTR_CREATE_SRQ_CQ_HANDLE); 70 if (IS_ERR(attr.ext.cq)) 71 return PTR_ERR(attr.ext.cq); 72 } 73 74 switch (attr.srq_type) { 75 case IB_UVERBS_SRQT_XRC: 76 xrcd_uobj = uverbs_attr_get_uobject(attrs, 77 UVERBS_ATTR_CREATE_SRQ_XRCD_HANDLE); 78 if (IS_ERR(xrcd_uobj)) 79 return PTR_ERR(xrcd_uobj); 80 81 attr.ext.xrc.xrcd = (struct ib_xrcd *)xrcd_uobj->object; 82 if (!attr.ext.xrc.xrcd) 83 return -EINVAL; 84 obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, 85 uobject); 86 atomic_inc(&obj->uxrcd->refcnt); 87 break; 88 case IB_UVERBS_SRQT_TM: 89 ret = uverbs_copy_from(&attr.ext.tag_matching.max_num_tags, 90 attrs, 91 UVERBS_ATTR_CREATE_SRQ_MAX_NUM_TAGS); 92 if (ret) 93 return ret; 94 break; 95 case IB_UVERBS_SRQT_BASIC: 96 break; 97 default: 98 return -EINVAL; 99 } 100 101 obj->uevent.event_file = ib_uverbs_get_async_event(attrs, 102 UVERBS_ATTR_CREATE_SRQ_EVENT_FD); 103 INIT_LIST_HEAD(&obj->uevent.event_list); 104 attr.event_handler = ib_uverbs_srq_event_handler; 105 obj->uevent.uobject.user_handle = user_handle; 106 107 srq = ib_create_srq_user(pd, &attr, obj, &attrs->driver_udata); 108 if (IS_ERR(srq)) { 109 ret = PTR_ERR(srq); 110 goto err; 111 } 112 113 obj->uevent.uobject.object = srq; 114 uverbs_finalize_uobj_create(attrs, UVERBS_ATTR_CREATE_SRQ_HANDLE); 115 116 ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_SRQ_RESP_MAX_WR, 117 &attr.attr.max_wr, 118 sizeof(attr.attr.max_wr)); 119 if (ret) 120 return ret; 121 122 ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_SRQ_RESP_MAX_SGE, 123 &attr.attr.max_sge, 124 sizeof(attr.attr.max_sge)); 125 if (ret) 126 return ret; 127 128 if (attr.srq_type == IB_SRQT_XRC) { 129 ret = uverbs_copy_to(attrs, 130 UVERBS_ATTR_CREATE_SRQ_RESP_SRQ_NUM, 131 &srq->ext.xrc.srq_num, 132 sizeof(srq->ext.xrc.srq_num)); 133 if (ret) 134 return ret; 135 } 136 137 return 0; 138 err: 139 if (obj->uevent.event_file) 140 uverbs_uobject_put(&obj->uevent.event_file->uobj); 141 if (attr.srq_type == IB_SRQT_XRC) 142 atomic_dec(&obj->uxrcd->refcnt); 143 return ret; 144 }; 145 146 DECLARE_UVERBS_NAMED_METHOD( 147 UVERBS_METHOD_SRQ_CREATE, 148 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_SRQ_HANDLE, 149 UVERBS_OBJECT_SRQ, 150 UVERBS_ACCESS_NEW, 151 UA_MANDATORY), 152 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_SRQ_PD_HANDLE, 153 UVERBS_OBJECT_PD, 154 UVERBS_ACCESS_READ, 155 UA_MANDATORY), 156 UVERBS_ATTR_CONST_IN(UVERBS_ATTR_CREATE_SRQ_TYPE, 157 enum ib_uverbs_srq_type, 158 UA_MANDATORY), 159 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_USER_HANDLE, 160 UVERBS_ATTR_TYPE(u64), 161 UA_MANDATORY), 162 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_MAX_WR, 163 UVERBS_ATTR_TYPE(u32), 164 UA_MANDATORY), 165 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_MAX_SGE, 166 UVERBS_ATTR_TYPE(u32), 167 UA_MANDATORY), 168 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_LIMIT, 169 UVERBS_ATTR_TYPE(u32), 170 UA_MANDATORY), 171 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_SRQ_XRCD_HANDLE, 172 UVERBS_OBJECT_XRCD, 173 UVERBS_ACCESS_READ, 174 UA_OPTIONAL), 175 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_SRQ_CQ_HANDLE, 176 UVERBS_OBJECT_CQ, 177 UVERBS_ACCESS_READ, 178 UA_OPTIONAL), 179 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_MAX_NUM_TAGS, 180 UVERBS_ATTR_TYPE(u32), 181 UA_OPTIONAL), 182 UVERBS_ATTR_FD(UVERBS_ATTR_CREATE_SRQ_EVENT_FD, 183 UVERBS_OBJECT_ASYNC_EVENT, 184 UVERBS_ACCESS_READ, 185 UA_OPTIONAL), 186 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_SRQ_RESP_MAX_WR, 187 UVERBS_ATTR_TYPE(u32), 188 UA_MANDATORY), 189 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_SRQ_RESP_MAX_SGE, 190 UVERBS_ATTR_TYPE(u32), 191 UA_MANDATORY), 192 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_SRQ_RESP_SRQ_NUM, 193 UVERBS_ATTR_TYPE(u32), 194 UA_OPTIONAL), 195 UVERBS_ATTR_UHW()); 196 197 static int UVERBS_HANDLER(UVERBS_METHOD_SRQ_DESTROY)( 198 struct uverbs_attr_bundle *attrs) 199 { 200 struct ib_uobject *uobj = 201 uverbs_attr_get_uobject(attrs, UVERBS_ATTR_DESTROY_SRQ_HANDLE); 202 struct ib_usrq_object *obj = 203 container_of(uobj, struct ib_usrq_object, uevent.uobject); 204 struct ib_uverbs_destroy_srq_resp resp = { 205 .events_reported = obj->uevent.events_reported 206 }; 207 208 return uverbs_copy_to(attrs, UVERBS_ATTR_DESTROY_SRQ_RESP, &resp, 209 sizeof(resp)); 210 } 211 212 DECLARE_UVERBS_NAMED_METHOD( 213 UVERBS_METHOD_SRQ_DESTROY, 214 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_SRQ_HANDLE, 215 UVERBS_OBJECT_SRQ, 216 UVERBS_ACCESS_DESTROY, 217 UA_MANDATORY), 218 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_DESTROY_SRQ_RESP, 219 UVERBS_ATTR_TYPE(struct ib_uverbs_destroy_srq_resp), 220 UA_MANDATORY)); 221 222 DECLARE_UVERBS_NAMED_OBJECT( 223 UVERBS_OBJECT_SRQ, 224 UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_usrq_object), 225 uverbs_free_srq), 226 &UVERBS_METHOD(UVERBS_METHOD_SRQ_CREATE), 227 &UVERBS_METHOD(UVERBS_METHOD_SRQ_DESTROY) 228 ); 229 230 const struct uapi_definition uverbs_def_obj_srq[] = { 231 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_SRQ, 232 UAPI_DEF_OBJ_NEEDS_FN(destroy_srq)), 233 {} 234 }; 235