diff options
-rw-r--r-- | drivers/scsi/libiscsi.c | 37 | ||||
-rw-r--r-- | include/scsi/libiscsi.h | 3 |
2 files changed, 16 insertions, 24 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 3eddab0774e4..1def8e101249 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -505,6 +505,7 @@ static void iscsi_free_task(struct iscsi_task *task) | |||
505 | struct iscsi_conn *conn = task->conn; | 505 | struct iscsi_conn *conn = task->conn; |
506 | struct iscsi_session *session = conn->session; | 506 | struct iscsi_session *session = conn->session; |
507 | struct scsi_cmnd *sc = task->sc; | 507 | struct scsi_cmnd *sc = task->sc; |
508 | int oldstate = task->state; | ||
508 | 509 | ||
509 | ISCSI_DBG_SESSION(session, "freeing task itt 0x%x state %d sc %p\n", | 510 | ISCSI_DBG_SESSION(session, "freeing task itt 0x%x state %d sc %p\n", |
510 | task->itt, task->state, task->sc); | 511 | task->itt, task->state, task->sc); |
@@ -525,10 +526,10 @@ static void iscsi_free_task(struct iscsi_task *task) | |||
525 | /* SCSI eh reuses commands to verify us */ | 526 | /* SCSI eh reuses commands to verify us */ |
526 | sc->SCp.ptr = NULL; | 527 | sc->SCp.ptr = NULL; |
527 | /* | 528 | /* |
528 | * queue command may call this to free the task, but | 529 | * queue command may call this to free the task, so |
529 | * not have setup the sc callback | 530 | * it will decide how to return sc to scsi-ml. |
530 | */ | 531 | */ |
531 | if (sc->scsi_done) | 532 | if (oldstate != ISCSI_TASK_REQUEUE_SCSIQ) |
532 | sc->scsi_done(sc); | 533 | sc->scsi_done(sc); |
533 | } | 534 | } |
534 | } | 535 | } |
@@ -572,7 +573,8 @@ static void iscsi_complete_task(struct iscsi_task *task, int state) | |||
572 | task->itt, task->state, task->sc); | 573 | task->itt, task->state, task->sc); |
573 | if (task->state == ISCSI_TASK_COMPLETED || | 574 | if (task->state == ISCSI_TASK_COMPLETED || |
574 | task->state == ISCSI_TASK_ABRT_TMF || | 575 | task->state == ISCSI_TASK_ABRT_TMF || |
575 | task->state == ISCSI_TASK_ABRT_SESS_RECOV) | 576 | task->state == ISCSI_TASK_ABRT_SESS_RECOV || |
577 | task->state == ISCSI_TASK_REQUEUE_SCSIQ) | ||
576 | return; | 578 | return; |
577 | WARN_ON_ONCE(task->state == ISCSI_TASK_FREE); | 579 | WARN_ON_ONCE(task->state == ISCSI_TASK_FREE); |
578 | task->state = state; | 580 | task->state = state; |
@@ -1600,27 +1602,23 @@ enum { | |||
1600 | FAILURE_SESSION_NOT_READY, | 1602 | FAILURE_SESSION_NOT_READY, |
1601 | }; | 1603 | }; |
1602 | 1604 | ||
1603 | static int iscsi_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | 1605 | int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) |
1604 | { | 1606 | { |
1605 | struct iscsi_cls_session *cls_session; | 1607 | struct iscsi_cls_session *cls_session; |
1606 | struct Scsi_Host *host; | ||
1607 | struct iscsi_host *ihost; | 1608 | struct iscsi_host *ihost; |
1608 | int reason = 0; | 1609 | int reason = 0; |
1609 | struct iscsi_session *session; | 1610 | struct iscsi_session *session; |
1610 | struct iscsi_conn *conn; | 1611 | struct iscsi_conn *conn; |
1611 | struct iscsi_task *task = NULL; | 1612 | struct iscsi_task *task = NULL; |
1612 | 1613 | ||
1613 | sc->scsi_done = done; | ||
1614 | sc->result = 0; | 1614 | sc->result = 0; |
1615 | sc->SCp.ptr = NULL; | 1615 | sc->SCp.ptr = NULL; |
1616 | 1616 | ||
1617 | host = sc->device->host; | ||
1618 | ihost = shost_priv(host); | 1617 | ihost = shost_priv(host); |
1619 | spin_unlock(host->host_lock); | ||
1620 | 1618 | ||
1621 | cls_session = starget_to_session(scsi_target(sc->device)); | 1619 | cls_session = starget_to_session(scsi_target(sc->device)); |
1622 | session = cls_session->dd_data; | 1620 | session = cls_session->dd_data; |
1623 | spin_lock(&session->lock); | 1621 | spin_lock_bh(&session->lock); |
1624 | 1622 | ||
1625 | reason = iscsi_session_chkready(cls_session); | 1623 | reason = iscsi_session_chkready(cls_session); |
1626 | if (reason) { | 1624 | if (reason) { |
@@ -1706,25 +1704,21 @@ static int iscsi_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi | |||
1706 | } | 1704 | } |
1707 | 1705 | ||
1708 | session->queued_cmdsn++; | 1706 | session->queued_cmdsn++; |
1709 | spin_unlock(&session->lock); | 1707 | spin_unlock_bh(&session->lock); |
1710 | spin_lock(host->host_lock); | ||
1711 | return 0; | 1708 | return 0; |
1712 | 1709 | ||
1713 | prepd_reject: | 1710 | prepd_reject: |
1714 | sc->scsi_done = NULL; | 1711 | iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ); |
1715 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); | ||
1716 | reject: | 1712 | reject: |
1717 | spin_unlock(&session->lock); | 1713 | spin_unlock_bh(&session->lock); |
1718 | ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n", | 1714 | ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n", |
1719 | sc->cmnd[0], reason); | 1715 | sc->cmnd[0], reason); |
1720 | spin_lock(host->host_lock); | ||
1721 | return SCSI_MLQUEUE_TARGET_BUSY; | 1716 | return SCSI_MLQUEUE_TARGET_BUSY; |
1722 | 1717 | ||
1723 | prepd_fault: | 1718 | prepd_fault: |
1724 | sc->scsi_done = NULL; | 1719 | iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ); |
1725 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); | ||
1726 | fault: | 1720 | fault: |
1727 | spin_unlock(&session->lock); | 1721 | spin_unlock_bh(&session->lock); |
1728 | ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n", | 1722 | ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n", |
1729 | sc->cmnd[0], reason); | 1723 | sc->cmnd[0], reason); |
1730 | if (!scsi_bidi_cmnd(sc)) | 1724 | if (!scsi_bidi_cmnd(sc)) |
@@ -1733,12 +1727,9 @@ fault: | |||
1733 | scsi_out(sc)->resid = scsi_out(sc)->length; | 1727 | scsi_out(sc)->resid = scsi_out(sc)->length; |
1734 | scsi_in(sc)->resid = scsi_in(sc)->length; | 1728 | scsi_in(sc)->resid = scsi_in(sc)->length; |
1735 | } | 1729 | } |
1736 | done(sc); | 1730 | sc->scsi_done(sc); |
1737 | spin_lock(host->host_lock); | ||
1738 | return 0; | 1731 | return 0; |
1739 | } | 1732 | } |
1740 | |||
1741 | DEF_SCSI_QCMD(iscsi_queuecommand) | ||
1742 | EXPORT_SYMBOL_GPL(iscsi_queuecommand); | 1733 | EXPORT_SYMBOL_GPL(iscsi_queuecommand); |
1743 | 1734 | ||
1744 | int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason) | 1735 | int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason) |
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 68e951d79f0b..748382b32b52 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h | |||
@@ -89,6 +89,7 @@ enum { | |||
89 | ISCSI_TASK_RUNNING, | 89 | ISCSI_TASK_RUNNING, |
90 | ISCSI_TASK_ABRT_TMF, /* aborted due to TMF */ | 90 | ISCSI_TASK_ABRT_TMF, /* aborted due to TMF */ |
91 | ISCSI_TASK_ABRT_SESS_RECOV, /* aborted due to session recovery */ | 91 | ISCSI_TASK_ABRT_SESS_RECOV, /* aborted due to session recovery */ |
92 | ISCSI_TASK_REQUEUE_SCSIQ, /* qcmd requeueing to scsi-ml */ | ||
92 | }; | 93 | }; |
93 | 94 | ||
94 | struct iscsi_r2t_info { | 95 | struct iscsi_r2t_info { |
@@ -341,7 +342,7 @@ extern int iscsi_eh_abort(struct scsi_cmnd *sc); | |||
341 | extern int iscsi_eh_recover_target(struct scsi_cmnd *sc); | 342 | extern int iscsi_eh_recover_target(struct scsi_cmnd *sc); |
342 | extern int iscsi_eh_session_reset(struct scsi_cmnd *sc); | 343 | extern int iscsi_eh_session_reset(struct scsi_cmnd *sc); |
343 | extern int iscsi_eh_device_reset(struct scsi_cmnd *sc); | 344 | extern int iscsi_eh_device_reset(struct scsi_cmnd *sc); |
344 | extern int iscsi_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *sc); | 345 | extern int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc); |
345 | 346 | ||
346 | /* | 347 | /* |
347 | * iSCSI host helpers. | 348 | * iSCSI host helpers. |