diff options
Diffstat (limited to 'drivers/infiniband/ulp/srp/ib_srp.c')
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.c | 49 |
1 files changed, 32 insertions, 17 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 5f0f4fc58f43..e397f1b0af09 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -1787,17 +1787,24 @@ static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp) | |||
1787 | if (unlikely(rsp->tag & SRP_TAG_TSK_MGMT)) { | 1787 | if (unlikely(rsp->tag & SRP_TAG_TSK_MGMT)) { |
1788 | spin_lock_irqsave(&ch->lock, flags); | 1788 | spin_lock_irqsave(&ch->lock, flags); |
1789 | ch->req_lim += be32_to_cpu(rsp->req_lim_delta); | 1789 | ch->req_lim += be32_to_cpu(rsp->req_lim_delta); |
1790 | if (rsp->tag == ch->tsk_mgmt_tag) { | ||
1791 | ch->tsk_mgmt_status = -1; | ||
1792 | if (be32_to_cpu(rsp->resp_data_len) >= 4) | ||
1793 | ch->tsk_mgmt_status = rsp->data[3]; | ||
1794 | complete(&ch->tsk_mgmt_done); | ||
1795 | } else { | ||
1796 | shost_printk(KERN_ERR, target->scsi_host, | ||
1797 | "Received tsk mgmt response too late for tag %#llx\n", | ||
1798 | rsp->tag); | ||
1799 | } | ||
1790 | spin_unlock_irqrestore(&ch->lock, flags); | 1800 | spin_unlock_irqrestore(&ch->lock, flags); |
1791 | |||
1792 | ch->tsk_mgmt_status = -1; | ||
1793 | if (be32_to_cpu(rsp->resp_data_len) >= 4) | ||
1794 | ch->tsk_mgmt_status = rsp->data[3]; | ||
1795 | complete(&ch->tsk_mgmt_done); | ||
1796 | } else { | 1801 | } else { |
1797 | scmnd = scsi_host_find_tag(target->scsi_host, rsp->tag); | 1802 | scmnd = scsi_host_find_tag(target->scsi_host, rsp->tag); |
1798 | if (scmnd) { | 1803 | if (scmnd && scmnd->host_scribble) { |
1799 | req = (void *)scmnd->host_scribble; | 1804 | req = (void *)scmnd->host_scribble; |
1800 | scmnd = srp_claim_req(ch, req, NULL, scmnd); | 1805 | scmnd = srp_claim_req(ch, req, NULL, scmnd); |
1806 | } else { | ||
1807 | scmnd = NULL; | ||
1801 | } | 1808 | } |
1802 | if (!scmnd) { | 1809 | if (!scmnd) { |
1803 | shost_printk(KERN_ERR, target->scsi_host, | 1810 | shost_printk(KERN_ERR, target->scsi_host, |
@@ -2469,19 +2476,18 @@ srp_change_queue_depth(struct scsi_device *sdev, int qdepth) | |||
2469 | } | 2476 | } |
2470 | 2477 | ||
2471 | static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun, | 2478 | static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun, |
2472 | u8 func) | 2479 | u8 func, u8 *status) |
2473 | { | 2480 | { |
2474 | struct srp_target_port *target = ch->target; | 2481 | struct srp_target_port *target = ch->target; |
2475 | struct srp_rport *rport = target->rport; | 2482 | struct srp_rport *rport = target->rport; |
2476 | struct ib_device *dev = target->srp_host->srp_dev->dev; | 2483 | struct ib_device *dev = target->srp_host->srp_dev->dev; |
2477 | struct srp_iu *iu; | 2484 | struct srp_iu *iu; |
2478 | struct srp_tsk_mgmt *tsk_mgmt; | 2485 | struct srp_tsk_mgmt *tsk_mgmt; |
2486 | int res; | ||
2479 | 2487 | ||
2480 | if (!ch->connected || target->qp_in_error) | 2488 | if (!ch->connected || target->qp_in_error) |
2481 | return -1; | 2489 | return -1; |
2482 | 2490 | ||
2483 | init_completion(&ch->tsk_mgmt_done); | ||
2484 | |||
2485 | /* | 2491 | /* |
2486 | * Lock the rport mutex to avoid that srp_create_ch_ib() is | 2492 | * Lock the rport mutex to avoid that srp_create_ch_ib() is |
2487 | * invoked while a task management function is being sent. | 2493 | * invoked while a task management function is being sent. |
@@ -2504,10 +2510,16 @@ static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun, | |||
2504 | 2510 | ||
2505 | tsk_mgmt->opcode = SRP_TSK_MGMT; | 2511 | tsk_mgmt->opcode = SRP_TSK_MGMT; |
2506 | int_to_scsilun(lun, &tsk_mgmt->lun); | 2512 | int_to_scsilun(lun, &tsk_mgmt->lun); |
2507 | tsk_mgmt->tag = req_tag | SRP_TAG_TSK_MGMT; | ||
2508 | tsk_mgmt->tsk_mgmt_func = func; | 2513 | tsk_mgmt->tsk_mgmt_func = func; |
2509 | tsk_mgmt->task_tag = req_tag; | 2514 | tsk_mgmt->task_tag = req_tag; |
2510 | 2515 | ||
2516 | spin_lock_irq(&ch->lock); | ||
2517 | ch->tsk_mgmt_tag = (ch->tsk_mgmt_tag + 1) | SRP_TAG_TSK_MGMT; | ||
2518 | tsk_mgmt->tag = ch->tsk_mgmt_tag; | ||
2519 | spin_unlock_irq(&ch->lock); | ||
2520 | |||
2521 | init_completion(&ch->tsk_mgmt_done); | ||
2522 | |||
2511 | ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt, | 2523 | ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt, |
2512 | DMA_TO_DEVICE); | 2524 | DMA_TO_DEVICE); |
2513 | if (srp_post_send(ch, iu, sizeof(*tsk_mgmt))) { | 2525 | if (srp_post_send(ch, iu, sizeof(*tsk_mgmt))) { |
@@ -2516,13 +2528,15 @@ static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun, | |||
2516 | 2528 | ||
2517 | return -1; | 2529 | return -1; |
2518 | } | 2530 | } |
2531 | res = wait_for_completion_timeout(&ch->tsk_mgmt_done, | ||
2532 | msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS)); | ||
2533 | if (res > 0 && status) | ||
2534 | *status = ch->tsk_mgmt_status; | ||
2519 | mutex_unlock(&rport->mutex); | 2535 | mutex_unlock(&rport->mutex); |
2520 | 2536 | ||
2521 | if (!wait_for_completion_timeout(&ch->tsk_mgmt_done, | 2537 | WARN_ON_ONCE(res < 0); |
2522 | msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS))) | ||
2523 | return -1; | ||
2524 | 2538 | ||
2525 | return 0; | 2539 | return res > 0 ? 0 : -1; |
2526 | } | 2540 | } |
2527 | 2541 | ||
2528 | static int srp_abort(struct scsi_cmnd *scmnd) | 2542 | static int srp_abort(struct scsi_cmnd *scmnd) |
@@ -2548,7 +2562,7 @@ static int srp_abort(struct scsi_cmnd *scmnd) | |||
2548 | shost_printk(KERN_ERR, target->scsi_host, | 2562 | shost_printk(KERN_ERR, target->scsi_host, |
2549 | "Sending SRP abort for tag %#x\n", tag); | 2563 | "Sending SRP abort for tag %#x\n", tag); |
2550 | if (srp_send_tsk_mgmt(ch, tag, scmnd->device->lun, | 2564 | if (srp_send_tsk_mgmt(ch, tag, scmnd->device->lun, |
2551 | SRP_TSK_ABORT_TASK) == 0) | 2565 | SRP_TSK_ABORT_TASK, NULL) == 0) |
2552 | ret = SUCCESS; | 2566 | ret = SUCCESS; |
2553 | else if (target->rport->state == SRP_RPORT_LOST) | 2567 | else if (target->rport->state == SRP_RPORT_LOST) |
2554 | ret = FAST_IO_FAIL; | 2568 | ret = FAST_IO_FAIL; |
@@ -2566,14 +2580,15 @@ static int srp_reset_device(struct scsi_cmnd *scmnd) | |||
2566 | struct srp_target_port *target = host_to_target(scmnd->device->host); | 2580 | struct srp_target_port *target = host_to_target(scmnd->device->host); |
2567 | struct srp_rdma_ch *ch; | 2581 | struct srp_rdma_ch *ch; |
2568 | int i; | 2582 | int i; |
2583 | u8 status; | ||
2569 | 2584 | ||
2570 | shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n"); | 2585 | shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n"); |
2571 | 2586 | ||
2572 | ch = &target->ch[0]; | 2587 | ch = &target->ch[0]; |
2573 | if (srp_send_tsk_mgmt(ch, SRP_TAG_NO_REQ, scmnd->device->lun, | 2588 | if (srp_send_tsk_mgmt(ch, SRP_TAG_NO_REQ, scmnd->device->lun, |
2574 | SRP_TSK_LUN_RESET)) | 2589 | SRP_TSK_LUN_RESET, &status)) |
2575 | return FAILED; | 2590 | return FAILED; |
2576 | if (ch->tsk_mgmt_status) | 2591 | if (status) |
2577 | return FAILED; | 2592 | return FAILED; |
2578 | 2593 | ||
2579 | for (i = 0; i < target->ch_count; i++) { | 2594 | for (i = 0; i < target->ch_count; i++) { |