diff options
author | Sean Hefty <sean.hefty@intel.com> | 2005-08-19 16:46:34 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2005-08-26 23:37:38 -0400 |
commit | b9ef520f9caf20aba8ac7cb2bbba45b52ff19d53 (patch) | |
tree | b5e81a95dc8a9a099b85af13c476bf35d49ba56c /drivers/infiniband/core/ucm.c | |
parent | 4ce059378c04b40c2e9f658b1c6a2e9078b85c7c (diff) |
[PATCH] IB: fix userspace CM deadlock
Fix deadlock condition resulting from trying to destroy a cm_id
from the context of a CM thread. The synchronization around the
ucm context structure is simplified as a result, and some simple
code cleanup is included.
Signed-off-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/core/ucm.c')
-rw-r--r-- | drivers/infiniband/core/ucm.c | 464 |
1 files changed, 157 insertions, 307 deletions
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index 61d07c732f49..79595826ccc7 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005 Topspin Communications. All rights reserved. | 2 | * Copyright (c) 2005 Topspin Communications. All rights reserved. |
3 | * Copyright (c) 2005 Intel Corporation. All rights reserved. | ||
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 6 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -73,14 +74,18 @@ static struct semaphore ctx_id_mutex; | |||
73 | static struct idr ctx_id_table; | 74 | static struct idr ctx_id_table; |
74 | static int ctx_id_rover = 0; | 75 | static int ctx_id_rover = 0; |
75 | 76 | ||
76 | static struct ib_ucm_context *ib_ucm_ctx_get(int id) | 77 | static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id) |
77 | { | 78 | { |
78 | struct ib_ucm_context *ctx; | 79 | struct ib_ucm_context *ctx; |
79 | 80 | ||
80 | down(&ctx_id_mutex); | 81 | down(&ctx_id_mutex); |
81 | ctx = idr_find(&ctx_id_table, id); | 82 | ctx = idr_find(&ctx_id_table, id); |
82 | if (ctx) | 83 | if (!ctx) |
83 | ctx->ref++; | 84 | ctx = ERR_PTR(-ENOENT); |
85 | else if (ctx->file != file) | ||
86 | ctx = ERR_PTR(-EINVAL); | ||
87 | else | ||
88 | atomic_inc(&ctx->ref); | ||
84 | up(&ctx_id_mutex); | 89 | up(&ctx_id_mutex); |
85 | 90 | ||
86 | return ctx; | 91 | return ctx; |
@@ -88,21 +93,37 @@ static struct ib_ucm_context *ib_ucm_ctx_get(int id) | |||
88 | 93 | ||
89 | static void ib_ucm_ctx_put(struct ib_ucm_context *ctx) | 94 | static void ib_ucm_ctx_put(struct ib_ucm_context *ctx) |
90 | { | 95 | { |
96 | if (atomic_dec_and_test(&ctx->ref)) | ||
97 | wake_up(&ctx->wait); | ||
98 | } | ||
99 | |||
100 | static ssize_t ib_ucm_destroy_ctx(struct ib_ucm_file *file, int id) | ||
101 | { | ||
102 | struct ib_ucm_context *ctx; | ||
91 | struct ib_ucm_event *uevent; | 103 | struct ib_ucm_event *uevent; |
92 | 104 | ||
93 | down(&ctx_id_mutex); | 105 | down(&ctx_id_mutex); |
94 | 106 | ctx = idr_find(&ctx_id_table, id); | |
95 | ctx->ref--; | 107 | if (!ctx) |
96 | if (!ctx->ref) | 108 | ctx = ERR_PTR(-ENOENT); |
109 | else if (ctx->file != file) | ||
110 | ctx = ERR_PTR(-EINVAL); | ||
111 | else | ||
97 | idr_remove(&ctx_id_table, ctx->id); | 112 | idr_remove(&ctx_id_table, ctx->id); |
98 | |||
99 | up(&ctx_id_mutex); | 113 | up(&ctx_id_mutex); |
100 | 114 | ||
101 | if (ctx->ref) | 115 | if (IS_ERR(ctx)) |
102 | return; | 116 | return PTR_ERR(ctx); |
103 | 117 | ||
104 | down(&ctx->file->mutex); | 118 | atomic_dec(&ctx->ref); |
119 | wait_event(ctx->wait, !atomic_read(&ctx->ref)); | ||
120 | |||
121 | /* No new events will be generated after destroying the cm_id. */ | ||
122 | if (!IS_ERR(ctx->cm_id)) | ||
123 | ib_destroy_cm_id(ctx->cm_id); | ||
105 | 124 | ||
125 | /* Cleanup events not yet reported to the user. */ | ||
126 | down(&file->mutex); | ||
106 | list_del(&ctx->file_list); | 127 | list_del(&ctx->file_list); |
107 | while (!list_empty(&ctx->events)) { | 128 | while (!list_empty(&ctx->events)) { |
108 | 129 | ||
@@ -117,13 +138,10 @@ static void ib_ucm_ctx_put(struct ib_ucm_context *ctx) | |||
117 | 138 | ||
118 | kfree(uevent); | 139 | kfree(uevent); |
119 | } | 140 | } |
141 | up(&file->mutex); | ||
120 | 142 | ||
121 | up(&ctx->file->mutex); | ||
122 | |||
123 | ucm_dbg("Destroyed CM ID <%d>\n", ctx->id); | ||
124 | |||
125 | ib_destroy_cm_id(ctx->cm_id); | ||
126 | kfree(ctx); | 143 | kfree(ctx); |
144 | return 0; | ||
127 | } | 145 | } |
128 | 146 | ||
129 | static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file) | 147 | static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file) |
@@ -135,11 +153,11 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file) | |||
135 | if (!ctx) | 153 | if (!ctx) |
136 | return NULL; | 154 | return NULL; |
137 | 155 | ||
138 | ctx->ref = 1; /* user reference */ | 156 | atomic_set(&ctx->ref, 1); |
157 | init_waitqueue_head(&ctx->wait); | ||
139 | ctx->file = file; | 158 | ctx->file = file; |
140 | 159 | ||
141 | INIT_LIST_HEAD(&ctx->events); | 160 | INIT_LIST_HEAD(&ctx->events); |
142 | init_MUTEX(&ctx->mutex); | ||
143 | 161 | ||
144 | list_add_tail(&ctx->file_list, &file->ctxs); | 162 | list_add_tail(&ctx->file_list, &file->ctxs); |
145 | 163 | ||
@@ -177,8 +195,8 @@ static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath, | |||
177 | if (!kpath || !upath) | 195 | if (!kpath || !upath) |
178 | return; | 196 | return; |
179 | 197 | ||
180 | memcpy(upath->dgid, kpath->dgid.raw, sizeof(union ib_gid)); | 198 | memcpy(upath->dgid, kpath->dgid.raw, sizeof *upath->dgid); |
181 | memcpy(upath->sgid, kpath->sgid.raw, sizeof(union ib_gid)); | 199 | memcpy(upath->sgid, kpath->sgid.raw, sizeof *upath->sgid); |
182 | 200 | ||
183 | upath->dlid = kpath->dlid; | 201 | upath->dlid = kpath->dlid; |
184 | upath->slid = kpath->slid; | 202 | upath->slid = kpath->slid; |
@@ -201,10 +219,11 @@ static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath, | |||
201 | kpath->packet_life_time_selector; | 219 | kpath->packet_life_time_selector; |
202 | } | 220 | } |
203 | 221 | ||
204 | static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq, | 222 | static void ib_ucm_event_req_get(struct ib_ucm_context *ctx, |
223 | struct ib_ucm_req_event_resp *ureq, | ||
205 | struct ib_cm_req_event_param *kreq) | 224 | struct ib_cm_req_event_param *kreq) |
206 | { | 225 | { |
207 | ureq->listen_id = (long)kreq->listen_id->context; | 226 | ureq->listen_id = ctx->id; |
208 | 227 | ||
209 | ureq->remote_ca_guid = kreq->remote_ca_guid; | 228 | ureq->remote_ca_guid = kreq->remote_ca_guid; |
210 | ureq->remote_qkey = kreq->remote_qkey; | 229 | ureq->remote_qkey = kreq->remote_qkey; |
@@ -240,34 +259,11 @@ static void ib_ucm_event_rep_get(struct ib_ucm_rep_event_resp *urep, | |||
240 | urep->srq = krep->srq; | 259 | urep->srq = krep->srq; |
241 | } | 260 | } |
242 | 261 | ||
243 | static void ib_ucm_event_rej_get(struct ib_ucm_rej_event_resp *urej, | 262 | static void ib_ucm_event_sidr_req_get(struct ib_ucm_context *ctx, |
244 | struct ib_cm_rej_event_param *krej) | 263 | struct ib_ucm_sidr_req_event_resp *ureq, |
245 | { | ||
246 | urej->reason = krej->reason; | ||
247 | } | ||
248 | |||
249 | static void ib_ucm_event_mra_get(struct ib_ucm_mra_event_resp *umra, | ||
250 | struct ib_cm_mra_event_param *kmra) | ||
251 | { | ||
252 | umra->timeout = kmra->service_timeout; | ||
253 | } | ||
254 | |||
255 | static void ib_ucm_event_lap_get(struct ib_ucm_lap_event_resp *ulap, | ||
256 | struct ib_cm_lap_event_param *klap) | ||
257 | { | ||
258 | ib_ucm_event_path_get(&ulap->path, klap->alternate_path); | ||
259 | } | ||
260 | |||
261 | static void ib_ucm_event_apr_get(struct ib_ucm_apr_event_resp *uapr, | ||
262 | struct ib_cm_apr_event_param *kapr) | ||
263 | { | ||
264 | uapr->status = kapr->ap_status; | ||
265 | } | ||
266 | |||
267 | static void ib_ucm_event_sidr_req_get(struct ib_ucm_sidr_req_event_resp *ureq, | ||
268 | struct ib_cm_sidr_req_event_param *kreq) | 264 | struct ib_cm_sidr_req_event_param *kreq) |
269 | { | 265 | { |
270 | ureq->listen_id = (long)kreq->listen_id->context; | 266 | ureq->listen_id = ctx->id; |
271 | ureq->pkey = kreq->pkey; | 267 | ureq->pkey = kreq->pkey; |
272 | } | 268 | } |
273 | 269 | ||
@@ -279,19 +275,18 @@ static void ib_ucm_event_sidr_rep_get(struct ib_ucm_sidr_rep_event_resp *urep, | |||
279 | urep->qpn = krep->qpn; | 275 | urep->qpn = krep->qpn; |
280 | }; | 276 | }; |
281 | 277 | ||
282 | static int ib_ucm_event_process(struct ib_cm_event *evt, | 278 | static int ib_ucm_event_process(struct ib_ucm_context *ctx, |
279 | struct ib_cm_event *evt, | ||
283 | struct ib_ucm_event *uvt) | 280 | struct ib_ucm_event *uvt) |
284 | { | 281 | { |
285 | void *info = NULL; | 282 | void *info = NULL; |
286 | int result; | ||
287 | 283 | ||
288 | switch (evt->event) { | 284 | switch (evt->event) { |
289 | case IB_CM_REQ_RECEIVED: | 285 | case IB_CM_REQ_RECEIVED: |
290 | ib_ucm_event_req_get(&uvt->resp.u.req_resp, | 286 | ib_ucm_event_req_get(ctx, &uvt->resp.u.req_resp, |
291 | &evt->param.req_rcvd); | 287 | &evt->param.req_rcvd); |
292 | uvt->data_len = IB_CM_REQ_PRIVATE_DATA_SIZE; | 288 | uvt->data_len = IB_CM_REQ_PRIVATE_DATA_SIZE; |
293 | uvt->resp.present |= (evt->param.req_rcvd.primary_path ? | 289 | uvt->resp.present = IB_UCM_PRES_PRIMARY; |
294 | IB_UCM_PRES_PRIMARY : 0); | ||
295 | uvt->resp.present |= (evt->param.req_rcvd.alternate_path ? | 290 | uvt->resp.present |= (evt->param.req_rcvd.alternate_path ? |
296 | IB_UCM_PRES_ALTERNATE : 0); | 291 | IB_UCM_PRES_ALTERNATE : 0); |
297 | break; | 292 | break; |
@@ -299,57 +294,46 @@ static int ib_ucm_event_process(struct ib_cm_event *evt, | |||
299 | ib_ucm_event_rep_get(&uvt->resp.u.rep_resp, | 294 | ib_ucm_event_rep_get(&uvt->resp.u.rep_resp, |
300 | &evt->param.rep_rcvd); | 295 | &evt->param.rep_rcvd); |
301 | uvt->data_len = IB_CM_REP_PRIVATE_DATA_SIZE; | 296 | uvt->data_len = IB_CM_REP_PRIVATE_DATA_SIZE; |
302 | |||
303 | break; | 297 | break; |
304 | case IB_CM_RTU_RECEIVED: | 298 | case IB_CM_RTU_RECEIVED: |
305 | uvt->data_len = IB_CM_RTU_PRIVATE_DATA_SIZE; | 299 | uvt->data_len = IB_CM_RTU_PRIVATE_DATA_SIZE; |
306 | uvt->resp.u.send_status = evt->param.send_status; | 300 | uvt->resp.u.send_status = evt->param.send_status; |
307 | |||
308 | break; | 301 | break; |
309 | case IB_CM_DREQ_RECEIVED: | 302 | case IB_CM_DREQ_RECEIVED: |
310 | uvt->data_len = IB_CM_DREQ_PRIVATE_DATA_SIZE; | 303 | uvt->data_len = IB_CM_DREQ_PRIVATE_DATA_SIZE; |
311 | uvt->resp.u.send_status = evt->param.send_status; | 304 | uvt->resp.u.send_status = evt->param.send_status; |
312 | |||
313 | break; | 305 | break; |
314 | case IB_CM_DREP_RECEIVED: | 306 | case IB_CM_DREP_RECEIVED: |
315 | uvt->data_len = IB_CM_DREP_PRIVATE_DATA_SIZE; | 307 | uvt->data_len = IB_CM_DREP_PRIVATE_DATA_SIZE; |
316 | uvt->resp.u.send_status = evt->param.send_status; | 308 | uvt->resp.u.send_status = evt->param.send_status; |
317 | |||
318 | break; | 309 | break; |
319 | case IB_CM_MRA_RECEIVED: | 310 | case IB_CM_MRA_RECEIVED: |
320 | ib_ucm_event_mra_get(&uvt->resp.u.mra_resp, | 311 | uvt->resp.u.mra_resp.timeout = |
321 | &evt->param.mra_rcvd); | 312 | evt->param.mra_rcvd.service_timeout; |
322 | uvt->data_len = IB_CM_MRA_PRIVATE_DATA_SIZE; | 313 | uvt->data_len = IB_CM_MRA_PRIVATE_DATA_SIZE; |
323 | |||
324 | break; | 314 | break; |
325 | case IB_CM_REJ_RECEIVED: | 315 | case IB_CM_REJ_RECEIVED: |
326 | ib_ucm_event_rej_get(&uvt->resp.u.rej_resp, | 316 | uvt->resp.u.rej_resp.reason = evt->param.rej_rcvd.reason; |
327 | &evt->param.rej_rcvd); | ||
328 | uvt->data_len = IB_CM_REJ_PRIVATE_DATA_SIZE; | 317 | uvt->data_len = IB_CM_REJ_PRIVATE_DATA_SIZE; |
329 | uvt->info_len = evt->param.rej_rcvd.ari_length; | 318 | uvt->info_len = evt->param.rej_rcvd.ari_length; |
330 | info = evt->param.rej_rcvd.ari; | 319 | info = evt->param.rej_rcvd.ari; |
331 | |||
332 | break; | 320 | break; |
333 | case IB_CM_LAP_RECEIVED: | 321 | case IB_CM_LAP_RECEIVED: |
334 | ib_ucm_event_lap_get(&uvt->resp.u.lap_resp, | 322 | ib_ucm_event_path_get(&uvt->resp.u.lap_resp.path, |
335 | &evt->param.lap_rcvd); | 323 | evt->param.lap_rcvd.alternate_path); |
336 | uvt->data_len = IB_CM_LAP_PRIVATE_DATA_SIZE; | 324 | uvt->data_len = IB_CM_LAP_PRIVATE_DATA_SIZE; |
337 | uvt->resp.present |= (evt->param.lap_rcvd.alternate_path ? | 325 | uvt->resp.present = IB_UCM_PRES_ALTERNATE; |
338 | IB_UCM_PRES_ALTERNATE : 0); | ||
339 | break; | 326 | break; |
340 | case IB_CM_APR_RECEIVED: | 327 | case IB_CM_APR_RECEIVED: |
341 | ib_ucm_event_apr_get(&uvt->resp.u.apr_resp, | 328 | uvt->resp.u.apr_resp.status = evt->param.apr_rcvd.ap_status; |
342 | &evt->param.apr_rcvd); | ||
343 | uvt->data_len = IB_CM_APR_PRIVATE_DATA_SIZE; | 329 | uvt->data_len = IB_CM_APR_PRIVATE_DATA_SIZE; |
344 | uvt->info_len = evt->param.apr_rcvd.info_len; | 330 | uvt->info_len = evt->param.apr_rcvd.info_len; |
345 | info = evt->param.apr_rcvd.apr_info; | 331 | info = evt->param.apr_rcvd.apr_info; |
346 | |||
347 | break; | 332 | break; |
348 | case IB_CM_SIDR_REQ_RECEIVED: | 333 | case IB_CM_SIDR_REQ_RECEIVED: |
349 | ib_ucm_event_sidr_req_get(&uvt->resp.u.sidr_req_resp, | 334 | ib_ucm_event_sidr_req_get(ctx, &uvt->resp.u.sidr_req_resp, |
350 | &evt->param.sidr_req_rcvd); | 335 | &evt->param.sidr_req_rcvd); |
351 | uvt->data_len = IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE; | 336 | uvt->data_len = IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE; |
352 | |||
353 | break; | 337 | break; |
354 | case IB_CM_SIDR_REP_RECEIVED: | 338 | case IB_CM_SIDR_REP_RECEIVED: |
355 | ib_ucm_event_sidr_rep_get(&uvt->resp.u.sidr_rep_resp, | 339 | ib_ucm_event_sidr_rep_get(&uvt->resp.u.sidr_rep_resp, |
@@ -357,43 +341,35 @@ static int ib_ucm_event_process(struct ib_cm_event *evt, | |||
357 | uvt->data_len = IB_CM_SIDR_REP_PRIVATE_DATA_SIZE; | 341 | uvt->data_len = IB_CM_SIDR_REP_PRIVATE_DATA_SIZE; |
358 | uvt->info_len = evt->param.sidr_rep_rcvd.info_len; | 342 | uvt->info_len = evt->param.sidr_rep_rcvd.info_len; |
359 | info = evt->param.sidr_rep_rcvd.info; | 343 | info = evt->param.sidr_rep_rcvd.info; |
360 | |||
361 | break; | 344 | break; |
362 | default: | 345 | default: |
363 | uvt->resp.u.send_status = evt->param.send_status; | 346 | uvt->resp.u.send_status = evt->param.send_status; |
364 | |||
365 | break; | 347 | break; |
366 | } | 348 | } |
367 | 349 | ||
368 | if (uvt->data_len && evt->private_data) { | 350 | if (uvt->data_len) { |
369 | |||
370 | uvt->data = kmalloc(uvt->data_len, GFP_KERNEL); | 351 | uvt->data = kmalloc(uvt->data_len, GFP_KERNEL); |
371 | if (!uvt->data) { | 352 | if (!uvt->data) |
372 | result = -ENOMEM; | 353 | goto err1; |
373 | goto error; | ||
374 | } | ||
375 | 354 | ||
376 | memcpy(uvt->data, evt->private_data, uvt->data_len); | 355 | memcpy(uvt->data, evt->private_data, uvt->data_len); |
377 | uvt->resp.present |= IB_UCM_PRES_DATA; | 356 | uvt->resp.present |= IB_UCM_PRES_DATA; |
378 | } | 357 | } |
379 | 358 | ||
380 | if (uvt->info_len && info) { | 359 | if (uvt->info_len) { |
381 | |||
382 | uvt->info = kmalloc(uvt->info_len, GFP_KERNEL); | 360 | uvt->info = kmalloc(uvt->info_len, GFP_KERNEL); |
383 | if (!uvt->info) { | 361 | if (!uvt->info) |
384 | result = -ENOMEM; | 362 | goto err2; |
385 | goto error; | ||
386 | } | ||
387 | 363 | ||
388 | memcpy(uvt->info, info, uvt->info_len); | 364 | memcpy(uvt->info, info, uvt->info_len); |
389 | uvt->resp.present |= IB_UCM_PRES_INFO; | 365 | uvt->resp.present |= IB_UCM_PRES_INFO; |
390 | } | 366 | } |
391 | |||
392 | return 0; | 367 | return 0; |
393 | error: | 368 | |
394 | kfree(uvt->info); | 369 | err2: |
395 | kfree(uvt->data); | 370 | kfree(uvt->data); |
396 | return result; | 371 | err1: |
372 | return -ENOMEM; | ||
397 | } | 373 | } |
398 | 374 | ||
399 | static int ib_ucm_event_handler(struct ib_cm_id *cm_id, | 375 | static int ib_ucm_event_handler(struct ib_cm_id *cm_id, |
@@ -403,63 +379,42 @@ static int ib_ucm_event_handler(struct ib_cm_id *cm_id, | |||
403 | struct ib_ucm_context *ctx; | 379 | struct ib_ucm_context *ctx; |
404 | int result = 0; | 380 | int result = 0; |
405 | int id; | 381 | int id; |
406 | /* | ||
407 | * lookup correct context based on event type. | ||
408 | */ | ||
409 | switch (event->event) { | ||
410 | case IB_CM_REQ_RECEIVED: | ||
411 | id = (long)event->param.req_rcvd.listen_id->context; | ||
412 | break; | ||
413 | case IB_CM_SIDR_REQ_RECEIVED: | ||
414 | id = (long)event->param.sidr_req_rcvd.listen_id->context; | ||
415 | break; | ||
416 | default: | ||
417 | id = (long)cm_id->context; | ||
418 | break; | ||
419 | } | ||
420 | 382 | ||
421 | ucm_dbg("Event. CM ID <%d> event <%d>\n", id, event->event); | 383 | ctx = cm_id->context; |
422 | |||
423 | ctx = ib_ucm_ctx_get(id); | ||
424 | if (!ctx) | ||
425 | return -ENOENT; | ||
426 | 384 | ||
427 | if (event->event == IB_CM_REQ_RECEIVED || | 385 | if (event->event == IB_CM_REQ_RECEIVED || |
428 | event->event == IB_CM_SIDR_REQ_RECEIVED) | 386 | event->event == IB_CM_SIDR_REQ_RECEIVED) |
429 | id = IB_UCM_CM_ID_INVALID; | 387 | id = IB_UCM_CM_ID_INVALID; |
388 | else | ||
389 | id = ctx->id; | ||
430 | 390 | ||
431 | uevent = kmalloc(sizeof(*uevent), GFP_KERNEL); | 391 | uevent = kmalloc(sizeof(*uevent), GFP_KERNEL); |
432 | if (!uevent) { | 392 | if (!uevent) |
433 | result = -ENOMEM; | 393 | goto err1; |
434 | goto done; | ||
435 | } | ||
436 | 394 | ||
437 | memset(uevent, 0, sizeof(*uevent)); | 395 | memset(uevent, 0, sizeof(*uevent)); |
438 | |||
439 | uevent->resp.id = id; | 396 | uevent->resp.id = id; |
440 | uevent->resp.event = event->event; | 397 | uevent->resp.event = event->event; |
441 | 398 | ||
442 | result = ib_ucm_event_process(event, uevent); | 399 | result = ib_ucm_event_process(ctx, event, uevent); |
443 | if (result) | 400 | if (result) |
444 | goto done; | 401 | goto err2; |
445 | 402 | ||
446 | uevent->ctx = ctx; | 403 | uevent->ctx = ctx; |
447 | uevent->cm_id = ((event->event == IB_CM_REQ_RECEIVED || | 404 | uevent->cm_id = (id == IB_UCM_CM_ID_INVALID) ? cm_id : NULL; |
448 | event->event == IB_CM_SIDR_REQ_RECEIVED ) ? | ||
449 | cm_id : NULL); | ||
450 | 405 | ||
451 | down(&ctx->file->mutex); | 406 | down(&ctx->file->mutex); |
452 | |||
453 | list_add_tail(&uevent->file_list, &ctx->file->events); | 407 | list_add_tail(&uevent->file_list, &ctx->file->events); |
454 | list_add_tail(&uevent->ctx_list, &ctx->events); | 408 | list_add_tail(&uevent->ctx_list, &ctx->events); |
455 | |||
456 | wake_up_interruptible(&ctx->file->poll_wait); | 409 | wake_up_interruptible(&ctx->file->poll_wait); |
457 | |||
458 | up(&ctx->file->mutex); | 410 | up(&ctx->file->mutex); |
459 | done: | 411 | return 0; |
460 | ctx->error = result; | 412 | |
461 | ib_ucm_ctx_put(ctx); /* func reference */ | 413 | err2: |
462 | return result; | 414 | kfree(uevent); |
415 | err1: | ||
416 | /* Destroy new cm_id's */ | ||
417 | return (id == IB_UCM_CM_ID_INVALID); | ||
463 | } | 418 | } |
464 | 419 | ||
465 | static ssize_t ib_ucm_event(struct ib_ucm_file *file, | 420 | static ssize_t ib_ucm_event(struct ib_ucm_file *file, |
@@ -517,9 +472,8 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file, | |||
517 | goto done; | 472 | goto done; |
518 | } | 473 | } |
519 | 474 | ||
520 | ctx->cm_id = uevent->cm_id; | 475 | ctx->cm_id = uevent->cm_id; |
521 | ctx->cm_id->cm_handler = ib_ucm_event_handler; | 476 | ctx->cm_id->context = ctx; |
522 | ctx->cm_id->context = (void *)(unsigned long)ctx->id; | ||
523 | 477 | ||
524 | uevent->resp.id = ctx->id; | 478 | uevent->resp.id = ctx->id; |
525 | 479 | ||
@@ -585,30 +539,29 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file, | |||
585 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) | 539 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) |
586 | return -EFAULT; | 540 | return -EFAULT; |
587 | 541 | ||
542 | down(&file->mutex); | ||
588 | ctx = ib_ucm_ctx_alloc(file); | 543 | ctx = ib_ucm_ctx_alloc(file); |
544 | up(&file->mutex); | ||
589 | if (!ctx) | 545 | if (!ctx) |
590 | return -ENOMEM; | 546 | return -ENOMEM; |
591 | 547 | ||
592 | ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler, | 548 | ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler, ctx); |
593 | (void *)(unsigned long)ctx->id); | 549 | if (IS_ERR(ctx->cm_id)) { |
594 | if (!ctx->cm_id) { | 550 | result = PTR_ERR(ctx->cm_id); |
595 | result = -ENOMEM; | 551 | goto err; |
596 | goto err_cm; | ||
597 | } | 552 | } |
598 | 553 | ||
599 | resp.id = ctx->id; | 554 | resp.id = ctx->id; |
600 | if (copy_to_user((void __user *)(unsigned long)cmd.response, | 555 | if (copy_to_user((void __user *)(unsigned long)cmd.response, |
601 | &resp, sizeof(resp))) { | 556 | &resp, sizeof(resp))) { |
602 | result = -EFAULT; | 557 | result = -EFAULT; |
603 | goto err_ret; | 558 | goto err; |
604 | } | 559 | } |
605 | 560 | ||
606 | return 0; | 561 | return 0; |
607 | err_ret: | ||
608 | ib_destroy_cm_id(ctx->cm_id); | ||
609 | err_cm: | ||
610 | ib_ucm_ctx_put(ctx); /* user reference */ | ||
611 | 562 | ||
563 | err: | ||
564 | ib_ucm_destroy_ctx(file, ctx->id); | ||
612 | return result; | 565 | return result; |
613 | } | 566 | } |
614 | 567 | ||
@@ -617,19 +570,11 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file, | |||
617 | int in_len, int out_len) | 570 | int in_len, int out_len) |
618 | { | 571 | { |
619 | struct ib_ucm_destroy_id cmd; | 572 | struct ib_ucm_destroy_id cmd; |
620 | struct ib_ucm_context *ctx; | ||
621 | 573 | ||
622 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) | 574 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) |
623 | return -EFAULT; | 575 | return -EFAULT; |
624 | 576 | ||
625 | ctx = ib_ucm_ctx_get(cmd.id); | 577 | return ib_ucm_destroy_ctx(file, cmd.id); |
626 | if (!ctx) | ||
627 | return -ENOENT; | ||
628 | |||
629 | ib_ucm_ctx_put(ctx); /* user reference */ | ||
630 | ib_ucm_ctx_put(ctx); /* func reference */ | ||
631 | |||
632 | return 0; | ||
633 | } | 578 | } |
634 | 579 | ||
635 | static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file, | 580 | static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file, |
@@ -647,15 +592,9 @@ static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file, | |||
647 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) | 592 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) |
648 | return -EFAULT; | 593 | return -EFAULT; |
649 | 594 | ||
650 | ctx = ib_ucm_ctx_get(cmd.id); | 595 | ctx = ib_ucm_ctx_get(file, cmd.id); |
651 | if (!ctx) | 596 | if (IS_ERR(ctx)) |
652 | return -ENOENT; | 597 | return PTR_ERR(ctx); |
653 | |||
654 | down(&ctx->file->mutex); | ||
655 | if (ctx->file != file) { | ||
656 | result = -EINVAL; | ||
657 | goto done; | ||
658 | } | ||
659 | 598 | ||
660 | resp.service_id = ctx->cm_id->service_id; | 599 | resp.service_id = ctx->cm_id->service_id; |
661 | resp.service_mask = ctx->cm_id->service_mask; | 600 | resp.service_mask = ctx->cm_id->service_mask; |
@@ -666,9 +605,7 @@ static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file, | |||
666 | &resp, sizeof(resp))) | 605 | &resp, sizeof(resp))) |
667 | result = -EFAULT; | 606 | result = -EFAULT; |
668 | 607 | ||
669 | done: | 608 | ib_ucm_ctx_put(ctx); |
670 | up(&ctx->file->mutex); | ||
671 | ib_ucm_ctx_put(ctx); /* func reference */ | ||
672 | return result; | 609 | return result; |
673 | } | 610 | } |
674 | 611 | ||
@@ -683,19 +620,12 @@ static ssize_t ib_ucm_listen(struct ib_ucm_file *file, | |||
683 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) | 620 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) |
684 | return -EFAULT; | 621 | return -EFAULT; |
685 | 622 | ||
686 | ctx = ib_ucm_ctx_get(cmd.id); | 623 | ctx = ib_ucm_ctx_get(file, cmd.id); |
687 | if (!ctx) | 624 | if (IS_ERR(ctx)) |
688 | return -ENOENT; | 625 | return PTR_ERR(ctx); |
689 | 626 | ||
690 | down(&ctx->file->mutex); | 627 | result = ib_cm_listen(ctx->cm_id, cmd.service_id, cmd.service_mask); |
691 | if (ctx->file != file) | 628 | ib_ucm_ctx_put(ctx); |
692 | result = -EINVAL; | ||
693 | else | ||
694 | result = ib_cm_listen(ctx->cm_id, cmd.service_id, | ||
695 | cmd.service_mask); | ||
696 | |||
697 | up(&ctx->file->mutex); | ||
698 | ib_ucm_ctx_put(ctx); /* func reference */ | ||
699 | return result; | 629 | return result; |
700 | } | 630 | } |
701 | 631 | ||
@@ -710,18 +640,12 @@ static ssize_t ib_ucm_establish(struct ib_ucm_file *file, | |||
710 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) | 640 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) |
711 | return -EFAULT; | 641 | return -EFAULT; |
712 | 642 | ||
713 | ctx = ib_ucm_ctx_get(cmd.id); | 643 | ctx = ib_ucm_ctx_get(file, cmd.id); |
714 | if (!ctx) | 644 | if (IS_ERR(ctx)) |
715 | return -ENOENT; | 645 | return PTR_ERR(ctx); |
716 | |||
717 | down(&ctx->file->mutex); | ||
718 | if (ctx->file != file) | ||
719 | result = -EINVAL; | ||
720 | else | ||
721 | result = ib_cm_establish(ctx->cm_id); | ||
722 | 646 | ||
723 | up(&ctx->file->mutex); | 647 | result = ib_cm_establish(ctx->cm_id); |
724 | ib_ucm_ctx_put(ctx); /* func reference */ | 648 | ib_ucm_ctx_put(ctx); |
725 | return result; | 649 | return result; |
726 | } | 650 | } |
727 | 651 | ||
@@ -768,8 +692,8 @@ static int ib_ucm_path_get(struct ib_sa_path_rec **path, u64 src) | |||
768 | return -EFAULT; | 692 | return -EFAULT; |
769 | } | 693 | } |
770 | 694 | ||
771 | memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof(union ib_gid)); | 695 | memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof sa_path->dgid); |
772 | memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof(union ib_gid)); | 696 | memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof sa_path->sgid); |
773 | 697 | ||
774 | sa_path->dlid = ucm_path.dlid; | 698 | sa_path->dlid = ucm_path.dlid; |
775 | sa_path->slid = ucm_path.slid; | 699 | sa_path->slid = ucm_path.slid; |
@@ -839,25 +763,17 @@ static ssize_t ib_ucm_send_req(struct ib_ucm_file *file, | |||
839 | param.max_cm_retries = cmd.max_cm_retries; | 763 | param.max_cm_retries = cmd.max_cm_retries; |
840 | param.srq = cmd.srq; | 764 | param.srq = cmd.srq; |
841 | 765 | ||
842 | ctx = ib_ucm_ctx_get(cmd.id); | 766 | ctx = ib_ucm_ctx_get(file, cmd.id); |
843 | if (!ctx) { | 767 | if (!IS_ERR(ctx)) { |
844 | result = -ENOENT; | ||
845 | goto done; | ||
846 | } | ||
847 | |||
848 | down(&ctx->file->mutex); | ||
849 | if (ctx->file != file) | ||
850 | result = -EINVAL; | ||
851 | else | ||
852 | result = ib_send_cm_req(ctx->cm_id, ¶m); | 768 | result = ib_send_cm_req(ctx->cm_id, ¶m); |
769 | ib_ucm_ctx_put(ctx); | ||
770 | } else | ||
771 | result = PTR_ERR(ctx); | ||
853 | 772 | ||
854 | up(&ctx->file->mutex); | ||
855 | ib_ucm_ctx_put(ctx); /* func reference */ | ||
856 | done: | 773 | done: |
857 | kfree(param.private_data); | 774 | kfree(param.private_data); |
858 | kfree(param.primary_path); | 775 | kfree(param.primary_path); |
859 | kfree(param.alternate_path); | 776 | kfree(param.alternate_path); |
860 | |||
861 | return result; | 777 | return result; |
862 | } | 778 | } |
863 | 779 | ||
@@ -890,23 +806,14 @@ static ssize_t ib_ucm_send_rep(struct ib_ucm_file *file, | |||
890 | param.rnr_retry_count = cmd.rnr_retry_count; | 806 | param.rnr_retry_count = cmd.rnr_retry_count; |
891 | param.srq = cmd.srq; | 807 | param.srq = cmd.srq; |
892 | 808 | ||
893 | ctx = ib_ucm_ctx_get(cmd.id); | 809 | ctx = ib_ucm_ctx_get(file, cmd.id); |
894 | if (!ctx) { | 810 | if (!IS_ERR(ctx)) { |
895 | result = -ENOENT; | ||
896 | goto done; | ||
897 | } | ||
898 | |||
899 | down(&ctx->file->mutex); | ||
900 | if (ctx->file != file) | ||
901 | result = -EINVAL; | ||
902 | else | ||
903 | result = ib_send_cm_rep(ctx->cm_id, ¶m); | 811 | result = ib_send_cm_rep(ctx->cm_id, ¶m); |
812 | ib_ucm_ctx_put(ctx); | ||
813 | } else | ||
814 | result = PTR_ERR(ctx); | ||
904 | 815 | ||
905 | up(&ctx->file->mutex); | ||
906 | ib_ucm_ctx_put(ctx); /* func reference */ | ||
907 | done: | ||
908 | kfree(param.private_data); | 816 | kfree(param.private_data); |
909 | |||
910 | return result; | 817 | return result; |
911 | } | 818 | } |
912 | 819 | ||
@@ -928,23 +835,14 @@ static ssize_t ib_ucm_send_private_data(struct ib_ucm_file *file, | |||
928 | if (result) | 835 | if (result) |
929 | return result; | 836 | return result; |
930 | 837 | ||
931 | ctx = ib_ucm_ctx_get(cmd.id); | 838 | ctx = ib_ucm_ctx_get(file, cmd.id); |
932 | if (!ctx) { | 839 | if (!IS_ERR(ctx)) { |
933 | result = -ENOENT; | ||
934 | goto done; | ||
935 | } | ||
936 | |||
937 | down(&ctx->file->mutex); | ||
938 | if (ctx->file != file) | ||
939 | result = -EINVAL; | ||
940 | else | ||
941 | result = func(ctx->cm_id, private_data, cmd.len); | 840 | result = func(ctx->cm_id, private_data, cmd.len); |
841 | ib_ucm_ctx_put(ctx); | ||
842 | } else | ||
843 | result = PTR_ERR(ctx); | ||
942 | 844 | ||
943 | up(&ctx->file->mutex); | ||
944 | ib_ucm_ctx_put(ctx); /* func reference */ | ||
945 | done: | ||
946 | kfree(private_data); | 845 | kfree(private_data); |
947 | |||
948 | return result; | 846 | return result; |
949 | } | 847 | } |
950 | 848 | ||
@@ -995,26 +893,17 @@ static ssize_t ib_ucm_send_info(struct ib_ucm_file *file, | |||
995 | if (result) | 893 | if (result) |
996 | goto done; | 894 | goto done; |
997 | 895 | ||
998 | ctx = ib_ucm_ctx_get(cmd.id); | 896 | ctx = ib_ucm_ctx_get(file, cmd.id); |
999 | if (!ctx) { | 897 | if (!IS_ERR(ctx)) { |
1000 | result = -ENOENT; | 898 | result = func(ctx->cm_id, cmd.status, info, cmd.info_len, |
1001 | goto done; | ||
1002 | } | ||
1003 | |||
1004 | down(&ctx->file->mutex); | ||
1005 | if (ctx->file != file) | ||
1006 | result = -EINVAL; | ||
1007 | else | ||
1008 | result = func(ctx->cm_id, cmd.status, | ||
1009 | info, cmd.info_len, | ||
1010 | data, cmd.data_len); | 899 | data, cmd.data_len); |
900 | ib_ucm_ctx_put(ctx); | ||
901 | } else | ||
902 | result = PTR_ERR(ctx); | ||
1011 | 903 | ||
1012 | up(&ctx->file->mutex); | ||
1013 | ib_ucm_ctx_put(ctx); /* func reference */ | ||
1014 | done: | 904 | done: |
1015 | kfree(data); | 905 | kfree(data); |
1016 | kfree(info); | 906 | kfree(info); |
1017 | |||
1018 | return result; | 907 | return result; |
1019 | } | 908 | } |
1020 | 909 | ||
@@ -1048,24 +937,14 @@ static ssize_t ib_ucm_send_mra(struct ib_ucm_file *file, | |||
1048 | if (result) | 937 | if (result) |
1049 | return result; | 938 | return result; |
1050 | 939 | ||
1051 | ctx = ib_ucm_ctx_get(cmd.id); | 940 | ctx = ib_ucm_ctx_get(file, cmd.id); |
1052 | if (!ctx) { | 941 | if (!IS_ERR(ctx)) { |
1053 | result = -ENOENT; | 942 | result = ib_send_cm_mra(ctx->cm_id, cmd.timeout, data, cmd.len); |
1054 | goto done; | 943 | ib_ucm_ctx_put(ctx); |
1055 | } | 944 | } else |
945 | result = PTR_ERR(ctx); | ||
1056 | 946 | ||
1057 | down(&ctx->file->mutex); | ||
1058 | if (ctx->file != file) | ||
1059 | result = -EINVAL; | ||
1060 | else | ||
1061 | result = ib_send_cm_mra(ctx->cm_id, cmd.timeout, | ||
1062 | data, cmd.len); | ||
1063 | |||
1064 | up(&ctx->file->mutex); | ||
1065 | ib_ucm_ctx_put(ctx); /* func reference */ | ||
1066 | done: | ||
1067 | kfree(data); | 947 | kfree(data); |
1068 | |||
1069 | return result; | 948 | return result; |
1070 | } | 949 | } |
1071 | 950 | ||
@@ -1090,24 +969,16 @@ static ssize_t ib_ucm_send_lap(struct ib_ucm_file *file, | |||
1090 | if (result) | 969 | if (result) |
1091 | goto done; | 970 | goto done; |
1092 | 971 | ||
1093 | ctx = ib_ucm_ctx_get(cmd.id); | 972 | ctx = ib_ucm_ctx_get(file, cmd.id); |
1094 | if (!ctx) { | 973 | if (!IS_ERR(ctx)) { |
1095 | result = -ENOENT; | ||
1096 | goto done; | ||
1097 | } | ||
1098 | |||
1099 | down(&ctx->file->mutex); | ||
1100 | if (ctx->file != file) | ||
1101 | result = -EINVAL; | ||
1102 | else | ||
1103 | result = ib_send_cm_lap(ctx->cm_id, path, data, cmd.len); | 974 | result = ib_send_cm_lap(ctx->cm_id, path, data, cmd.len); |
975 | ib_ucm_ctx_put(ctx); | ||
976 | } else | ||
977 | result = PTR_ERR(ctx); | ||
1104 | 978 | ||
1105 | up(&ctx->file->mutex); | ||
1106 | ib_ucm_ctx_put(ctx); /* func reference */ | ||
1107 | done: | 979 | done: |
1108 | kfree(data); | 980 | kfree(data); |
1109 | kfree(path); | 981 | kfree(path); |
1110 | |||
1111 | return result; | 982 | return result; |
1112 | } | 983 | } |
1113 | 984 | ||
@@ -1140,24 +1011,16 @@ static ssize_t ib_ucm_send_sidr_req(struct ib_ucm_file *file, | |||
1140 | param.max_cm_retries = cmd.max_cm_retries; | 1011 | param.max_cm_retries = cmd.max_cm_retries; |
1141 | param.pkey = cmd.pkey; | 1012 | param.pkey = cmd.pkey; |
1142 | 1013 | ||
1143 | ctx = ib_ucm_ctx_get(cmd.id); | 1014 | ctx = ib_ucm_ctx_get(file, cmd.id); |
1144 | if (!ctx) { | 1015 | if (!IS_ERR(ctx)) { |
1145 | result = -ENOENT; | ||
1146 | goto done; | ||
1147 | } | ||
1148 | |||
1149 | down(&ctx->file->mutex); | ||
1150 | if (ctx->file != file) | ||
1151 | result = -EINVAL; | ||
1152 | else | ||
1153 | result = ib_send_cm_sidr_req(ctx->cm_id, ¶m); | 1016 | result = ib_send_cm_sidr_req(ctx->cm_id, ¶m); |
1017 | ib_ucm_ctx_put(ctx); | ||
1018 | } else | ||
1019 | result = PTR_ERR(ctx); | ||
1154 | 1020 | ||
1155 | up(&ctx->file->mutex); | ||
1156 | ib_ucm_ctx_put(ctx); /* func reference */ | ||
1157 | done: | 1021 | done: |
1158 | kfree(param.private_data); | 1022 | kfree(param.private_data); |
1159 | kfree(param.path); | 1023 | kfree(param.path); |
1160 | |||
1161 | return result; | 1024 | return result; |
1162 | } | 1025 | } |
1163 | 1026 | ||
@@ -1184,30 +1047,22 @@ static ssize_t ib_ucm_send_sidr_rep(struct ib_ucm_file *file, | |||
1184 | if (result) | 1047 | if (result) |
1185 | goto done; | 1048 | goto done; |
1186 | 1049 | ||
1187 | param.qp_num = cmd.qpn; | 1050 | param.qp_num = cmd.qpn; |
1188 | param.qkey = cmd.qkey; | 1051 | param.qkey = cmd.qkey; |
1189 | param.status = cmd.status; | 1052 | param.status = cmd.status; |
1190 | param.info_length = cmd.info_len; | 1053 | param.info_length = cmd.info_len; |
1191 | param.private_data_len = cmd.data_len; | 1054 | param.private_data_len = cmd.data_len; |
1192 | |||
1193 | ctx = ib_ucm_ctx_get(cmd.id); | ||
1194 | if (!ctx) { | ||
1195 | result = -ENOENT; | ||
1196 | goto done; | ||
1197 | } | ||
1198 | 1055 | ||
1199 | down(&ctx->file->mutex); | 1056 | ctx = ib_ucm_ctx_get(file, cmd.id); |
1200 | if (ctx->file != file) | 1057 | if (!IS_ERR(ctx)) { |
1201 | result = -EINVAL; | ||
1202 | else | ||
1203 | result = ib_send_cm_sidr_rep(ctx->cm_id, ¶m); | 1058 | result = ib_send_cm_sidr_rep(ctx->cm_id, ¶m); |
1059 | ib_ucm_ctx_put(ctx); | ||
1060 | } else | ||
1061 | result = PTR_ERR(ctx); | ||
1204 | 1062 | ||
1205 | up(&ctx->file->mutex); | ||
1206 | ib_ucm_ctx_put(ctx); /* func reference */ | ||
1207 | done: | 1063 | done: |
1208 | kfree(param.private_data); | 1064 | kfree(param.private_data); |
1209 | kfree(param.info); | 1065 | kfree(param.info); |
1210 | |||
1211 | return result; | 1066 | return result; |
1212 | } | 1067 | } |
1213 | 1068 | ||
@@ -1305,22 +1160,17 @@ static int ib_ucm_close(struct inode *inode, struct file *filp) | |||
1305 | struct ib_ucm_context *ctx; | 1160 | struct ib_ucm_context *ctx; |
1306 | 1161 | ||
1307 | down(&file->mutex); | 1162 | down(&file->mutex); |
1308 | |||
1309 | while (!list_empty(&file->ctxs)) { | 1163 | while (!list_empty(&file->ctxs)) { |
1310 | 1164 | ||
1311 | ctx = list_entry(file->ctxs.next, | 1165 | ctx = list_entry(file->ctxs.next, |
1312 | struct ib_ucm_context, file_list); | 1166 | struct ib_ucm_context, file_list); |
1313 | 1167 | ||
1314 | up(&ctx->file->mutex); | 1168 | up(&file->mutex); |
1315 | ib_ucm_ctx_put(ctx); /* user reference */ | 1169 | ib_ucm_destroy_ctx(file, ctx->id); |
1316 | down(&file->mutex); | 1170 | down(&file->mutex); |
1317 | } | 1171 | } |
1318 | |||
1319 | up(&file->mutex); | 1172 | up(&file->mutex); |
1320 | |||
1321 | kfree(file); | 1173 | kfree(file); |
1322 | |||
1323 | ucm_dbg("Deleted struct\n"); | ||
1324 | return 0; | 1174 | return 0; |
1325 | } | 1175 | } |
1326 | 1176 | ||