|
@@ -646,13 +646,16 @@ static void srp_reset_req(struct srp_target_port *target, struct srp_request *re
|
|
|
|
|
|
static int srp_reconnect_target(struct srp_target_port *target)
|
|
|
{
|
|
|
+ struct Scsi_Host *shost = target->scsi_host;
|
|
|
struct ib_qp_attr qp_attr;
|
|
|
struct ib_wc wc;
|
|
|
int i, ret;
|
|
|
|
|
|
- if (!srp_change_state(target, SRP_TARGET_LIVE, SRP_TARGET_CONNECTING))
|
|
|
+ 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
|
|
@@ -660,16 +663,16 @@ static int srp_reconnect_target(struct srp_target_port *target)
|
|
|
*/
|
|
|
ret = srp_new_cm_id(target);
|
|
|
if (ret)
|
|
|
- goto err;
|
|
|
+ goto unblock;
|
|
|
|
|
|
qp_attr.qp_state = IB_QPS_RESET;
|
|
|
ret = ib_modify_qp(target->qp, &qp_attr, IB_QP_STATE);
|
|
|
if (ret)
|
|
|
- goto err;
|
|
|
+ goto unblock;
|
|
|
|
|
|
ret = srp_init_qp(target, target->qp);
|
|
|
if (ret)
|
|
|
- goto err;
|
|
|
+ goto unblock;
|
|
|
|
|
|
while (ib_poll_cq(target->recv_cq, 1, &wc) > 0)
|
|
|
; /* nothing */
|
|
@@ -688,11 +691,15 @@ static int srp_reconnect_target(struct srp_target_port *target)
|
|
|
|
|
|
target->qp_in_error = 0;
|
|
|
ret = srp_connect_target(target);
|
|
|
+
|
|
|
+unblock:
|
|
|
+ scsi_target_unblock(&shost->shost_gendev, ret == 0 ? SDEV_RUNNING :
|
|
|
+ SDEV_TRANSPORT_OFFLINE);
|
|
|
+
|
|
|
if (ret)
|
|
|
goto err;
|
|
|
|
|
|
- if (!srp_change_state(target, SRP_TARGET_CONNECTING, SRP_TARGET_LIVE))
|
|
|
- ret = -EAGAIN;
|
|
|
+ shost_printk(KERN_INFO, target->scsi_host, PFX "reconnect succeeded\n");
|
|
|
|
|
|
return ret;
|
|
|
|
|
@@ -710,7 +717,7 @@ err:
|
|
|
* the flush_scheduled_work() in srp_remove_one().
|
|
|
*/
|
|
|
spin_lock_irq(&target->lock);
|
|
|
- if (target->state == SRP_TARGET_CONNECTING) {
|
|
|
+ if (target->state == SRP_TARGET_LIVE) {
|
|
|
target->state = SRP_TARGET_DEAD;
|
|
|
INIT_WORK(&target->work, srp_remove_work);
|
|
|
queue_work(ib_wq, &target->work);
|
|
@@ -1311,9 +1318,6 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
|
|
|
unsigned long flags;
|
|
|
int len;
|
|
|
|
|
|
- if (target->state == SRP_TARGET_CONNECTING)
|
|
|
- goto err;
|
|
|
-
|
|
|
if (target->state == SRP_TARGET_DEAD ||
|
|
|
target->state == SRP_TARGET_REMOVED) {
|
|
|
scmnd->result = DID_BAD_TARGET << 16;
|
|
@@ -1377,7 +1381,6 @@ err_iu:
|
|
|
err_unlock:
|
|
|
spin_unlock_irqrestore(&target->lock, flags);
|
|
|
|
|
|
-err:
|
|
|
return SCSI_MLQUEUE_HOST_BUSY;
|
|
|
}
|
|
|
|