diff options
Diffstat (limited to 'drivers/infiniband/hw/i40iw/i40iw_utils.c')
-rw-r--r-- | drivers/infiniband/hw/i40iw/i40iw_utils.c | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/i40iw/i40iw_utils.c b/drivers/infiniband/hw/i40iw/i40iw_utils.c index 56d986924a4c..e311ec559f4e 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_utils.c +++ b/drivers/infiniband/hw/i40iw/i40iw_utils.c | |||
@@ -337,6 +337,7 @@ struct i40iw_cqp_request *i40iw_get_cqp_request(struct i40iw_cqp *cqp, bool wait | |||
337 | */ | 337 | */ |
338 | void i40iw_free_cqp_request(struct i40iw_cqp *cqp, struct i40iw_cqp_request *cqp_request) | 338 | void i40iw_free_cqp_request(struct i40iw_cqp *cqp, struct i40iw_cqp_request *cqp_request) |
339 | { | 339 | { |
340 | struct i40iw_device *iwdev = container_of(cqp, struct i40iw_device, cqp); | ||
340 | unsigned long flags; | 341 | unsigned long flags; |
341 | 342 | ||
342 | if (cqp_request->dynamic) { | 343 | if (cqp_request->dynamic) { |
@@ -350,6 +351,7 @@ void i40iw_free_cqp_request(struct i40iw_cqp *cqp, struct i40iw_cqp_request *cqp | |||
350 | list_add_tail(&cqp_request->list, &cqp->cqp_avail_reqs); | 351 | list_add_tail(&cqp_request->list, &cqp->cqp_avail_reqs); |
351 | spin_unlock_irqrestore(&cqp->req_lock, flags); | 352 | spin_unlock_irqrestore(&cqp->req_lock, flags); |
352 | } | 353 | } |
354 | wake_up(&iwdev->close_wq); | ||
353 | } | 355 | } |
354 | 356 | ||
355 | /** | 357 | /** |
@@ -365,6 +367,56 @@ void i40iw_put_cqp_request(struct i40iw_cqp *cqp, | |||
365 | } | 367 | } |
366 | 368 | ||
367 | /** | 369 | /** |
370 | * i40iw_free_pending_cqp_request -free pending cqp request objs | ||
371 | * @cqp: cqp ptr | ||
372 | * @cqp_request: to be put back in cqp list | ||
373 | */ | ||
374 | static void i40iw_free_pending_cqp_request(struct i40iw_cqp *cqp, | ||
375 | struct i40iw_cqp_request *cqp_request) | ||
376 | { | ||
377 | struct i40iw_device *iwdev = container_of(cqp, struct i40iw_device, cqp); | ||
378 | |||
379 | if (cqp_request->waiting) { | ||
380 | cqp_request->compl_info.error = true; | ||
381 | cqp_request->request_done = true; | ||
382 | wake_up(&cqp_request->waitq); | ||
383 | } | ||
384 | i40iw_put_cqp_request(cqp, cqp_request); | ||
385 | wait_event_timeout(iwdev->close_wq, | ||
386 | !atomic_read(&cqp_request->refcount), | ||
387 | 1000); | ||
388 | } | ||
389 | |||
390 | /** | ||
391 | * i40iw_cleanup_pending_cqp_op - clean-up cqp with no completions | ||
392 | * @iwdev: iwarp device | ||
393 | */ | ||
394 | void i40iw_cleanup_pending_cqp_op(struct i40iw_device *iwdev) | ||
395 | { | ||
396 | struct i40iw_sc_dev *dev = &iwdev->sc_dev; | ||
397 | struct i40iw_cqp *cqp = &iwdev->cqp; | ||
398 | struct i40iw_cqp_request *cqp_request = NULL; | ||
399 | struct cqp_commands_info *pcmdinfo = NULL; | ||
400 | u32 i, pending_work, wqe_idx; | ||
401 | |||
402 | pending_work = I40IW_RING_WORK_AVAILABLE(cqp->sc_cqp.sq_ring); | ||
403 | wqe_idx = I40IW_RING_GETCURRENT_TAIL(cqp->sc_cqp.sq_ring); | ||
404 | for (i = 0; i < pending_work; i++) { | ||
405 | cqp_request = (struct i40iw_cqp_request *)(unsigned long)cqp->scratch_array[wqe_idx]; | ||
406 | if (cqp_request) | ||
407 | i40iw_free_pending_cqp_request(cqp, cqp_request); | ||
408 | wqe_idx = (wqe_idx + 1) % I40IW_RING_GETSIZE(cqp->sc_cqp.sq_ring); | ||
409 | } | ||
410 | |||
411 | while (!list_empty(&dev->cqp_cmd_head)) { | ||
412 | pcmdinfo = (struct cqp_commands_info *)i40iw_remove_head(&dev->cqp_cmd_head); | ||
413 | cqp_request = container_of(pcmdinfo, struct i40iw_cqp_request, info); | ||
414 | if (cqp_request) | ||
415 | i40iw_free_pending_cqp_request(cqp, cqp_request); | ||
416 | } | ||
417 | } | ||
418 | |||
419 | /** | ||
368 | * i40iw_free_qp - callback after destroy cqp completes | 420 | * i40iw_free_qp - callback after destroy cqp completes |
369 | * @cqp_request: cqp request for destroy qp | 421 | * @cqp_request: cqp request for destroy qp |
370 | * @num: not used | 422 | * @num: not used |
@@ -546,8 +598,12 @@ void i40iw_rem_ref(struct ib_qp *ibqp) | |||
546 | cqp_info->in.u.qp_destroy.scratch = (uintptr_t)cqp_request; | 598 | cqp_info->in.u.qp_destroy.scratch = (uintptr_t)cqp_request; |
547 | cqp_info->in.u.qp_destroy.remove_hash_idx = true; | 599 | cqp_info->in.u.qp_destroy.remove_hash_idx = true; |
548 | status = i40iw_handle_cqp_op(iwdev, cqp_request); | 600 | status = i40iw_handle_cqp_op(iwdev, cqp_request); |
549 | if (status) | 601 | if (!status) |
550 | i40iw_pr_err("CQP-OP Destroy QP fail"); | 602 | return; |
603 | |||
604 | i40iw_rem_pdusecount(iwqp->iwpd, iwdev); | ||
605 | i40iw_free_qp_resources(iwdev, iwqp, qp_num); | ||
606 | i40iw_rem_devusecount(iwdev); | ||
551 | } | 607 | } |
552 | 608 | ||
553 | /** | 609 | /** |