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_wq(struct ib_uobject *uobject, 11 enum rdma_remove_reason why, 12 struct uverbs_attr_bundle *attrs) 13 { 14 struct ib_wq *wq = uobject->object; 15 struct ib_uwq_object *uwq = 16 container_of(uobject, struct ib_uwq_object, uevent.uobject); 17 int ret; 18 19 ret = ib_destroy_wq_user(wq, &attrs->driver_udata); 20 if (ret) 21 return ret; 22 23 ib_uverbs_release_uevent(&uwq->uevent); 24 return 0; 25 } 26 27 static int UVERBS_HANDLER(UVERBS_METHOD_WQ_CREATE)( 28 struct uverbs_attr_bundle *attrs) 29 { 30 struct ib_uwq_object *obj = container_of( 31 uverbs_attr_get_uobject(attrs, UVERBS_ATTR_CREATE_WQ_HANDLE), 32 typeof(*obj), uevent.uobject); 33 struct ib_pd *pd = 34 uverbs_attr_get_obj(attrs, UVERBS_ATTR_CREATE_WQ_PD_HANDLE); 35 struct ib_cq *cq = 36 uverbs_attr_get_obj(attrs, UVERBS_ATTR_CREATE_WQ_CQ_HANDLE); 37 struct ib_wq_init_attr wq_init_attr = {}; 38 struct ib_wq *wq; 39 u64 user_handle; 40 int ret; 41 42 ret = uverbs_get_flags32(&wq_init_attr.create_flags, attrs, 43 UVERBS_ATTR_CREATE_WQ_FLAGS, 44 IB_UVERBS_WQ_FLAGS_CVLAN_STRIPPING | 45 IB_UVERBS_WQ_FLAGS_SCATTER_FCS | 46 IB_UVERBS_WQ_FLAGS_DELAY_DROP | 47 IB_UVERBS_WQ_FLAGS_PCI_WRITE_END_PADDING); 48 if (!ret) 49 ret = uverbs_copy_from(&wq_init_attr.max_sge, attrs, 50 UVERBS_ATTR_CREATE_WQ_MAX_SGE); 51 if (!ret) 52 ret = uverbs_copy_from(&wq_init_attr.max_wr, attrs, 53 UVERBS_ATTR_CREATE_WQ_MAX_WR); 54 if (!ret) 55 ret = uverbs_copy_from(&user_handle, attrs, 56 UVERBS_ATTR_CREATE_WQ_USER_HANDLE); 57 if (!ret) 58 ret = uverbs_get_const(&wq_init_attr.wq_type, attrs, 59 UVERBS_ATTR_CREATE_WQ_TYPE); 60 if (ret) 61 return ret; 62 63 if (wq_init_attr.wq_type != IB_WQT_RQ) 64 return -EINVAL; 65 66 obj->uevent.event_file = ib_uverbs_get_async_event(attrs, 67 UVERBS_ATTR_CREATE_WQ_EVENT_FD); 68 obj->uevent.uobject.user_handle = user_handle; 69 INIT_LIST_HEAD(&obj->uevent.event_list); 70 wq_init_attr.event_handler = ib_uverbs_wq_event_handler; 71 wq_init_attr.wq_context = attrs->ufile; 72 wq_init_attr.cq = cq; 73 74 wq = pd->device->ops.create_wq(pd, &wq_init_attr, &attrs->driver_udata); 75 if (IS_ERR(wq)) { 76 ret = PTR_ERR(wq); 77 goto err; 78 } 79 80 obj->uevent.uobject.object = wq; 81 wq->wq_type = wq_init_attr.wq_type; 82 wq->cq = cq; 83 wq->pd = pd; 84 wq->device = pd->device; 85 wq->wq_context = wq_init_attr.wq_context; 86 atomic_set(&wq->usecnt, 0); 87 atomic_inc(&pd->usecnt); 88 atomic_inc(&cq->usecnt); 89 wq->uobject = obj; 90 uverbs_finalize_uobj_create(attrs, UVERBS_ATTR_CREATE_WQ_HANDLE); 91 92 ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_WQ_RESP_MAX_WR, 93 &wq_init_attr.max_wr, 94 sizeof(wq_init_attr.max_wr)); 95 if (ret) 96 return ret; 97 98 ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_WQ_RESP_MAX_SGE, 99 &wq_init_attr.max_sge, 100 sizeof(wq_init_attr.max_sge)); 101 if (ret) 102 return ret; 103 104 ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_WQ_RESP_WQ_NUM, 105 &wq->wq_num, 106 sizeof(wq->wq_num)); 107 return ret; 108 109 err: 110 if (obj->uevent.event_file) 111 uverbs_uobject_put(&obj->uevent.event_file->uobj); 112 return ret; 113 }; 114 115 DECLARE_UVERBS_NAMED_METHOD( 116 UVERBS_METHOD_WQ_CREATE, 117 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_WQ_HANDLE, 118 UVERBS_OBJECT_WQ, 119 UVERBS_ACCESS_NEW, 120 UA_MANDATORY), 121 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_WQ_PD_HANDLE, 122 UVERBS_OBJECT_PD, 123 UVERBS_ACCESS_READ, 124 UA_MANDATORY), 125 UVERBS_ATTR_CONST_IN(UVERBS_ATTR_CREATE_WQ_TYPE, 126 enum ib_wq_type, 127 UA_MANDATORY), 128 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_WQ_USER_HANDLE, 129 UVERBS_ATTR_TYPE(u64), 130 UA_MANDATORY), 131 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_WQ_MAX_WR, 132 UVERBS_ATTR_TYPE(u32), 133 UA_MANDATORY), 134 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_WQ_MAX_SGE, 135 UVERBS_ATTR_TYPE(u32), 136 UA_MANDATORY), 137 UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_CREATE_WQ_FLAGS, 138 enum ib_uverbs_wq_flags, 139 UA_MANDATORY), 140 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_WQ_CQ_HANDLE, 141 UVERBS_OBJECT_CQ, 142 UVERBS_ACCESS_READ, 143 UA_OPTIONAL), 144 UVERBS_ATTR_FD(UVERBS_ATTR_CREATE_WQ_EVENT_FD, 145 UVERBS_OBJECT_ASYNC_EVENT, 146 UVERBS_ACCESS_READ, 147 UA_OPTIONAL), 148 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_WQ_RESP_MAX_WR, 149 UVERBS_ATTR_TYPE(u32), 150 UA_MANDATORY), 151 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_WQ_RESP_MAX_SGE, 152 UVERBS_ATTR_TYPE(u32), 153 UA_MANDATORY), 154 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_WQ_RESP_WQ_NUM, 155 UVERBS_ATTR_TYPE(u32), 156 UA_OPTIONAL), 157 UVERBS_ATTR_UHW()); 158 159 static int UVERBS_HANDLER(UVERBS_METHOD_WQ_DESTROY)( 160 struct uverbs_attr_bundle *attrs) 161 { 162 struct ib_uobject *uobj = 163 uverbs_attr_get_uobject(attrs, UVERBS_ATTR_DESTROY_WQ_HANDLE); 164 struct ib_uwq_object *obj = 165 container_of(uobj, struct ib_uwq_object, uevent.uobject); 166 167 return uverbs_copy_to(attrs, UVERBS_ATTR_DESTROY_WQ_RESP, 168 &obj->uevent.events_reported, 169 sizeof(obj->uevent.events_reported)); 170 } 171 172 DECLARE_UVERBS_NAMED_METHOD( 173 UVERBS_METHOD_WQ_DESTROY, 174 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_WQ_HANDLE, 175 UVERBS_OBJECT_WQ, 176 UVERBS_ACCESS_DESTROY, 177 UA_MANDATORY), 178 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_DESTROY_WQ_RESP, 179 UVERBS_ATTR_TYPE(u32), 180 UA_MANDATORY)); 181 182 183 DECLARE_UVERBS_NAMED_OBJECT( 184 UVERBS_OBJECT_WQ, 185 UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uwq_object), uverbs_free_wq), 186 &UVERBS_METHOD(UVERBS_METHOD_WQ_CREATE), 187 &UVERBS_METHOD(UVERBS_METHOD_WQ_DESTROY) 188 ); 189 190 const struct uapi_definition uverbs_def_obj_wq[] = { 191 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_WQ, 192 UAPI_DEF_OBJ_NEEDS_FN(destroy_wq)), 193 {} 194 }; 195