|
@@ -700,23 +700,24 @@ static int srp_reconnect_target(struct srp_target_port *target)
|
|
|
struct Scsi_Host *shost = target->scsi_host;
|
|
|
int i, ret;
|
|
|
|
|
|
- if (target->state != SRP_TARGET_LIVE)
|
|
|
- return -EAGAIN;
|
|
|
-
|
|
|
scsi_target_block(&shost->shost_gendev);
|
|
|
|
|
|
srp_disconnect_target(target);
|
|
|
/*
|
|
|
- * Now get a new local CM ID so that we avoid confusing the
|
|
|
- * target in case things are really fouled up.
|
|
|
+ * Now get a new local CM ID so that we avoid confusing the target in
|
|
|
+ * case things are really fouled up. Doing so also ensures that all CM
|
|
|
+ * callbacks will have finished before a new QP is allocated.
|
|
|
*/
|
|
|
ret = srp_new_cm_id(target);
|
|
|
- if (ret)
|
|
|
- goto unblock;
|
|
|
-
|
|
|
- ret = srp_create_target_ib(target);
|
|
|
- if (ret)
|
|
|
- goto unblock;
|
|
|
+ /*
|
|
|
+ * Whether or not creating a new CM ID succeeded, create a new
|
|
|
+ * QP. This guarantees that all completion callback function
|
|
|
+ * invocations have finished before request resetting starts.
|
|
|
+ */
|
|
|
+ if (ret == 0)
|
|
|
+ ret = srp_create_target_ib(target);
|
|
|
+ else
|
|
|
+ srp_create_target_ib(target);
|
|
|
|
|
|
for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
|
|
|
struct srp_request *req = &target->req_ring[i];
|
|
@@ -728,9 +729,9 @@ static int srp_reconnect_target(struct srp_target_port *target)
|
|
|
for (i = 0; i < SRP_SQ_SIZE; ++i)
|
|
|
list_add(&target->tx_ring[i]->list, &target->free_tx);
|
|
|
|
|
|
- ret = srp_connect_target(target);
|
|
|
+ if (ret == 0)
|
|
|
+ ret = srp_connect_target(target);
|
|
|
|
|
|
-unblock:
|
|
|
scsi_target_unblock(&shost->shost_gendev, ret == 0 ? SDEV_RUNNING :
|
|
|
SDEV_TRANSPORT_OFFLINE);
|
|
|
|
|
@@ -1739,7 +1740,7 @@ static int srp_abort(struct scsi_cmnd *scmnd)
|
|
|
|
|
|
shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
|
|
|
|
|
|
- if (!req || target->qp_in_error || !srp_claim_req(target, req, scmnd))
|
|
|
+ if (!req || !srp_claim_req(target, req, scmnd))
|
|
|
return FAILED;
|
|
|
srp_send_tsk_mgmt(target, req->index, scmnd->device->lun,
|
|
|
SRP_TSK_ABORT_TASK);
|