diff options
author | Yishai Hadas <yishaih@mellanox.com> | 2016-05-23 08:20:49 -0400 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-06-23 11:02:43 -0400 |
commit | f213c05272100f385912372fff678d0af4d7f8ad (patch) | |
tree | 7aeb69b757cad6d6209ec3790583fac3b657226a | |
parent | 5fd251c8b4c52da0d0916470a67fbb77b972125e (diff) |
IB/uverbs: Add WQ support
User space applications which use RSS functionality need to create
a work queue object (WQ). The lifetime of such an object is:
* Create a WQ
* Modify the WQ from reset to init state.
* Use the WQ (by downstream patches).
* Destroy the WQ.
These commands are added to the uverbs API.
Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Matan Barak <matanb@mellanox.com>
Reviewed-by: Sagi Grimberg <sagi@rimberg.me>
Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r-- | drivers/infiniband/core/uverbs.h | 9 | ||||
-rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 243 | ||||
-rw-r--r-- | drivers/infiniband/core/uverbs_main.c | 25 | ||||
-rw-r--r-- | include/rdma/ib_verbs.h | 3 | ||||
-rw-r--r-- | include/uapi/rdma/ib_user_verbs.h | 41 |
5 files changed, 321 insertions, 0 deletions
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index 612ccfd39bf9..74776c6531f4 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h | |||
@@ -162,6 +162,10 @@ struct ib_uqp_object { | |||
162 | struct ib_uxrcd_object *uxrcd; | 162 | struct ib_uxrcd_object *uxrcd; |
163 | }; | 163 | }; |
164 | 164 | ||
165 | struct ib_uwq_object { | ||
166 | struct ib_uevent_object uevent; | ||
167 | }; | ||
168 | |||
165 | struct ib_ucq_object { | 169 | struct ib_ucq_object { |
166 | struct ib_uobject uobject; | 170 | struct ib_uobject uobject; |
167 | struct ib_uverbs_file *uverbs_file; | 171 | struct ib_uverbs_file *uverbs_file; |
@@ -181,6 +185,7 @@ extern struct idr ib_uverbs_qp_idr; | |||
181 | extern struct idr ib_uverbs_srq_idr; | 185 | extern struct idr ib_uverbs_srq_idr; |
182 | extern struct idr ib_uverbs_xrcd_idr; | 186 | extern struct idr ib_uverbs_xrcd_idr; |
183 | extern struct idr ib_uverbs_rule_idr; | 187 | extern struct idr ib_uverbs_rule_idr; |
188 | extern struct idr ib_uverbs_wq_idr; | ||
184 | 189 | ||
185 | void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj); | 190 | void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj); |
186 | 191 | ||
@@ -199,6 +204,7 @@ void ib_uverbs_release_uevent(struct ib_uverbs_file *file, | |||
199 | void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context); | 204 | void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context); |
200 | void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr); | 205 | void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr); |
201 | void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr); | 206 | void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr); |
207 | void ib_uverbs_wq_event_handler(struct ib_event *event, void *context_ptr); | ||
202 | void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr); | 208 | void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr); |
203 | void ib_uverbs_event_handler(struct ib_event_handler *handler, | 209 | void ib_uverbs_event_handler(struct ib_event_handler *handler, |
204 | struct ib_event *event); | 210 | struct ib_event *event); |
@@ -275,5 +281,8 @@ IB_UVERBS_DECLARE_EX_CMD(destroy_flow); | |||
275 | IB_UVERBS_DECLARE_EX_CMD(query_device); | 281 | IB_UVERBS_DECLARE_EX_CMD(query_device); |
276 | IB_UVERBS_DECLARE_EX_CMD(create_cq); | 282 | IB_UVERBS_DECLARE_EX_CMD(create_cq); |
277 | IB_UVERBS_DECLARE_EX_CMD(create_qp); | 283 | IB_UVERBS_DECLARE_EX_CMD(create_qp); |
284 | IB_UVERBS_DECLARE_EX_CMD(create_wq); | ||
285 | IB_UVERBS_DECLARE_EX_CMD(modify_wq); | ||
286 | IB_UVERBS_DECLARE_EX_CMD(destroy_wq); | ||
278 | 287 | ||
279 | #endif /* UVERBS_H */ | 288 | #endif /* UVERBS_H */ |
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 1a8babb8ee3c..22e617391657 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
@@ -57,6 +57,7 @@ static struct uverbs_lock_class ah_lock_class = { .name = "AH-uobj" }; | |||
57 | static struct uverbs_lock_class srq_lock_class = { .name = "SRQ-uobj" }; | 57 | static struct uverbs_lock_class srq_lock_class = { .name = "SRQ-uobj" }; |
58 | static struct uverbs_lock_class xrcd_lock_class = { .name = "XRCD-uobj" }; | 58 | static struct uverbs_lock_class xrcd_lock_class = { .name = "XRCD-uobj" }; |
59 | static struct uverbs_lock_class rule_lock_class = { .name = "RULE-uobj" }; | 59 | static struct uverbs_lock_class rule_lock_class = { .name = "RULE-uobj" }; |
60 | static struct uverbs_lock_class wq_lock_class = { .name = "WQ-uobj" }; | ||
60 | 61 | ||
61 | /* | 62 | /* |
62 | * The ib_uobject locking scheme is as follows: | 63 | * The ib_uobject locking scheme is as follows: |
@@ -243,6 +244,16 @@ static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context) | |||
243 | return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context, 0); | 244 | return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context, 0); |
244 | } | 245 | } |
245 | 246 | ||
247 | static struct ib_wq *idr_read_wq(int wq_handle, struct ib_ucontext *context) | ||
248 | { | ||
249 | return idr_read_obj(&ib_uverbs_wq_idr, wq_handle, context, 0); | ||
250 | } | ||
251 | |||
252 | static void put_wq_read(struct ib_wq *wq) | ||
253 | { | ||
254 | put_uobj_read(wq->uobject); | ||
255 | } | ||
256 | |||
246 | static struct ib_qp *idr_write_qp(int qp_handle, struct ib_ucontext *context) | 257 | static struct ib_qp *idr_write_qp(int qp_handle, struct ib_ucontext *context) |
247 | { | 258 | { |
248 | struct ib_uobject *uobj; | 259 | struct ib_uobject *uobj; |
@@ -326,6 +337,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, | |||
326 | INIT_LIST_HEAD(&ucontext->qp_list); | 337 | INIT_LIST_HEAD(&ucontext->qp_list); |
327 | INIT_LIST_HEAD(&ucontext->srq_list); | 338 | INIT_LIST_HEAD(&ucontext->srq_list); |
328 | INIT_LIST_HEAD(&ucontext->ah_list); | 339 | INIT_LIST_HEAD(&ucontext->ah_list); |
340 | INIT_LIST_HEAD(&ucontext->wq_list); | ||
329 | INIT_LIST_HEAD(&ucontext->xrcd_list); | 341 | INIT_LIST_HEAD(&ucontext->xrcd_list); |
330 | INIT_LIST_HEAD(&ucontext->rule_list); | 342 | INIT_LIST_HEAD(&ucontext->rule_list); |
331 | rcu_read_lock(); | 343 | rcu_read_lock(); |
@@ -3056,6 +3068,237 @@ static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec, | |||
3056 | return 0; | 3068 | return 0; |
3057 | } | 3069 | } |
3058 | 3070 | ||
3071 | int ib_uverbs_ex_create_wq(struct ib_uverbs_file *file, | ||
3072 | struct ib_device *ib_dev, | ||
3073 | struct ib_udata *ucore, | ||
3074 | struct ib_udata *uhw) | ||
3075 | { | ||
3076 | struct ib_uverbs_ex_create_wq cmd = {}; | ||
3077 | struct ib_uverbs_ex_create_wq_resp resp = {}; | ||
3078 | struct ib_uwq_object *obj; | ||
3079 | int err = 0; | ||
3080 | struct ib_cq *cq; | ||
3081 | struct ib_pd *pd; | ||
3082 | struct ib_wq *wq; | ||
3083 | struct ib_wq_init_attr wq_init_attr = {}; | ||
3084 | size_t required_cmd_sz; | ||
3085 | size_t required_resp_len; | ||
3086 | |||
3087 | required_cmd_sz = offsetof(typeof(cmd), max_sge) + sizeof(cmd.max_sge); | ||
3088 | required_resp_len = offsetof(typeof(resp), wqn) + sizeof(resp.wqn); | ||
3089 | |||
3090 | if (ucore->inlen < required_cmd_sz) | ||
3091 | return -EINVAL; | ||
3092 | |||
3093 | if (ucore->outlen < required_resp_len) | ||
3094 | return -ENOSPC; | ||
3095 | |||
3096 | if (ucore->inlen > sizeof(cmd) && | ||
3097 | !ib_is_udata_cleared(ucore, sizeof(cmd), | ||
3098 | ucore->inlen - sizeof(cmd))) | ||
3099 | return -EOPNOTSUPP; | ||
3100 | |||
3101 | err = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen)); | ||
3102 | if (err) | ||
3103 | return err; | ||
3104 | |||
3105 | if (cmd.comp_mask) | ||
3106 | return -EOPNOTSUPP; | ||
3107 | |||
3108 | obj = kmalloc(sizeof(*obj), GFP_KERNEL); | ||
3109 | if (!obj) | ||
3110 | return -ENOMEM; | ||
3111 | |||
3112 | init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, | ||
3113 | &wq_lock_class); | ||
3114 | down_write(&obj->uevent.uobject.mutex); | ||
3115 | pd = idr_read_pd(cmd.pd_handle, file->ucontext); | ||
3116 | if (!pd) { | ||
3117 | err = -EINVAL; | ||
3118 | goto err_uobj; | ||
3119 | } | ||
3120 | |||
3121 | cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0); | ||
3122 | if (!cq) { | ||
3123 | err = -EINVAL; | ||
3124 | goto err_put_pd; | ||
3125 | } | ||
3126 | |||
3127 | wq_init_attr.cq = cq; | ||
3128 | wq_init_attr.max_sge = cmd.max_sge; | ||
3129 | wq_init_attr.max_wr = cmd.max_wr; | ||
3130 | wq_init_attr.wq_context = file; | ||
3131 | wq_init_attr.wq_type = cmd.wq_type; | ||
3132 | wq_init_attr.event_handler = ib_uverbs_wq_event_handler; | ||
3133 | obj->uevent.events_reported = 0; | ||
3134 | INIT_LIST_HEAD(&obj->uevent.event_list); | ||
3135 | wq = pd->device->create_wq(pd, &wq_init_attr, uhw); | ||
3136 | if (IS_ERR(wq)) { | ||
3137 | err = PTR_ERR(wq); | ||
3138 | goto err_put_cq; | ||
3139 | } | ||
3140 | |||
3141 | wq->uobject = &obj->uevent.uobject; | ||
3142 | obj->uevent.uobject.object = wq; | ||
3143 | wq->wq_type = wq_init_attr.wq_type; | ||
3144 | wq->cq = cq; | ||
3145 | wq->pd = pd; | ||
3146 | wq->device = pd->device; | ||
3147 | wq->wq_context = wq_init_attr.wq_context; | ||
3148 | atomic_set(&wq->usecnt, 0); | ||
3149 | atomic_inc(&pd->usecnt); | ||
3150 | atomic_inc(&cq->usecnt); | ||
3151 | wq->uobject = &obj->uevent.uobject; | ||
3152 | obj->uevent.uobject.object = wq; | ||
3153 | err = idr_add_uobj(&ib_uverbs_wq_idr, &obj->uevent.uobject); | ||
3154 | if (err) | ||
3155 | goto destroy_wq; | ||
3156 | |||
3157 | memset(&resp, 0, sizeof(resp)); | ||
3158 | resp.wq_handle = obj->uevent.uobject.id; | ||
3159 | resp.max_sge = wq_init_attr.max_sge; | ||
3160 | resp.max_wr = wq_init_attr.max_wr; | ||
3161 | resp.wqn = wq->wq_num; | ||
3162 | resp.response_length = required_resp_len; | ||
3163 | err = ib_copy_to_udata(ucore, | ||
3164 | &resp, resp.response_length); | ||
3165 | if (err) | ||
3166 | goto err_copy; | ||
3167 | |||
3168 | put_pd_read(pd); | ||
3169 | put_cq_read(cq); | ||
3170 | |||
3171 | mutex_lock(&file->mutex); | ||
3172 | list_add_tail(&obj->uevent.uobject.list, &file->ucontext->wq_list); | ||
3173 | mutex_unlock(&file->mutex); | ||
3174 | |||
3175 | obj->uevent.uobject.live = 1; | ||
3176 | up_write(&obj->uevent.uobject.mutex); | ||
3177 | return 0; | ||
3178 | |||
3179 | err_copy: | ||
3180 | idr_remove_uobj(&ib_uverbs_wq_idr, &obj->uevent.uobject); | ||
3181 | destroy_wq: | ||
3182 | ib_destroy_wq(wq); | ||
3183 | err_put_cq: | ||
3184 | put_cq_read(cq); | ||
3185 | err_put_pd: | ||
3186 | put_pd_read(pd); | ||
3187 | err_uobj: | ||
3188 | put_uobj_write(&obj->uevent.uobject); | ||
3189 | |||
3190 | return err; | ||
3191 | } | ||
3192 | |||
3193 | int ib_uverbs_ex_destroy_wq(struct ib_uverbs_file *file, | ||
3194 | struct ib_device *ib_dev, | ||
3195 | struct ib_udata *ucore, | ||
3196 | struct ib_udata *uhw) | ||
3197 | { | ||
3198 | struct ib_uverbs_ex_destroy_wq cmd = {}; | ||
3199 | struct ib_uverbs_ex_destroy_wq_resp resp = {}; | ||
3200 | struct ib_wq *wq; | ||
3201 | struct ib_uobject *uobj; | ||
3202 | struct ib_uwq_object *obj; | ||
3203 | size_t required_cmd_sz; | ||
3204 | size_t required_resp_len; | ||
3205 | int ret; | ||
3206 | |||
3207 | required_cmd_sz = offsetof(typeof(cmd), wq_handle) + sizeof(cmd.wq_handle); | ||
3208 | required_resp_len = offsetof(typeof(resp), reserved) + sizeof(resp.reserved); | ||
3209 | |||
3210 | if (ucore->inlen < required_cmd_sz) | ||
3211 | return -EINVAL; | ||
3212 | |||
3213 | if (ucore->outlen < required_resp_len) | ||
3214 | return -ENOSPC; | ||
3215 | |||
3216 | if (ucore->inlen > sizeof(cmd) && | ||
3217 | !ib_is_udata_cleared(ucore, sizeof(cmd), | ||
3218 | ucore->inlen - sizeof(cmd))) | ||
3219 | return -EOPNOTSUPP; | ||
3220 | |||
3221 | ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen)); | ||
3222 | if (ret) | ||
3223 | return ret; | ||
3224 | |||
3225 | if (cmd.comp_mask) | ||
3226 | return -EOPNOTSUPP; | ||
3227 | |||
3228 | resp.response_length = required_resp_len; | ||
3229 | uobj = idr_write_uobj(&ib_uverbs_wq_idr, cmd.wq_handle, | ||
3230 | file->ucontext); | ||
3231 | if (!uobj) | ||
3232 | return -EINVAL; | ||
3233 | |||
3234 | wq = uobj->object; | ||
3235 | obj = container_of(uobj, struct ib_uwq_object, uevent.uobject); | ||
3236 | ret = ib_destroy_wq(wq); | ||
3237 | if (!ret) | ||
3238 | uobj->live = 0; | ||
3239 | |||
3240 | put_uobj_write(uobj); | ||
3241 | if (ret) | ||
3242 | return ret; | ||
3243 | |||
3244 | idr_remove_uobj(&ib_uverbs_wq_idr, uobj); | ||
3245 | |||
3246 | mutex_lock(&file->mutex); | ||
3247 | list_del(&uobj->list); | ||
3248 | mutex_unlock(&file->mutex); | ||
3249 | |||
3250 | ib_uverbs_release_uevent(file, &obj->uevent); | ||
3251 | resp.events_reported = obj->uevent.events_reported; | ||
3252 | put_uobj(uobj); | ||
3253 | |||
3254 | ret = ib_copy_to_udata(ucore, &resp, resp.response_length); | ||
3255 | if (ret) | ||
3256 | return ret; | ||
3257 | |||
3258 | return 0; | ||
3259 | } | ||
3260 | |||
3261 | int ib_uverbs_ex_modify_wq(struct ib_uverbs_file *file, | ||
3262 | struct ib_device *ib_dev, | ||
3263 | struct ib_udata *ucore, | ||
3264 | struct ib_udata *uhw) | ||
3265 | { | ||
3266 | struct ib_uverbs_ex_modify_wq cmd = {}; | ||
3267 | struct ib_wq *wq; | ||
3268 | struct ib_wq_attr wq_attr = {}; | ||
3269 | size_t required_cmd_sz; | ||
3270 | int ret; | ||
3271 | |||
3272 | required_cmd_sz = offsetof(typeof(cmd), curr_wq_state) + sizeof(cmd.curr_wq_state); | ||
3273 | if (ucore->inlen < required_cmd_sz) | ||
3274 | return -EINVAL; | ||
3275 | |||
3276 | if (ucore->inlen > sizeof(cmd) && | ||
3277 | !ib_is_udata_cleared(ucore, sizeof(cmd), | ||
3278 | ucore->inlen - sizeof(cmd))) | ||
3279 | return -EOPNOTSUPP; | ||
3280 | |||
3281 | ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen)); | ||
3282 | if (ret) | ||
3283 | return ret; | ||
3284 | |||
3285 | if (!cmd.attr_mask) | ||
3286 | return -EINVAL; | ||
3287 | |||
3288 | if (cmd.attr_mask > (IB_WQ_STATE | IB_WQ_CUR_STATE)) | ||
3289 | return -EINVAL; | ||
3290 | |||
3291 | wq = idr_read_wq(cmd.wq_handle, file->ucontext); | ||
3292 | if (!wq) | ||
3293 | return -EINVAL; | ||
3294 | |||
3295 | wq_attr.curr_wq_state = cmd.curr_wq_state; | ||
3296 | wq_attr.wq_state = cmd.wq_state; | ||
3297 | ret = wq->device->modify_wq(wq, &wq_attr, cmd.attr_mask, uhw); | ||
3298 | put_wq_read(wq); | ||
3299 | return ret; | ||
3300 | } | ||
3301 | |||
3059 | int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file, | 3302 | int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file, |
3060 | struct ib_device *ib_dev, | 3303 | struct ib_device *ib_dev, |
3061 | struct ib_udata *ucore, | 3304 | struct ib_udata *ucore, |
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 31f422a70623..91cb36f66ea7 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c | |||
@@ -76,6 +76,7 @@ DEFINE_IDR(ib_uverbs_qp_idr); | |||
76 | DEFINE_IDR(ib_uverbs_srq_idr); | 76 | DEFINE_IDR(ib_uverbs_srq_idr); |
77 | DEFINE_IDR(ib_uverbs_xrcd_idr); | 77 | DEFINE_IDR(ib_uverbs_xrcd_idr); |
78 | DEFINE_IDR(ib_uverbs_rule_idr); | 78 | DEFINE_IDR(ib_uverbs_rule_idr); |
79 | DEFINE_IDR(ib_uverbs_wq_idr); | ||
79 | 80 | ||
80 | static DEFINE_SPINLOCK(map_lock); | 81 | static DEFINE_SPINLOCK(map_lock); |
81 | static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES); | 82 | static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES); |
@@ -130,6 +131,9 @@ static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file, | |||
130 | [IB_USER_VERBS_EX_CMD_QUERY_DEVICE] = ib_uverbs_ex_query_device, | 131 | [IB_USER_VERBS_EX_CMD_QUERY_DEVICE] = ib_uverbs_ex_query_device, |
131 | [IB_USER_VERBS_EX_CMD_CREATE_CQ] = ib_uverbs_ex_create_cq, | 132 | [IB_USER_VERBS_EX_CMD_CREATE_CQ] = ib_uverbs_ex_create_cq, |
132 | [IB_USER_VERBS_EX_CMD_CREATE_QP] = ib_uverbs_ex_create_qp, | 133 | [IB_USER_VERBS_EX_CMD_CREATE_QP] = ib_uverbs_ex_create_qp, |
134 | [IB_USER_VERBS_EX_CMD_CREATE_WQ] = ib_uverbs_ex_create_wq, | ||
135 | [IB_USER_VERBS_EX_CMD_MODIFY_WQ] = ib_uverbs_ex_modify_wq, | ||
136 | [IB_USER_VERBS_EX_CMD_DESTROY_WQ] = ib_uverbs_ex_destroy_wq, | ||
133 | }; | 137 | }; |
134 | 138 | ||
135 | static void ib_uverbs_add_one(struct ib_device *device); | 139 | static void ib_uverbs_add_one(struct ib_device *device); |
@@ -265,6 +269,17 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, | |||
265 | kfree(uqp); | 269 | kfree(uqp); |
266 | } | 270 | } |
267 | 271 | ||
272 | list_for_each_entry_safe(uobj, tmp, &context->wq_list, list) { | ||
273 | struct ib_wq *wq = uobj->object; | ||
274 | struct ib_uwq_object *uwq = | ||
275 | container_of(uobj, struct ib_uwq_object, uevent.uobject); | ||
276 | |||
277 | idr_remove_uobj(&ib_uverbs_wq_idr, uobj); | ||
278 | ib_destroy_wq(wq); | ||
279 | ib_uverbs_release_uevent(file, &uwq->uevent); | ||
280 | kfree(uwq); | ||
281 | } | ||
282 | |||
268 | list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) { | 283 | list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) { |
269 | struct ib_srq *srq = uobj->object; | 284 | struct ib_srq *srq = uobj->object; |
270 | struct ib_uevent_object *uevent = | 285 | struct ib_uevent_object *uevent = |
@@ -568,6 +583,16 @@ void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr) | |||
568 | &uobj->events_reported); | 583 | &uobj->events_reported); |
569 | } | 584 | } |
570 | 585 | ||
586 | void ib_uverbs_wq_event_handler(struct ib_event *event, void *context_ptr) | ||
587 | { | ||
588 | struct ib_uevent_object *uobj = container_of(event->element.wq->uobject, | ||
589 | struct ib_uevent_object, uobject); | ||
590 | |||
591 | ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle, | ||
592 | event->event, &uobj->event_list, | ||
593 | &uobj->events_reported); | ||
594 | } | ||
595 | |||
571 | void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr) | 596 | void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr) |
572 | { | 597 | { |
573 | struct ib_uevent_object *uobj; | 598 | struct ib_uevent_object *uobj; |
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index f2d954ac42f6..0c1956a98573 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h | |||
@@ -562,6 +562,7 @@ enum ib_event_type { | |||
562 | IB_EVENT_QP_LAST_WQE_REACHED, | 562 | IB_EVENT_QP_LAST_WQE_REACHED, |
563 | IB_EVENT_CLIENT_REREGISTER, | 563 | IB_EVENT_CLIENT_REREGISTER, |
564 | IB_EVENT_GID_CHANGE, | 564 | IB_EVENT_GID_CHANGE, |
565 | IB_EVENT_WQ_FATAL, | ||
565 | }; | 566 | }; |
566 | 567 | ||
567 | const char *__attribute_const__ ib_event_msg(enum ib_event_type event); | 568 | const char *__attribute_const__ ib_event_msg(enum ib_event_type event); |
@@ -572,6 +573,7 @@ struct ib_event { | |||
572 | struct ib_cq *cq; | 573 | struct ib_cq *cq; |
573 | struct ib_qp *qp; | 574 | struct ib_qp *qp; |
574 | struct ib_srq *srq; | 575 | struct ib_srq *srq; |
576 | struct ib_wq *wq; | ||
575 | u8 port_num; | 577 | u8 port_num; |
576 | } element; | 578 | } element; |
577 | enum ib_event_type event; | 579 | enum ib_event_type event; |
@@ -1323,6 +1325,7 @@ struct ib_ucontext { | |||
1323 | struct list_head ah_list; | 1325 | struct list_head ah_list; |
1324 | struct list_head xrcd_list; | 1326 | struct list_head xrcd_list; |
1325 | struct list_head rule_list; | 1327 | struct list_head rule_list; |
1328 | struct list_head wq_list; | ||
1326 | int closing; | 1329 | int closing; |
1327 | 1330 | ||
1328 | struct pid *tgid; | 1331 | struct pid *tgid; |
diff --git a/include/uapi/rdma/ib_user_verbs.h b/include/uapi/rdma/ib_user_verbs.h index b6543d73d20a..c9470e511e03 100644 --- a/include/uapi/rdma/ib_user_verbs.h +++ b/include/uapi/rdma/ib_user_verbs.h | |||
@@ -95,6 +95,9 @@ enum { | |||
95 | IB_USER_VERBS_EX_CMD_CREATE_QP = IB_USER_VERBS_CMD_CREATE_QP, | 95 | IB_USER_VERBS_EX_CMD_CREATE_QP = IB_USER_VERBS_CMD_CREATE_QP, |
96 | IB_USER_VERBS_EX_CMD_CREATE_FLOW = IB_USER_VERBS_CMD_THRESHOLD, | 96 | IB_USER_VERBS_EX_CMD_CREATE_FLOW = IB_USER_VERBS_CMD_THRESHOLD, |
97 | IB_USER_VERBS_EX_CMD_DESTROY_FLOW, | 97 | IB_USER_VERBS_EX_CMD_DESTROY_FLOW, |
98 | IB_USER_VERBS_EX_CMD_CREATE_WQ, | ||
99 | IB_USER_VERBS_EX_CMD_MODIFY_WQ, | ||
100 | IB_USER_VERBS_EX_CMD_DESTROY_WQ, | ||
98 | }; | 101 | }; |
99 | 102 | ||
100 | /* | 103 | /* |
@@ -946,4 +949,42 @@ struct ib_uverbs_destroy_srq_resp { | |||
946 | __u32 events_reported; | 949 | __u32 events_reported; |
947 | }; | 950 | }; |
948 | 951 | ||
952 | struct ib_uverbs_ex_create_wq { | ||
953 | __u32 comp_mask; | ||
954 | __u32 wq_type; | ||
955 | __u64 user_handle; | ||
956 | __u32 pd_handle; | ||
957 | __u32 cq_handle; | ||
958 | __u32 max_wr; | ||
959 | __u32 max_sge; | ||
960 | }; | ||
961 | |||
962 | struct ib_uverbs_ex_create_wq_resp { | ||
963 | __u32 comp_mask; | ||
964 | __u32 response_length; | ||
965 | __u32 wq_handle; | ||
966 | __u32 max_wr; | ||
967 | __u32 max_sge; | ||
968 | __u32 wqn; | ||
969 | }; | ||
970 | |||
971 | struct ib_uverbs_ex_destroy_wq { | ||
972 | __u32 comp_mask; | ||
973 | __u32 wq_handle; | ||
974 | }; | ||
975 | |||
976 | struct ib_uverbs_ex_destroy_wq_resp { | ||
977 | __u32 comp_mask; | ||
978 | __u32 response_length; | ||
979 | __u32 events_reported; | ||
980 | __u32 reserved; | ||
981 | }; | ||
982 | |||
983 | struct ib_uverbs_ex_modify_wq { | ||
984 | __u32 attr_mask; | ||
985 | __u32 wq_handle; | ||
986 | __u32 wq_state; | ||
987 | __u32 curr_wq_state; | ||
988 | }; | ||
989 | |||
949 | #endif /* IB_USER_VERBS_H */ | 990 | #endif /* IB_USER_VERBS_H */ |