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