aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_error.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_error.c')
-rw-r--r--drivers/scsi/scsi_error.c39
1 files changed, 24 insertions, 15 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 1c75646f9689..6a7a60fc0a4e 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -26,13 +26,13 @@
#include <linux/delay.h>
#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h>
-#include <scsi/scsi_request.h>
#include "scsi_priv.h"
#include "scsi_logging.h"
@@ -58,6 +58,28 @@ void scsi_eh_wakeup(struct Scsi_Host *shost)
}
/**
+ * scsi_schedule_eh - schedule EH for SCSI host
+ * @shost: SCSI host to invoke error handling on.
+ *
+ * Schedule SCSI EH without scmd.
+ **/
+void scsi_schedule_eh(struct Scsi_Host *shost)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(shost->host_lock, flags);
+
+ if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 ||
+ scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) {
+ shost->host_eh_scheduled++;
+ scsi_eh_wakeup(shost);
+ }
+
+ spin_unlock_irqrestore(shost->host_lock, flags);
+}
+EXPORT_SYMBOL_GPL(scsi_schedule_eh);
+
+/**
* scsi_eh_scmd_add - add scsi cmd to error handling.
* @scmd: scmd to run eh on.
* @eh_flag: optional SCSI_EH flag.
@@ -452,7 +474,6 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
(sdev->lun << 5 & 0xe0);
shost->eh_action = &done;
- scmd->request->rq_status = RQ_SCSI_BUSY;
spin_lock_irqsave(shost->host_lock, flags);
scsi_log_send(scmd);
@@ -461,7 +482,6 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
timeleft = wait_for_completion_timeout(&done, timeout);
- scmd->request->rq_status = RQ_SCSI_DONE;
shost->eh_action = NULL;
scsi_log_completion(scmd, SUCCESS);
@@ -1517,7 +1537,7 @@ int scsi_error_handler(void *data)
*/
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) {
- if (shost->host_failed == 0 ||
+ if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) ||
shost->host_failed != shost->host_busy) {
SCSI_LOG_ERROR_RECOVERY(1,
printk("Error handler scsi_eh_%d sleeping\n",
@@ -1657,7 +1677,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
scmd->request = &req;
memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout));
- scmd->request->rq_status = RQ_SCSI_BUSY;
memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd));
@@ -1671,8 +1690,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
scmd->cmd_len = 0;
scmd->sc_data_direction = DMA_BIDIRECTIONAL;
- scmd->sc_request = NULL;
- scmd->sc_magic = SCSI_CMND_MAGIC;
init_timer(&scmd->eh_timeout);
@@ -1769,14 +1786,6 @@ int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
}
EXPORT_SYMBOL(scsi_normalize_sense);
-int scsi_request_normalize_sense(struct scsi_request *sreq,
- struct scsi_sense_hdr *sshdr)
-{
- return scsi_normalize_sense(sreq->sr_sense_buffer,
- sizeof(sreq->sr_sense_buffer), sshdr);
-}
-EXPORT_SYMBOL(scsi_request_normalize_sense);
-
int scsi_command_normalize_sense(struct scsi_cmnd *cmd,
struct scsi_sense_hdr *sshdr)
{