xref: /openbmc/linux/drivers/scsi/scsi_error.c (revision 695c312ec5a68e4373d063ee649c7b925ffb5da7)
1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *  scsi_error.c Copyright (C) 1997 Eric Youngdale
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  *  SCSI error/timeout handling
61da177e4SLinus Torvalds  *      Initial versions: Eric Youngdale.  Based upon conversations with
71da177e4SLinus Torvalds  *                        Leonard Zubkoff and David Miller at Linux Expo,
81da177e4SLinus Torvalds  *                        ideas originating from all over the place.
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  *	Restructured scsi_unjam_host and associated functions.
111da177e4SLinus Torvalds  *	September 04, 2002 Mike Anderson (andmike@us.ibm.com)
121da177e4SLinus Torvalds  *
131da177e4SLinus Torvalds  *	Forward port of Russell King's (rmk@arm.linux.org.uk) changes and
141da177e4SLinus Torvalds  *	minor cleanups.
151da177e4SLinus Torvalds  *	September 30, 2002 Mike Anderson (andmike@us.ibm.com)
161da177e4SLinus Torvalds  */
171da177e4SLinus Torvalds 
181da177e4SLinus Torvalds #include <linux/module.h>
191da177e4SLinus Torvalds #include <linux/sched.h>
205a0e3ad6STejun Heo #include <linux/gfp.h>
211da177e4SLinus Torvalds #include <linux/timer.h>
221da177e4SLinus Torvalds #include <linux/string.h>
231da177e4SLinus Torvalds #include <linux/kernel.h>
2483144186SRafael J. Wysocki #include <linux/freezer.h>
25c5478defSChristoph Hellwig #include <linux/kthread.h>
261da177e4SLinus Torvalds #include <linux/interrupt.h>
271da177e4SLinus Torvalds #include <linux/blkdev.h>
281da177e4SLinus Torvalds #include <linux/delay.h>
29fc73648aSHannes Reinecke #include <linux/jiffies.h>
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds #include <scsi/scsi.h>
32beb40487SChristoph Hellwig #include <scsi/scsi_cmnd.h>
331da177e4SLinus Torvalds #include <scsi/scsi_dbg.h>
341da177e4SLinus Torvalds #include <scsi/scsi_device.h>
3518a4d0a2SMartin K. Petersen #include <scsi/scsi_driver.h>
361da177e4SLinus Torvalds #include <scsi/scsi_eh.h>
377708c165SSagi Grimberg #include <scsi/scsi_common.h>
38c829c394SJames Smart #include <scsi/scsi_transport.h>
391da177e4SLinus Torvalds #include <scsi/scsi_host.h>
401da177e4SLinus Torvalds #include <scsi/scsi_ioctl.h>
41ee14c674SChristoph Hellwig #include <scsi/scsi_dh.h>
4229cfc2abSMartin Wilck #include <scsi/scsi_devinfo.h>
43176aa9d6SChristoph Hellwig #include <scsi/sg.h>
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds #include "scsi_priv.h"
461da177e4SLinus Torvalds #include "scsi_logging.h"
4779ee8304SAdrian Bunk #include "scsi_transport_api.h"
481da177e4SLinus Torvalds 
49bf816235SKei Tokunaga #include <trace/events/scsi.h>
50bf816235SKei Tokunaga 
512908769cSDamien Le Moal #include <asm/unaligned.h>
522908769cSDamien Le Moal 
531da177e4SLinus Torvalds /*
541da177e4SLinus Torvalds  * These should *probably* be handled by the host itself.
551da177e4SLinus Torvalds  * Since it is allowed to sleep, it probably should.
561da177e4SLinus Torvalds  */
571da177e4SLinus Torvalds #define BUS_RESET_SETTLE_TIME   (10)
581da177e4SLinus Torvalds #define HOST_RESET_SETTLE_TIME  (10)
591da177e4SLinus Torvalds 
603eef6257SDavid Jeffery static int scsi_eh_try_stu(struct scsi_cmnd *scmd);
6131435de9SBart Van Assche static enum scsi_disposition scsi_try_to_abort_cmd(const struct scsi_host_template *,
62e494f6a7SHannes Reinecke 						   struct scsi_cmnd *);
633eef6257SDavid Jeffery 
scsi_eh_wakeup(struct Scsi_Host * shost,unsigned int busy)6465ead846SMing Lei void scsi_eh_wakeup(struct Scsi_Host *shost, unsigned int busy)
651da177e4SLinus Torvalds {
66f0317e88SBart Van Assche 	lockdep_assert_held(shost->host_lock);
67f0317e88SBart Van Assche 
6865ead846SMing Lei 	if (busy == shost->host_failed) {
69bf816235SKei Tokunaga 		trace_scsi_eh_wakeup(shost);
703ed7a470SJames Bottomley 		wake_up_process(shost->ehandler);
7191921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(5, shost_printk(KERN_INFO, shost,
7291921e01SHannes Reinecke 			"Waking error handler thread\n"));
731da177e4SLinus Torvalds 	}
741da177e4SLinus Torvalds }
75f8bbfc24STejun Heo 
76f8bbfc24STejun Heo /**
77f8bbfc24STejun Heo  * scsi_schedule_eh - schedule EH for SCSI host
78f8bbfc24STejun Heo  * @shost:	SCSI host to invoke error handling on.
79f8bbfc24STejun Heo  *
80f8bbfc24STejun Heo  * Schedule SCSI EH without scmd.
81dc8875e1SRandy Dunlap  */
scsi_schedule_eh(struct Scsi_Host * shost)82f8bbfc24STejun Heo void scsi_schedule_eh(struct Scsi_Host *shost)
83f8bbfc24STejun Heo {
84f8bbfc24STejun Heo 	unsigned long flags;
85f8bbfc24STejun Heo 
86f8bbfc24STejun Heo 	spin_lock_irqsave(shost->host_lock, flags);
87f8bbfc24STejun Heo 
88f8bbfc24STejun Heo 	if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 ||
89f8bbfc24STejun Heo 	    scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) {
90f8bbfc24STejun Heo 		shost->host_eh_scheduled++;
9165ead846SMing Lei 		scsi_eh_wakeup(shost, scsi_host_busy(shost));
92f8bbfc24STejun Heo 	}
93f8bbfc24STejun Heo 
94f8bbfc24STejun Heo 	spin_unlock_irqrestore(shost->host_lock, flags);
95f8bbfc24STejun Heo }
96f8bbfc24STejun Heo EXPORT_SYMBOL_GPL(scsi_schedule_eh);
971da177e4SLinus Torvalds 
scsi_host_eh_past_deadline(struct Scsi_Host * shost)98b4562022SHannes Reinecke static int scsi_host_eh_past_deadline(struct Scsi_Host *shost)
99b4562022SHannes Reinecke {
100bb3b621aSRen Mingxin 	if (!shost->last_reset || shost->eh_deadline == -1)
101b4562022SHannes Reinecke 		return 0;
102b4562022SHannes Reinecke 
10376ad3e59SHannes Reinecke 	/*
10476ad3e59SHannes Reinecke 	 * 32bit accesses are guaranteed to be atomic
10576ad3e59SHannes Reinecke 	 * (on all supported architectures), so instead
10676ad3e59SHannes Reinecke 	 * of using a spinlock we can as well double check
107bb3b621aSRen Mingxin 	 * if eh_deadline has been set to 'off' during the
10876ad3e59SHannes Reinecke 	 * time_before call.
10976ad3e59SHannes Reinecke 	 */
11076ad3e59SHannes Reinecke 	if (time_before(jiffies, shost->last_reset + shost->eh_deadline) &&
111bb3b621aSRen Mingxin 	    shost->eh_deadline > -1)
112b4562022SHannes Reinecke 		return 0;
113b4562022SHannes Reinecke 
114b4562022SHannes Reinecke 	return 1;
115b4562022SHannes Reinecke }
116b4562022SHannes Reinecke 
scsi_cmd_retry_allowed(struct scsi_cmnd * cmd)1172a242d59SMike Christie static bool scsi_cmd_retry_allowed(struct scsi_cmnd *cmd)
1182a242d59SMike Christie {
1192a242d59SMike Christie 	if (cmd->allowed == SCSI_CMD_RETRIES_NO_LIMIT)
1202a242d59SMike Christie 		return true;
1212a242d59SMike Christie 
1222a242d59SMike Christie 	return ++cmd->retries <= cmd->allowed;
1232a242d59SMike Christie }
1242a242d59SMike Christie 
scsi_eh_should_retry_cmd(struct scsi_cmnd * cmd)12560bee27bSMuneendra Kumar static bool scsi_eh_should_retry_cmd(struct scsi_cmnd *cmd)
12660bee27bSMuneendra Kumar {
12760bee27bSMuneendra Kumar 	struct scsi_device *sdev = cmd->device;
12860bee27bSMuneendra Kumar 	struct Scsi_Host *host = sdev->host;
12960bee27bSMuneendra Kumar 
13060bee27bSMuneendra Kumar 	if (host->hostt->eh_should_retry_cmd)
13160bee27bSMuneendra Kumar 		return  host->hostt->eh_should_retry_cmd(cmd);
13260bee27bSMuneendra Kumar 
13360bee27bSMuneendra Kumar 	return true;
13460bee27bSMuneendra Kumar }
13560bee27bSMuneendra Kumar 
1361da177e4SLinus Torvalds /**
137e494f6a7SHannes Reinecke  * scmd_eh_abort_handler - Handle command aborts
138e494f6a7SHannes Reinecke  * @work:	command to be aborted.
139923f46f9SBart Van Assche  *
140923f46f9SBart Van Assche  * Note: this function must be called only for a command that has timed out.
141923f46f9SBart Van Assche  * Because the block layer marks a request as complete before it calls
142deef1be1SJohn Garry  * scsi_timeout(), a .scsi_done() call from the LLD for a command that has
143923f46f9SBart Van Assche  * timed out do not have any effect. Hence it is safe to call
144923f46f9SBart Van Assche  * scsi_finish_command() from this function.
145e494f6a7SHannes Reinecke  */
146e494f6a7SHannes Reinecke void
scmd_eh_abort_handler(struct work_struct * work)147e494f6a7SHannes Reinecke scmd_eh_abort_handler(struct work_struct *work)
148e494f6a7SHannes Reinecke {
149e494f6a7SHannes Reinecke 	struct scsi_cmnd *scmd =
150e494f6a7SHannes Reinecke 		container_of(work, struct scsi_cmnd, abort_work.work);
151e494f6a7SHannes Reinecke 	struct scsi_device *sdev = scmd->device;
15254d816d3SEwan D. Milne 	struct Scsi_Host *shost = sdev->host;
153b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
1545ae17501SEwan D. Milne 	unsigned long flags;
155e494f6a7SHannes Reinecke 
15654d816d3SEwan D. Milne 	if (scsi_host_eh_past_deadline(shost)) {
157e494f6a7SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3,
158e494f6a7SHannes Reinecke 			scmd_printk(KERN_INFO, scmd,
159470613b4SHannes Reinecke 				    "eh timeout, not aborting\n"));
16054d816d3SEwan D. Milne 		goto out;
16154d816d3SEwan D. Milne 	}
16254d816d3SEwan D. Milne 
163e494f6a7SHannes Reinecke 	SCSI_LOG_ERROR_RECOVERY(3,
164e494f6a7SHannes Reinecke 			scmd_printk(KERN_INFO, scmd,
165470613b4SHannes Reinecke 				    "aborting command\n"));
16654d816d3SEwan D. Milne 	rtn = scsi_try_to_abort_cmd(shost->hostt, scmd);
16754d816d3SEwan D. Milne 	if (rtn != SUCCESS) {
168e494f6a7SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3,
169e494f6a7SHannes Reinecke 			scmd_printk(KERN_INFO, scmd,
170470613b4SHannes Reinecke 				    "cmd abort %s\n",
171883a030fSHannes Reinecke 				    (rtn == FAST_IO_FAIL) ?
172883a030fSHannes Reinecke 				    "not send" : "failed"));
17354d816d3SEwan D. Milne 		goto out;
174e494f6a7SHannes Reinecke 	}
17554d816d3SEwan D. Milne 	set_host_byte(scmd, DID_TIME_OUT);
17654d816d3SEwan D. Milne 	if (scsi_host_eh_past_deadline(shost)) {
17754d816d3SEwan D. Milne 		SCSI_LOG_ERROR_RECOVERY(3,
17854d816d3SEwan D. Milne 			scmd_printk(KERN_INFO, scmd,
17954d816d3SEwan D. Milne 				    "eh timeout, not retrying "
18054d816d3SEwan D. Milne 				    "aborted command\n"));
18154d816d3SEwan D. Milne 		goto out;
182bb3b621aSRen Mingxin 	}
183e494f6a7SHannes Reinecke 
18454d816d3SEwan D. Milne 	spin_lock_irqsave(shost->host_lock, flags);
1855ae17501SEwan D. Milne 	list_del_init(&scmd->eh_entry);
18654d816d3SEwan D. Milne 
18754d816d3SEwan D. Milne 	/*
18854d816d3SEwan D. Milne 	 * If the abort succeeds, and there is no further
18954d816d3SEwan D. Milne 	 * EH action, clear the ->last_reset time.
19054d816d3SEwan D. Milne 	 */
19154d816d3SEwan D. Milne 	if (list_empty(&shost->eh_abort_list) &&
19254d816d3SEwan D. Milne 	    list_empty(&shost->eh_cmd_q))
19354d816d3SEwan D. Milne 		if (shost->eh_deadline != -1)
19454d816d3SEwan D. Milne 			shost->last_reset = 0;
19554d816d3SEwan D. Milne 
19654d816d3SEwan D. Milne 	spin_unlock_irqrestore(shost->host_lock, flags);
19754d816d3SEwan D. Milne 
19854d816d3SEwan D. Milne 	if (!scsi_noretry_cmd(scmd) &&
19954d816d3SEwan D. Milne 	    scsi_cmd_retry_allowed(scmd) &&
20054d816d3SEwan D. Milne 	    scsi_eh_should_retry_cmd(scmd)) {
20154d816d3SEwan D. Milne 		SCSI_LOG_ERROR_RECOVERY(3,
20254d816d3SEwan D. Milne 			scmd_printk(KERN_WARNING, scmd,
20354d816d3SEwan D. Milne 				    "retry aborted command\n"));
20454d816d3SEwan D. Milne 		scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY);
20554d816d3SEwan D. Milne 	} else {
20654d816d3SEwan D. Milne 		SCSI_LOG_ERROR_RECOVERY(3,
20754d816d3SEwan D. Milne 			scmd_printk(KERN_WARNING, scmd,
20854d816d3SEwan D. Milne 				    "finish aborted command\n"));
20954d816d3SEwan D. Milne 		scsi_finish_command(scmd);
21054d816d3SEwan D. Milne 	}
21154d816d3SEwan D. Milne 	return;
21254d816d3SEwan D. Milne 
21354d816d3SEwan D. Milne out:
21454d816d3SEwan D. Milne 	spin_lock_irqsave(shost->host_lock, flags);
21554d816d3SEwan D. Milne 	list_del_init(&scmd->eh_entry);
21654d816d3SEwan D. Milne 	spin_unlock_irqrestore(shost->host_lock, flags);
21754d816d3SEwan D. Milne 
218a0658632SHannes Reinecke 	scsi_eh_scmd_add(scmd);
219e494f6a7SHannes Reinecke }
220e494f6a7SHannes Reinecke 
221e494f6a7SHannes Reinecke /**
222e494f6a7SHannes Reinecke  * scsi_abort_command - schedule a command abort
223e494f6a7SHannes Reinecke  * @scmd:	scmd to abort.
224e494f6a7SHannes Reinecke  *
225e494f6a7SHannes Reinecke  * We only need to abort commands after a command timeout
226e494f6a7SHannes Reinecke  */
227e494f6a7SHannes Reinecke static int
scsi_abort_command(struct scsi_cmnd * scmd)228e494f6a7SHannes Reinecke scsi_abort_command(struct scsi_cmnd *scmd)
229e494f6a7SHannes Reinecke {
230e494f6a7SHannes Reinecke 	struct scsi_device *sdev = scmd->device;
231e494f6a7SHannes Reinecke 	struct Scsi_Host *shost = sdev->host;
232e494f6a7SHannes Reinecke 	unsigned long flags;
233e494f6a7SHannes Reinecke 
234d0b90255SHannes Reinecke 	if (!shost->hostt->eh_abort_handler) {
235d0b90255SHannes Reinecke 		/* No abort handler, fail command directly */
236d0b90255SHannes Reinecke 		return FAILED;
237d0b90255SHannes Reinecke 	}
238d0b90255SHannes Reinecke 
239e494f6a7SHannes Reinecke 	if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) {
240e494f6a7SHannes Reinecke 		/*
241e494f6a7SHannes Reinecke 		 * Retry after abort failed, escalate to next level.
242e494f6a7SHannes Reinecke 		 */
243e494f6a7SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3,
244e494f6a7SHannes Reinecke 			scmd_printk(KERN_INFO, scmd,
245470613b4SHannes Reinecke 				    "previous abort failed\n"));
246fcc95a76SBart Van Assche 		BUG_ON(delayed_work_pending(&scmd->abort_work));
247e494f6a7SHannes Reinecke 		return FAILED;
248e494f6a7SHannes Reinecke 	}
249e494f6a7SHannes Reinecke 
250e494f6a7SHannes Reinecke 	spin_lock_irqsave(shost->host_lock, flags);
251bb3b621aSRen Mingxin 	if (shost->eh_deadline != -1 && !shost->last_reset)
252e494f6a7SHannes Reinecke 		shost->last_reset = jiffies;
2535ae17501SEwan D. Milne 	BUG_ON(!list_empty(&scmd->eh_entry));
2545ae17501SEwan D. Milne 	list_add_tail(&scmd->eh_entry, &shost->eh_abort_list);
255e494f6a7SHannes Reinecke 	spin_unlock_irqrestore(shost->host_lock, flags);
256e494f6a7SHannes Reinecke 
257e494f6a7SHannes Reinecke 	scmd->eh_eflags |= SCSI_EH_ABORT_SCHEDULED;
258e494f6a7SHannes Reinecke 	SCSI_LOG_ERROR_RECOVERY(3,
259470613b4SHannes Reinecke 		scmd_printk(KERN_INFO, scmd, "abort scheduled\n"));
260e494f6a7SHannes Reinecke 	queue_delayed_work(shost->tmf_work_q, &scmd->abort_work, HZ / 100);
261e494f6a7SHannes Reinecke 	return SUCCESS;
262e494f6a7SHannes Reinecke }
263e494f6a7SHannes Reinecke 
264e494f6a7SHannes Reinecke /**
2657a38dc0bSHannes Reinecke  * scsi_eh_reset - call into ->eh_action to reset internal counters
2667a38dc0bSHannes Reinecke  * @scmd:	scmd to run eh on.
2677a38dc0bSHannes Reinecke  *
2687a38dc0bSHannes Reinecke  * The scsi driver might be carrying internal state about the
2697a38dc0bSHannes Reinecke  * devices, so we need to call into the driver to reset the
2707a38dc0bSHannes Reinecke  * internal state once the error handler is started.
2717a38dc0bSHannes Reinecke  */
scsi_eh_reset(struct scsi_cmnd * scmd)2727a38dc0bSHannes Reinecke static void scsi_eh_reset(struct scsi_cmnd *scmd)
2737a38dc0bSHannes Reinecke {
274aa8e25e5SBart Van Assche 	if (!blk_rq_is_passthrough(scsi_cmd_to_rq(scmd))) {
2757a38dc0bSHannes Reinecke 		struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd);
2767a38dc0bSHannes Reinecke 		if (sdrv->eh_reset)
2777a38dc0bSHannes Reinecke 			sdrv->eh_reset(scmd);
2787a38dc0bSHannes Reinecke 	}
2797a38dc0bSHannes Reinecke }
2807a38dc0bSHannes Reinecke 
scsi_eh_inc_host_failed(struct rcu_head * head)2813bd6f43fSBart Van Assche static void scsi_eh_inc_host_failed(struct rcu_head *head)
2823bd6f43fSBart Van Assche {
2833be8828fSBart Van Assche 	struct scsi_cmnd *scmd = container_of(head, typeof(*scmd), rcu);
2843be8828fSBart Van Assche 	struct Scsi_Host *shost = scmd->device->host;
285*aceb4ab9SMing Lei 	unsigned int busy = scsi_host_busy(shost);
2863bd6f43fSBart Van Assche 	unsigned long flags;
2873bd6f43fSBart Van Assche 
2883bd6f43fSBart Van Assche 	spin_lock_irqsave(shost->host_lock, flags);
2893bd6f43fSBart Van Assche 	shost->host_failed++;
290*aceb4ab9SMing Lei 	scsi_eh_wakeup(shost, busy);
2913bd6f43fSBart Van Assche 	spin_unlock_irqrestore(shost->host_lock, flags);
2923bd6f43fSBart Van Assche }
2933bd6f43fSBart Van Assche 
2947a38dc0bSHannes Reinecke /**
2951da177e4SLinus Torvalds  * scsi_eh_scmd_add - add scsi cmd to error handling.
2961da177e4SLinus Torvalds  * @scmd:	scmd to run eh on.
297dc8875e1SRandy Dunlap  */
scsi_eh_scmd_add(struct scsi_cmnd * scmd)298a0658632SHannes Reinecke void scsi_eh_scmd_add(struct scsi_cmnd *scmd)
2991da177e4SLinus Torvalds {
3001da177e4SLinus Torvalds 	struct Scsi_Host *shost = scmd->device->host;
3011da177e4SLinus Torvalds 	unsigned long flags;
3022171b6d0SHannes Reinecke 	int ret;
3031da177e4SLinus Torvalds 
3042171b6d0SHannes Reinecke 	WARN_ON_ONCE(!shost->ehandler);
3051da177e4SLinus Torvalds 
3061da177e4SLinus Torvalds 	spin_lock_irqsave(shost->host_lock, flags);
3072171b6d0SHannes Reinecke 	if (scsi_host_set_state(shost, SHOST_RECOVERY)) {
3082171b6d0SHannes Reinecke 		ret = scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY);
3092171b6d0SHannes Reinecke 		WARN_ON_ONCE(ret);
3102171b6d0SHannes Reinecke 	}
311bb3b621aSRen Mingxin 	if (shost->eh_deadline != -1 && !shost->last_reset)
312b4562022SHannes Reinecke 		shost->last_reset = jiffies;
313b4562022SHannes Reinecke 
3147a38dc0bSHannes Reinecke 	scsi_eh_reset(scmd);
3151da177e4SLinus Torvalds 	list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
3161da177e4SLinus Torvalds 	spin_unlock_irqrestore(shost->host_lock, flags);
3173bd6f43fSBart Van Assche 	/*
3183bd6f43fSBart Van Assche 	 * Ensure that all tasks observe the host state change before the
3193bd6f43fSBart Van Assche 	 * host_failed change.
3203bd6f43fSBart Van Assche 	 */
32154d87b0aSUladzislau Rezki 	call_rcu_hurry(&scmd->rcu, scsi_eh_inc_host_failed);
3221da177e4SLinus Torvalds }
3231da177e4SLinus Torvalds 
3241da177e4SLinus Torvalds /**
325deef1be1SJohn Garry  * scsi_timeout - Timeout function for normal scsi commands.
326242f9dcbSJens Axboe  * @req:	request that is timing out.
3271da177e4SLinus Torvalds  *
3281da177e4SLinus Torvalds  * Notes:
3291da177e4SLinus Torvalds  *     We do not need to lock this.  There is the potential for a race
3301da177e4SLinus Torvalds  *     only in that the normal completion handling might run, but if the
3311da177e4SLinus Torvalds  *     normal completion function determines that the timer has already
3321da177e4SLinus Torvalds  *     fired, then it mustn't do anything.
333dc8875e1SRandy Dunlap  */
scsi_timeout(struct request * req)3349bdb4833SJohn Garry enum blk_eh_timer_return scsi_timeout(struct request *req)
3351da177e4SLinus Torvalds {
336bed2213dSBart Van Assche 	struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(req);
3370bf8c869SJesper Juhl 	struct Scsi_Host *host = scmd->device->host;
3386c5f8ce1SJames Bottomley 
339bf816235SKei Tokunaga 	trace_scsi_dispatch_cmd_timeout(scmd);
3401da177e4SLinus Torvalds 	scsi_log_completion(scmd, TIMEOUT_ERROR);
3411da177e4SLinus Torvalds 
34248517eefSWu Bo 	atomic_inc(&scmd->device->iotmo_cnt);
343bb3b621aSRen Mingxin 	if (host->eh_deadline != -1 && !host->last_reset)
344b4562022SHannes Reinecke 		host->last_reset = jiffies;
345b4562022SHannes Reinecke 
346dee7121eSBart Van Assche 	if (host->hostt->eh_timed_out) {
347dee7121eSBart Van Assche 		switch (host->hostt->eh_timed_out(scmd)) {
348dee7121eSBart Van Assche 		case SCSI_EH_DONE:
349dee7121eSBart Van Assche 			return BLK_EH_DONE;
350dee7121eSBart Van Assche 		case SCSI_EH_RESET_TIMER:
351dee7121eSBart Van Assche 			return BLK_EH_RESET_TIMER;
352dee7121eSBart Van Assche 		case SCSI_EH_NOT_HANDLED:
353dee7121eSBart Van Assche 			break;
354dee7121eSBart Van Assche 		}
355dee7121eSBart Van Assche 	}
3566c5f8ce1SJames Bottomley 
357065990bdSKeith Busch 	/*
358dee7121eSBart Van Assche 	 * If scsi_done() has already set SCMD_STATE_COMPLETE, do not modify
359dee7121eSBart Van Assche 	 * *scmd.
360065990bdSKeith Busch 	 */
361f1342709SKeith Busch 	if (test_and_set_bit(SCMD_STATE_COMPLETE, &scmd->state))
362978b7922SBart Van Assche 		return BLK_EH_DONE;
363ec9780e4SWenchao Hao 	atomic_inc(&scmd->device->iodone_cnt);
364a0658632SHannes Reinecke 	if (scsi_abort_command(scmd) != SUCCESS) {
3658922a908SUlrich Obergfell 		set_host_byte(scmd, DID_TIME_OUT);
366a0658632SHannes Reinecke 		scsi_eh_scmd_add(scmd);
3672171b6d0SHannes Reinecke 	}
368242f9dcbSJens Axboe 
369dee7121eSBart Van Assche 	return BLK_EH_DONE;
3701da177e4SLinus Torvalds }
3711da177e4SLinus Torvalds 
3721da177e4SLinus Torvalds /**
3731da177e4SLinus Torvalds  * scsi_block_when_processing_errors - Prevent cmds from being queued.
3741da177e4SLinus Torvalds  * @sdev:	Device on which we are performing recovery.
3751da177e4SLinus Torvalds  *
3761da177e4SLinus Torvalds  * Description:
3771da177e4SLinus Torvalds  *     We block until the host is out of error recovery, and then check to
3781da177e4SLinus Torvalds  *     see whether the host or the device is offline.
3791da177e4SLinus Torvalds  *
3801da177e4SLinus Torvalds  * Return value:
3811da177e4SLinus Torvalds  *     0 when dev was taken offline by error recovery. 1 OK to proceed.
382dc8875e1SRandy Dunlap  */
scsi_block_when_processing_errors(struct scsi_device * sdev)3831da177e4SLinus Torvalds int scsi_block_when_processing_errors(struct scsi_device *sdev)
3841da177e4SLinus Torvalds {
3851da177e4SLinus Torvalds 	int online;
3861da177e4SLinus Torvalds 
387939647eeSJames Bottomley 	wait_event(sdev->host->host_wait, !scsi_host_in_recovery(sdev->host));
3881da177e4SLinus Torvalds 
3891da177e4SLinus Torvalds 	online = scsi_device_online(sdev);
3901da177e4SLinus Torvalds 
3911da177e4SLinus Torvalds 	return online;
3921da177e4SLinus Torvalds }
3931da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_block_when_processing_errors);
3941da177e4SLinus Torvalds 
3951da177e4SLinus Torvalds #ifdef CONFIG_SCSI_LOGGING
3961da177e4SLinus Torvalds /**
3971da177e4SLinus Torvalds  * scsi_eh_prt_fail_stats - Log info on failures.
3981da177e4SLinus Torvalds  * @shost:	scsi host being recovered.
3991da177e4SLinus Torvalds  * @work_q:	Queue of scsi cmds to process.
400dc8875e1SRandy Dunlap  */
scsi_eh_prt_fail_stats(struct Scsi_Host * shost,struct list_head * work_q)4011da177e4SLinus Torvalds static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
4021da177e4SLinus Torvalds 					  struct list_head *work_q)
4031da177e4SLinus Torvalds {
4041da177e4SLinus Torvalds 	struct scsi_cmnd *scmd;
4051da177e4SLinus Torvalds 	struct scsi_device *sdev;
4061da177e4SLinus Torvalds 	int total_failures = 0;
4071da177e4SLinus Torvalds 	int cmd_failed = 0;
4081da177e4SLinus Torvalds 	int cmd_cancel = 0;
4091da177e4SLinus Torvalds 	int devices_failed = 0;
4101da177e4SLinus Torvalds 
4111da177e4SLinus Torvalds 	shost_for_each_device(sdev, shost) {
4121da177e4SLinus Torvalds 		list_for_each_entry(scmd, work_q, eh_entry) {
4131da177e4SLinus Torvalds 			if (scmd->device == sdev) {
4141da177e4SLinus Torvalds 				++total_failures;
415a0658632SHannes Reinecke 				if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED)
4161da177e4SLinus Torvalds 					++cmd_cancel;
4171da177e4SLinus Torvalds 				else
4181da177e4SLinus Torvalds 					++cmd_failed;
4191da177e4SLinus Torvalds 			}
4201da177e4SLinus Torvalds 		}
4211da177e4SLinus Torvalds 
4221da177e4SLinus Torvalds 		if (cmd_cancel || cmd_failed) {
4231da177e4SLinus Torvalds 			SCSI_LOG_ERROR_RECOVERY(3,
424a3a790dcSHannes Reinecke 				shost_printk(KERN_INFO, shost,
4259ccfc756SJames Bottomley 					    "%s: cmds failed: %d, cancel: %d\n",
426cadbd4a5SHarvey Harrison 					    __func__, cmd_failed,
4279ccfc756SJames Bottomley 					    cmd_cancel));
4281da177e4SLinus Torvalds 			cmd_cancel = 0;
4291da177e4SLinus Torvalds 			cmd_failed = 0;
4301da177e4SLinus Torvalds 			++devices_failed;
4311da177e4SLinus Torvalds 		}
4321da177e4SLinus Torvalds 	}
4331da177e4SLinus Torvalds 
43491921e01SHannes Reinecke 	SCSI_LOG_ERROR_RECOVERY(2, shost_printk(KERN_INFO, shost,
43591921e01SHannes Reinecke 				   "Total of %d commands on %d"
4361da177e4SLinus Torvalds 				   " devices require eh work\n",
4371da177e4SLinus Torvalds 				   total_failures, devices_failed));
4381da177e4SLinus Torvalds }
4391da177e4SLinus Torvalds #endif
4401da177e4SLinus Torvalds 
4411da177e4SLinus Torvalds  /**
442279afdfeSEwan D. Milne  * scsi_report_lun_change - Set flag on all *other* devices on the same target
443279afdfeSEwan D. Milne  *                          to indicate that a UNIT ATTENTION is expected.
444279afdfeSEwan D. Milne  * @sdev:	Device reporting the UNIT ATTENTION
445279afdfeSEwan D. Milne  */
scsi_report_lun_change(struct scsi_device * sdev)446279afdfeSEwan D. Milne static void scsi_report_lun_change(struct scsi_device *sdev)
447279afdfeSEwan D. Milne {
448279afdfeSEwan D. Milne 	sdev->sdev_target->expecting_lun_change = 1;
449279afdfeSEwan D. Milne }
450279afdfeSEwan D. Milne 
451279afdfeSEwan D. Milne /**
452279afdfeSEwan D. Milne  * scsi_report_sense - Examine scsi sense information and log messages for
453279afdfeSEwan D. Milne  *		       certain conditions, also issue uevents for some of them.
454279afdfeSEwan D. Milne  * @sdev:	Device reporting the sense code
455279afdfeSEwan D. Milne  * @sshdr:	sshdr to be examined
456279afdfeSEwan D. Milne  */
scsi_report_sense(struct scsi_device * sdev,struct scsi_sense_hdr * sshdr)457279afdfeSEwan D. Milne static void scsi_report_sense(struct scsi_device *sdev,
458279afdfeSEwan D. Milne 			      struct scsi_sense_hdr *sshdr)
459279afdfeSEwan D. Milne {
460279afdfeSEwan D. Milne 	enum scsi_device_event evt_type = SDEV_EVT_MAXBITS;	/* i.e. none */
461279afdfeSEwan D. Milne 
462279afdfeSEwan D. Milne 	if (sshdr->sense_key == UNIT_ATTENTION) {
463279afdfeSEwan D. Milne 		if (sshdr->asc == 0x3f && sshdr->ascq == 0x03) {
464279afdfeSEwan D. Milne 			evt_type = SDEV_EVT_INQUIRY_CHANGE_REPORTED;
465279afdfeSEwan D. Milne 			sdev_printk(KERN_WARNING, sdev,
466279afdfeSEwan D. Milne 				    "Inquiry data has changed");
467279afdfeSEwan D. Milne 		} else if (sshdr->asc == 0x3f && sshdr->ascq == 0x0e) {
468279afdfeSEwan D. Milne 			evt_type = SDEV_EVT_LUN_CHANGE_REPORTED;
469279afdfeSEwan D. Milne 			scsi_report_lun_change(sdev);
470279afdfeSEwan D. Milne 			sdev_printk(KERN_WARNING, sdev,
471279afdfeSEwan D. Milne 				    "LUN assignments on this target have "
472279afdfeSEwan D. Milne 				    "changed. The Linux SCSI layer does not "
473279afdfeSEwan D. Milne 				    "automatically remap LUN assignments.\n");
474279afdfeSEwan D. Milne 		} else if (sshdr->asc == 0x3f)
475279afdfeSEwan D. Milne 			sdev_printk(KERN_WARNING, sdev,
476a2417db3SLi Zhijian 				    "Operating parameters on this target have "
477279afdfeSEwan D. Milne 				    "changed. The Linux SCSI layer does not "
478279afdfeSEwan D. Milne 				    "automatically adjust these parameters.\n");
479279afdfeSEwan D. Milne 
480279afdfeSEwan D. Milne 		if (sshdr->asc == 0x38 && sshdr->ascq == 0x07) {
481279afdfeSEwan D. Milne 			evt_type = SDEV_EVT_SOFT_THRESHOLD_REACHED_REPORTED;
482279afdfeSEwan D. Milne 			sdev_printk(KERN_WARNING, sdev,
483279afdfeSEwan D. Milne 				    "Warning! Received an indication that the "
484279afdfeSEwan D. Milne 				    "LUN reached a thin provisioning soft "
485279afdfeSEwan D. Milne 				    "threshold.\n");
486279afdfeSEwan D. Milne 		}
487279afdfeSEwan D. Milne 
488cf3431bbSHannes Reinecke 		if (sshdr->asc == 0x29) {
489cf3431bbSHannes Reinecke 			evt_type = SDEV_EVT_POWER_ON_RESET_OCCURRED;
490af4edb1dSAdrian Hunter 			/*
491af4edb1dSAdrian Hunter 			 * Do not print message if it is an expected side-effect
492af4edb1dSAdrian Hunter 			 * of runtime PM.
493af4edb1dSAdrian Hunter 			 */
494af4edb1dSAdrian Hunter 			if (!sdev->silence_suspend)
495cf3431bbSHannes Reinecke 				sdev_printk(KERN_WARNING, sdev,
496cf3431bbSHannes Reinecke 					    "Power-on or device reset occurred\n");
497cf3431bbSHannes Reinecke 		}
498cf3431bbSHannes Reinecke 
499279afdfeSEwan D. Milne 		if (sshdr->asc == 0x2a && sshdr->ascq == 0x01) {
500279afdfeSEwan D. Milne 			evt_type = SDEV_EVT_MODE_PARAMETER_CHANGE_REPORTED;
501279afdfeSEwan D. Milne 			sdev_printk(KERN_WARNING, sdev,
502279afdfeSEwan D. Milne 				    "Mode parameters changed");
50314c3e677SHannes Reinecke 		} else if (sshdr->asc == 0x2a && sshdr->ascq == 0x06) {
50414c3e677SHannes Reinecke 			evt_type = SDEV_EVT_ALUA_STATE_CHANGE_REPORTED;
50514c3e677SHannes Reinecke 			sdev_printk(KERN_WARNING, sdev,
50614c3e677SHannes Reinecke 				    "Asymmetric access state changed");
507279afdfeSEwan D. Milne 		} else if (sshdr->asc == 0x2a && sshdr->ascq == 0x09) {
508279afdfeSEwan D. Milne 			evt_type = SDEV_EVT_CAPACITY_CHANGE_REPORTED;
509279afdfeSEwan D. Milne 			sdev_printk(KERN_WARNING, sdev,
510279afdfeSEwan D. Milne 				    "Capacity data has changed");
511279afdfeSEwan D. Milne 		} else if (sshdr->asc == 0x2a)
512279afdfeSEwan D. Milne 			sdev_printk(KERN_WARNING, sdev,
513279afdfeSEwan D. Milne 				    "Parameters changed");
514279afdfeSEwan D. Milne 	}
515279afdfeSEwan D. Milne 
516279afdfeSEwan D. Milne 	if (evt_type != SDEV_EVT_MAXBITS) {
517279afdfeSEwan D. Milne 		set_bit(evt_type, sdev->pending_events);
518279afdfeSEwan D. Milne 		schedule_work(&sdev->event_work);
519279afdfeSEwan D. Milne 	}
520279afdfeSEwan D. Milne }
521279afdfeSEwan D. Milne 
set_scsi_ml_byte(struct scsi_cmnd * cmd,u8 status)52236ebf1e2SMike Christie static inline void set_scsi_ml_byte(struct scsi_cmnd *cmd, u8 status)
52336ebf1e2SMike Christie {
52436ebf1e2SMike Christie 	cmd->result = (cmd->result & 0xffff00ff) | (status << 8);
52536ebf1e2SMike Christie }
52636ebf1e2SMike Christie 
527279afdfeSEwan D. Milne /**
5281da177e4SLinus Torvalds  * scsi_check_sense - Examine scsi cmd sense
5291da177e4SLinus Torvalds  * @scmd:	Cmd to have sense checked.
5301da177e4SLinus Torvalds  *
5311da177e4SLinus Torvalds  * Return value:
53287f14e65SHannes Reinecke  *	SUCCESS or FAILED or NEEDS_RETRY or ADD_TO_MLQUEUE
5331da177e4SLinus Torvalds  *
5341da177e4SLinus Torvalds  * Notes:
5351da177e4SLinus Torvalds  *	When a deferred error is detected the current command has
5361da177e4SLinus Torvalds  *	not been executed and needs retrying.
537dc8875e1SRandy Dunlap  */
scsi_check_sense(struct scsi_cmnd * scmd)538b8e162f9SBart Van Assche enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd)
5391da177e4SLinus Torvalds {
540390e2d1aSNiklas Cassel 	struct request *req = scsi_cmd_to_rq(scmd);
541a6a8d9f8SChandra Seetharaman 	struct scsi_device *sdev = scmd->device;
5421da177e4SLinus Torvalds 	struct scsi_sense_hdr sshdr;
5431da177e4SLinus Torvalds 
5441da177e4SLinus Torvalds 	if (! scsi_command_normalize_sense(scmd, &sshdr))
5451da177e4SLinus Torvalds 		return FAILED;	/* no valid sense data */
5461da177e4SLinus Torvalds 
547279afdfeSEwan D. Milne 	scsi_report_sense(sdev, &sshdr);
548279afdfeSEwan D. Milne 
5491da177e4SLinus Torvalds 	if (scsi_sense_is_deferred(&sshdr))
5501da177e4SLinus Torvalds 		return NEEDS_RETRY;
5511da177e4SLinus Torvalds 
552ee14c674SChristoph Hellwig 	if (sdev->handler && sdev->handler->check_sense) {
553b8e162f9SBart Van Assche 		enum scsi_disposition rc;
554a6a8d9f8SChandra Seetharaman 
555ee14c674SChristoph Hellwig 		rc = sdev->handler->check_sense(sdev, &sshdr);
556a6a8d9f8SChandra Seetharaman 		if (rc != SCSI_RETURN_NOT_HANDLED)
557a6a8d9f8SChandra Seetharaman 			return rc;
558a6a8d9f8SChandra Seetharaman 		/* handler does not care. Drop down to default handling */
559a6a8d9f8SChandra Seetharaman 	}
560a6a8d9f8SChandra Seetharaman 
561bf23e619SBart Van Assche 	if (scmd->cmnd[0] == TEST_UNIT_READY &&
562bf23e619SBart Van Assche 	    scmd->submitter != SUBMITTED_BY_SCSI_ERROR_HANDLER)
563e925cc43SChristoph Hellwig 		/*
564e925cc43SChristoph Hellwig 		 * nasty: for mid-layer issued TURs, we need to return the
565e925cc43SChristoph Hellwig 		 * actual sense data without any recovery attempt.  For eh
566e925cc43SChristoph Hellwig 		 * issued ones, we need to try to recover and interpret
567e925cc43SChristoph Hellwig 		 */
568e925cc43SChristoph Hellwig 		return SUCCESS;
569e925cc43SChristoph Hellwig 
5701da177e4SLinus Torvalds 	/*
5711da177e4SLinus Torvalds 	 * Previous logic looked for FILEMARK, EOM or ILI which are
5721da177e4SLinus Torvalds 	 * mainly associated with tapes and returned SUCCESS.
5731da177e4SLinus Torvalds 	 */
5741da177e4SLinus Torvalds 	if (sshdr.response_code == 0x70) {
5751da177e4SLinus Torvalds 		/* fixed format */
5761da177e4SLinus Torvalds 		if (scmd->sense_buffer[2] & 0xe0)
5771da177e4SLinus Torvalds 			return SUCCESS;
5781da177e4SLinus Torvalds 	} else {
5791da177e4SLinus Torvalds 		/*
5801da177e4SLinus Torvalds 		 * descriptor format: look for "stream commands sense data
5811da177e4SLinus Torvalds 		 * descriptor" (see SSC-3). Assume single sense data
5821da177e4SLinus Torvalds 		 * descriptor. Ignore ILI from SBC-2 READ LONG and WRITE LONG.
5831da177e4SLinus Torvalds 		 */
5841da177e4SLinus Torvalds 		if ((sshdr.additional_length > 3) &&
5851da177e4SLinus Torvalds 		    (scmd->sense_buffer[8] == 0x4) &&
5861da177e4SLinus Torvalds 		    (scmd->sense_buffer[11] & 0xe0))
5871da177e4SLinus Torvalds 			return SUCCESS;
5881da177e4SLinus Torvalds 	}
5891da177e4SLinus Torvalds 
5901da177e4SLinus Torvalds 	switch (sshdr.sense_key) {
5911da177e4SLinus Torvalds 	case NO_SENSE:
5921da177e4SLinus Torvalds 		return SUCCESS;
5931da177e4SLinus Torvalds 	case RECOVERED_ERROR:
5941da177e4SLinus Torvalds 		return /* soft_error */ SUCCESS;
5951da177e4SLinus Torvalds 
5961da177e4SLinus Torvalds 	case ABORTED_COMMAND:
597511e44f4SMartin K. Petersen 		if (sshdr.asc == 0x10) /* DIF */
598511e44f4SMartin K. Petersen 			return SUCCESS;
599511e44f4SMartin K. Petersen 
600390e2d1aSNiklas Cassel 		/*
601390e2d1aSNiklas Cassel 		 * Check aborts due to command duration limit policy:
602390e2d1aSNiklas Cassel 		 * ABORTED COMMAND additional sense code with the
603390e2d1aSNiklas Cassel 		 * COMMAND TIMEOUT BEFORE PROCESSING or
604390e2d1aSNiklas Cassel 		 * COMMAND TIMEOUT DURING PROCESSING or
605390e2d1aSNiklas Cassel 		 * COMMAND TIMEOUT DURING PROCESSING DUE TO ERROR RECOVERY
606390e2d1aSNiklas Cassel 		 * additional sense code qualifiers.
607390e2d1aSNiklas Cassel 		 */
608390e2d1aSNiklas Cassel 		if (sshdr.asc == 0x2e &&
609390e2d1aSNiklas Cassel 		    sshdr.ascq >= 0x01 && sshdr.ascq <= 0x03) {
610390e2d1aSNiklas Cassel 			set_scsi_ml_byte(scmd, SCSIML_STAT_DL_TIMEOUT);
611390e2d1aSNiklas Cassel 			req->cmd_flags |= REQ_FAILFAST_DEV;
612390e2d1aSNiklas Cassel 			req->rq_flags |= RQF_QUIET;
613390e2d1aSNiklas Cassel 			return SUCCESS;
614390e2d1aSNiklas Cassel 		}
615390e2d1aSNiklas Cassel 
61629cfc2abSMartin Wilck 		if (sshdr.asc == 0x44 && sdev->sdev_bflags & BLIST_RETRY_ITF)
61729cfc2abSMartin Wilck 			return ADD_TO_MLQUEUE;
618c3606520SMartin Wilck 		if (sshdr.asc == 0xc1 && sshdr.ascq == 0x01 &&
619c3606520SMartin Wilck 		    sdev->sdev_bflags & BLIST_RETRY_ASC_C1)
620c3606520SMartin Wilck 			return ADD_TO_MLQUEUE;
62129cfc2abSMartin Wilck 
6221da177e4SLinus Torvalds 		return NEEDS_RETRY;
6231da177e4SLinus Torvalds 	case NOT_READY:
6241da177e4SLinus Torvalds 	case UNIT_ATTENTION:
6251da177e4SLinus Torvalds 		/*
6261da177e4SLinus Torvalds 		 * if we are expecting a cc/ua because of a bus reset that we
6271da177e4SLinus Torvalds 		 * performed, treat this just as a retry.  otherwise this is
6281da177e4SLinus Torvalds 		 * information that we should pass up to the upper-level driver
6291da177e4SLinus Torvalds 		 * so that we can deal with it there.
6301da177e4SLinus Torvalds 		 */
6311da177e4SLinus Torvalds 		if (scmd->device->expecting_cc_ua) {
632dfcf7775STARUISI Hiroaki 			/*
633dfcf7775STARUISI Hiroaki 			 * Because some device does not queue unit
634dfcf7775STARUISI Hiroaki 			 * attentions correctly, we carefully check
635dfcf7775STARUISI Hiroaki 			 * additional sense code and qualifier so as
636dfcf7775STARUISI Hiroaki 			 * not to squash media change unit attention.
637dfcf7775STARUISI Hiroaki 			 */
638dfcf7775STARUISI Hiroaki 			if (sshdr.asc != 0x28 || sshdr.ascq != 0x00) {
6391da177e4SLinus Torvalds 				scmd->device->expecting_cc_ua = 0;
6401da177e4SLinus Torvalds 				return NEEDS_RETRY;
6411da177e4SLinus Torvalds 			}
642dfcf7775STARUISI Hiroaki 		}
6431da177e4SLinus Torvalds 		/*
644279afdfeSEwan D. Milne 		 * we might also expect a cc/ua if another LUN on the target
645279afdfeSEwan D. Milne 		 * reported a UA with an ASC/ASCQ of 3F 0E -
646279afdfeSEwan D. Milne 		 * REPORTED LUNS DATA HAS CHANGED.
647279afdfeSEwan D. Milne 		 */
648279afdfeSEwan D. Milne 		if (scmd->device->sdev_target->expecting_lun_change &&
649279afdfeSEwan D. Milne 		    sshdr.asc == 0x3f && sshdr.ascq == 0x0e)
650279afdfeSEwan D. Milne 			return NEEDS_RETRY;
651279afdfeSEwan D. Milne 		/*
6521da177e4SLinus Torvalds 		 * if the device is in the process of becoming ready, we
6531da177e4SLinus Torvalds 		 * should retry.
6541da177e4SLinus Torvalds 		 */
6551da177e4SLinus Torvalds 		if ((sshdr.asc == 0x04) && (sshdr.ascq == 0x01))
6561da177e4SLinus Torvalds 			return NEEDS_RETRY;
6571da177e4SLinus Torvalds 		/*
6581da177e4SLinus Torvalds 		 * if the device is not started, we need to wake
6591da177e4SLinus Torvalds 		 * the error handler to start the motor
6601da177e4SLinus Torvalds 		 */
6611da177e4SLinus Torvalds 		if (scmd->device->allow_restart &&
6621da177e4SLinus Torvalds 		    (sshdr.asc == 0x04) && (sshdr.ascq == 0x02))
6631da177e4SLinus Torvalds 			return FAILED;
66477a42297SJames Bottomley 		/*
66502e031cbSChristoph Hellwig 		 * Pass the UA upwards for a determination in the completion
66602e031cbSChristoph Hellwig 		 * functions.
66777a42297SJames Bottomley 		 */
6681da177e4SLinus Torvalds 		return SUCCESS;
6691da177e4SLinus Torvalds 
67063583ccaSHannes Reinecke 		/* these are not supported */
671a9d6ceb8SHannes Reinecke 	case DATA_PROTECT:
672a9d6ceb8SHannes Reinecke 		if (sshdr.asc == 0x27 && sshdr.ascq == 0x07) {
673a9d6ceb8SHannes Reinecke 			/* Thin provisioning hard threshold reached */
6747dfaae6aSMike Christie 			set_scsi_ml_byte(scmd, SCSIML_STAT_NOSPC);
675a9d6ceb8SHannes Reinecke 			return SUCCESS;
676a9d6ceb8SHannes Reinecke 		}
677df561f66SGustavo A. R. Silva 		fallthrough;
6781da177e4SLinus Torvalds 	case COPY_ABORTED:
6791da177e4SLinus Torvalds 	case VOLUME_OVERFLOW:
6801da177e4SLinus Torvalds 	case MISCOMPARE:
68163583ccaSHannes Reinecke 	case BLANK_CHECK:
6827dfaae6aSMike Christie 		set_scsi_ml_byte(scmd, SCSIML_STAT_TGT_FAILURE);
68387f14e65SHannes Reinecke 		return SUCCESS;
6841da177e4SLinus Torvalds 
6851da177e4SLinus Torvalds 	case MEDIUM_ERROR:
686fd1b494dSLuben Tuikov 		if (sshdr.asc == 0x11 || /* UNRECOVERED READ ERR */
687fd1b494dSLuben Tuikov 		    sshdr.asc == 0x13 || /* AMNF DATA FIELD */
688fd1b494dSLuben Tuikov 		    sshdr.asc == 0x14) { /* RECORD NOT FOUND */
6897dfaae6aSMike Christie 			set_scsi_ml_byte(scmd, SCSIML_STAT_MED_ERROR);
69087f14e65SHannes Reinecke 			return SUCCESS;
691fd1b494dSLuben Tuikov 		}
6921da177e4SLinus Torvalds 		return NEEDS_RETRY;
6931da177e4SLinus Torvalds 
6941da177e4SLinus Torvalds 	case HARDWARE_ERROR:
6951da177e4SLinus Torvalds 		if (scmd->device->retry_hwerror)
696bb0003c1SMike Anderson 			return ADD_TO_MLQUEUE;
6971da177e4SLinus Torvalds 		else
6987dfaae6aSMike Christie 			set_scsi_ml_byte(scmd, SCSIML_STAT_TGT_FAILURE);
699df561f66SGustavo A. R. Silva 		fallthrough;
7001da177e4SLinus Torvalds 
7011da177e4SLinus Torvalds 	case ILLEGAL_REQUEST:
70247ac56dbSMike Snitzer 		if (sshdr.asc == 0x20 || /* Invalid command operation code */
70347ac56dbSMike Snitzer 		    sshdr.asc == 0x21 || /* Logical block address out of range */
704a8bbb2abSHannes Reinecke 		    sshdr.asc == 0x22 || /* Invalid function */
70547ac56dbSMike Snitzer 		    sshdr.asc == 0x24 || /* Invalid field in cdb */
706d0b7a909SMartin Wilck 		    sshdr.asc == 0x26 || /* Parameter value invalid */
707d0b7a909SMartin Wilck 		    sshdr.asc == 0x27) { /* Write protected */
7087dfaae6aSMike Christie 			set_scsi_ml_byte(scmd, SCSIML_STAT_TGT_FAILURE);
70947ac56dbSMike Snitzer 		}
71047ac56dbSMike Snitzer 		return SUCCESS;
71147ac56dbSMike Snitzer 
712390e2d1aSNiklas Cassel 	case COMPLETED:
713390e2d1aSNiklas Cassel 		if (sshdr.asc == 0x55 && sshdr.ascq == 0x0a) {
714390e2d1aSNiklas Cassel 			set_scsi_ml_byte(scmd, SCSIML_STAT_DL_TIMEOUT);
715390e2d1aSNiklas Cassel 			req->cmd_flags |= REQ_FAILFAST_DEV;
716390e2d1aSNiklas Cassel 			req->rq_flags |= RQF_QUIET;
717390e2d1aSNiklas Cassel 		}
718390e2d1aSNiklas Cassel 		return SUCCESS;
719390e2d1aSNiklas Cassel 
7201da177e4SLinus Torvalds 	default:
7211da177e4SLinus Torvalds 		return SUCCESS;
7221da177e4SLinus Torvalds 	}
7231da177e4SLinus Torvalds }
7243852e373SHannes Reinecke EXPORT_SYMBOL_GPL(scsi_check_sense);
7251da177e4SLinus Torvalds 
scsi_handle_queue_ramp_up(struct scsi_device * sdev)7264a84067dSVasu Dev static void scsi_handle_queue_ramp_up(struct scsi_device *sdev)
7274a84067dSVasu Dev {
72831435de9SBart Van Assche 	const struct scsi_host_template *sht = sdev->host->hostt;
7294a84067dSVasu Dev 	struct scsi_device *tmp_sdev;
7304a84067dSVasu Dev 
731c40ecc12SChristoph Hellwig 	if (!sht->track_queue_depth ||
7324a84067dSVasu Dev 	    sdev->queue_depth >= sdev->max_queue_depth)
7334a84067dSVasu Dev 		return;
7344a84067dSVasu Dev 
7354a84067dSVasu Dev 	if (time_before(jiffies,
7364a84067dSVasu Dev 	    sdev->last_queue_ramp_up + sdev->queue_ramp_up_period))
7374a84067dSVasu Dev 		return;
7384a84067dSVasu Dev 
7394a84067dSVasu Dev 	if (time_before(jiffies,
7404a84067dSVasu Dev 	    sdev->last_queue_full_time + sdev->queue_ramp_up_period))
7414a84067dSVasu Dev 		return;
7424a84067dSVasu Dev 
7434a84067dSVasu Dev 	/*
7444a84067dSVasu Dev 	 * Walk all devices of a target and do
7454a84067dSVasu Dev 	 * ramp up on them.
7464a84067dSVasu Dev 	 */
7474a84067dSVasu Dev 	shost_for_each_device(tmp_sdev, sdev->host) {
7484a84067dSVasu Dev 		if (tmp_sdev->channel != sdev->channel ||
7494a84067dSVasu Dev 		    tmp_sdev->id != sdev->id ||
7504a84067dSVasu Dev 		    tmp_sdev->queue_depth == sdev->max_queue_depth)
7514a84067dSVasu Dev 			continue;
752c40ecc12SChristoph Hellwig 
753db5ed4dfSChristoph Hellwig 		scsi_change_queue_depth(tmp_sdev, tmp_sdev->queue_depth + 1);
7544a84067dSVasu Dev 		sdev->last_queue_ramp_up = jiffies;
7554a84067dSVasu Dev 	}
7564a84067dSVasu Dev }
7574a84067dSVasu Dev 
scsi_handle_queue_full(struct scsi_device * sdev)75842a6a918SMike Christie static void scsi_handle_queue_full(struct scsi_device *sdev)
75942a6a918SMike Christie {
76031435de9SBart Van Assche 	const struct scsi_host_template *sht = sdev->host->hostt;
76142a6a918SMike Christie 	struct scsi_device *tmp_sdev;
76242a6a918SMike Christie 
763c40ecc12SChristoph Hellwig 	if (!sht->track_queue_depth)
76442a6a918SMike Christie 		return;
76542a6a918SMike Christie 
76642a6a918SMike Christie 	shost_for_each_device(tmp_sdev, sdev->host) {
76742a6a918SMike Christie 		if (tmp_sdev->channel != sdev->channel ||
76842a6a918SMike Christie 		    tmp_sdev->id != sdev->id)
76942a6a918SMike Christie 			continue;
77042a6a918SMike Christie 		/*
77142a6a918SMike Christie 		 * We do not know the number of commands that were at
77242a6a918SMike Christie 		 * the device when we got the queue full so we start
77342a6a918SMike Christie 		 * from the highest possible value and work our way down.
77442a6a918SMike Christie 		 */
775c40ecc12SChristoph Hellwig 		scsi_track_queue_full(tmp_sdev, tmp_sdev->queue_depth - 1);
77642a6a918SMike Christie 	}
77742a6a918SMike Christie }
77842a6a918SMike Christie 
7791da177e4SLinus Torvalds /**
7801da177e4SLinus Torvalds  * scsi_eh_completed_normally - Disposition a eh cmd on return from LLD.
7811da177e4SLinus Torvalds  * @scmd:	SCSI cmd to examine.
7821da177e4SLinus Torvalds  *
7831da177e4SLinus Torvalds  * Notes:
7841da177e4SLinus Torvalds  *    This is *only* called when we are examining the status of commands
7851da177e4SLinus Torvalds  *    queued during error recovery.  the main difference here is that we
7861da177e4SLinus Torvalds  *    don't allow for the possibility of retries here, and we are a lot
7871da177e4SLinus Torvalds  *    more restrictive about what we consider acceptable.
788dc8875e1SRandy Dunlap  */
scsi_eh_completed_normally(struct scsi_cmnd * scmd)789b8e162f9SBart Van Assche static enum scsi_disposition scsi_eh_completed_normally(struct scsi_cmnd *scmd)
7901da177e4SLinus Torvalds {
7911da177e4SLinus Torvalds 	/*
7921da177e4SLinus Torvalds 	 * first check the host byte, to see if there is anything in there
7931da177e4SLinus Torvalds 	 * that would indicate what we need to do.
7941da177e4SLinus Torvalds 	 */
7951da177e4SLinus Torvalds 	if (host_byte(scmd->result) == DID_RESET) {
7961da177e4SLinus Torvalds 		/*
7971da177e4SLinus Torvalds 		 * rats.  we are already in the error handler, so we now
7981da177e4SLinus Torvalds 		 * get to try and figure out what to do next.  if the sense
7991da177e4SLinus Torvalds 		 * is valid, we have a pretty good idea of what to do.
8001da177e4SLinus Torvalds 		 * if not, we mark it as FAILED.
8011da177e4SLinus Torvalds 		 */
8021da177e4SLinus Torvalds 		return scsi_check_sense(scmd);
8031da177e4SLinus Torvalds 	}
8041da177e4SLinus Torvalds 	if (host_byte(scmd->result) != DID_OK)
8051da177e4SLinus Torvalds 		return FAILED;
8061da177e4SLinus Torvalds 
8071da177e4SLinus Torvalds 	/*
8081da177e4SLinus Torvalds 	 * now, check the status byte to see if this indicates
8091da177e4SLinus Torvalds 	 * anything special.
8101da177e4SLinus Torvalds 	 */
8113d45cefcSHannes Reinecke 	switch (get_status_byte(scmd)) {
8123d45cefcSHannes Reinecke 	case SAM_STAT_GOOD:
8134a84067dSVasu Dev 		scsi_handle_queue_ramp_up(scmd->device);
814390e2d1aSNiklas Cassel 		if (scmd->sense_buffer && SCSI_SENSE_VALID(scmd))
815390e2d1aSNiklas Cassel 			/*
816390e2d1aSNiklas Cassel 			 * If we have sense data, call scsi_check_sense() in
817390e2d1aSNiklas Cassel 			 * order to set the correct SCSI ML byte (if any).
818390e2d1aSNiklas Cassel 			 * No point in checking the return value, since the
819390e2d1aSNiklas Cassel 			 * command has already completed successfully.
820390e2d1aSNiklas Cassel 			 */
821390e2d1aSNiklas Cassel 			scsi_check_sense(scmd);
822df561f66SGustavo A. R. Silva 		fallthrough;
8233d45cefcSHannes Reinecke 	case SAM_STAT_COMMAND_TERMINATED:
8241da177e4SLinus Torvalds 		return SUCCESS;
8253d45cefcSHannes Reinecke 	case SAM_STAT_CHECK_CONDITION:
8261da177e4SLinus Torvalds 		return scsi_check_sense(scmd);
8273d45cefcSHannes Reinecke 	case SAM_STAT_CONDITION_MET:
8283d45cefcSHannes Reinecke 	case SAM_STAT_INTERMEDIATE:
8293d45cefcSHannes Reinecke 	case SAM_STAT_INTERMEDIATE_CONDITION_MET:
8301da177e4SLinus Torvalds 		/*
8311da177e4SLinus Torvalds 		 * who knows?  FIXME(eric)
8321da177e4SLinus Torvalds 		 */
8331da177e4SLinus Torvalds 		return SUCCESS;
8343d45cefcSHannes Reinecke 	case SAM_STAT_RESERVATION_CONFLICT:
83567110dfdSJames Bottomley 		if (scmd->cmnd[0] == TEST_UNIT_READY)
83667110dfdSJames Bottomley 			/* it is a success, we probed the device and
83767110dfdSJames Bottomley 			 * found it */
8385f91bb05SMichael Reed 			return SUCCESS;
83967110dfdSJames Bottomley 		/* otherwise, we failed to send the command */
84067110dfdSJames Bottomley 		return FAILED;
8413d45cefcSHannes Reinecke 	case SAM_STAT_TASK_SET_FULL:
84242a6a918SMike Christie 		scsi_handle_queue_full(scmd->device);
843df561f66SGustavo A. R. Silva 		fallthrough;
8443d45cefcSHannes Reinecke 	case SAM_STAT_BUSY:
8453eb3a928SHannes Reinecke 		return NEEDS_RETRY;
8461da177e4SLinus Torvalds 	default:
8471da177e4SLinus Torvalds 		return FAILED;
8481da177e4SLinus Torvalds 	}
8491da177e4SLinus Torvalds 	return FAILED;
8501da177e4SLinus Torvalds }
8511da177e4SLinus Torvalds 
8521da177e4SLinus Torvalds /**
8531da177e4SLinus Torvalds  * scsi_eh_done - Completion function for error handling.
8541da177e4SLinus Torvalds  * @scmd:	Cmd that is done.
855dc8875e1SRandy Dunlap  */
scsi_eh_done(struct scsi_cmnd * scmd)856bf23e619SBart Van Assche void scsi_eh_done(struct scsi_cmnd *scmd)
8571da177e4SLinus Torvalds {
85885631672SMichael Reed 	struct completion *eh_action;
85985631672SMichael Reed 
86091921e01SHannes Reinecke 	SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
861470613b4SHannes Reinecke 			"%s result: %x\n", __func__, scmd->result));
86285631672SMichael Reed 
86385631672SMichael Reed 	eh_action = scmd->device->host->eh_action;
86485631672SMichael Reed 	if (eh_action)
86585631672SMichael Reed 		complete(eh_action);
8661da177e4SLinus Torvalds }
8671da177e4SLinus Torvalds 
8681da177e4SLinus Torvalds /**
869292148f8SBrian King  * scsi_try_host_reset - ask host adapter to reset itself
870c2b3ebd0SGeert Uytterhoeven  * @scmd:	SCSI cmd to send host reset.
871dc8875e1SRandy Dunlap  */
scsi_try_host_reset(struct scsi_cmnd * scmd)872b8e162f9SBart Van Assche static enum scsi_disposition scsi_try_host_reset(struct scsi_cmnd *scmd)
873292148f8SBrian King {
874292148f8SBrian King 	unsigned long flags;
875b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
8760bf8c869SJesper Juhl 	struct Scsi_Host *host = scmd->device->host;
87731435de9SBart Van Assche 	const struct scsi_host_template *hostt = host->hostt;
878292148f8SBrian King 
87991921e01SHannes Reinecke 	SCSI_LOG_ERROR_RECOVERY(3,
88091921e01SHannes Reinecke 		shost_printk(KERN_INFO, host, "Snd Host RST\n"));
881292148f8SBrian King 
8820bf8c869SJesper Juhl 	if (!hostt->eh_host_reset_handler)
883292148f8SBrian King 		return FAILED;
884292148f8SBrian King 
8850bf8c869SJesper Juhl 	rtn = hostt->eh_host_reset_handler(scmd);
886292148f8SBrian King 
887292148f8SBrian King 	if (rtn == SUCCESS) {
8880bf8c869SJesper Juhl 		if (!hostt->skip_settle_delay)
889292148f8SBrian King 			ssleep(HOST_RESET_SETTLE_TIME);
8900bf8c869SJesper Juhl 		spin_lock_irqsave(host->host_lock, flags);
8910bf8c869SJesper Juhl 		scsi_report_bus_reset(host, scmd_channel(scmd));
8920bf8c869SJesper Juhl 		spin_unlock_irqrestore(host->host_lock, flags);
893292148f8SBrian King 	}
894292148f8SBrian King 
895292148f8SBrian King 	return rtn;
896292148f8SBrian King }
897292148f8SBrian King 
898292148f8SBrian King /**
899292148f8SBrian King  * scsi_try_bus_reset - ask host to perform a bus reset
900292148f8SBrian King  * @scmd:	SCSI cmd to send bus reset.
901dc8875e1SRandy Dunlap  */
scsi_try_bus_reset(struct scsi_cmnd * scmd)902b8e162f9SBart Van Assche static enum scsi_disposition scsi_try_bus_reset(struct scsi_cmnd *scmd)
903292148f8SBrian King {
904292148f8SBrian King 	unsigned long flags;
905b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
9060bf8c869SJesper Juhl 	struct Scsi_Host *host = scmd->device->host;
90731435de9SBart Van Assche 	const struct scsi_host_template *hostt = host->hostt;
908292148f8SBrian King 
90991921e01SHannes Reinecke 	SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
91091921e01SHannes Reinecke 		"%s: Snd Bus RST\n", __func__));
911292148f8SBrian King 
9120bf8c869SJesper Juhl 	if (!hostt->eh_bus_reset_handler)
913292148f8SBrian King 		return FAILED;
914292148f8SBrian King 
9150bf8c869SJesper Juhl 	rtn = hostt->eh_bus_reset_handler(scmd);
916292148f8SBrian King 
917292148f8SBrian King 	if (rtn == SUCCESS) {
9180bf8c869SJesper Juhl 		if (!hostt->skip_settle_delay)
919292148f8SBrian King 			ssleep(BUS_RESET_SETTLE_TIME);
9200bf8c869SJesper Juhl 		spin_lock_irqsave(host->host_lock, flags);
9210bf8c869SJesper Juhl 		scsi_report_bus_reset(host, scmd_channel(scmd));
9220bf8c869SJesper Juhl 		spin_unlock_irqrestore(host->host_lock, flags);
923292148f8SBrian King 	}
924292148f8SBrian King 
925292148f8SBrian King 	return rtn;
926292148f8SBrian King }
927292148f8SBrian King 
__scsi_report_device_reset(struct scsi_device * sdev,void * data)92830bd7df8SMike Christie static void __scsi_report_device_reset(struct scsi_device *sdev, void *data)
92930bd7df8SMike Christie {
93030bd7df8SMike Christie 	sdev->was_reset = 1;
93130bd7df8SMike Christie 	sdev->expecting_cc_ua = 1;
93230bd7df8SMike Christie }
93330bd7df8SMike Christie 
93430bd7df8SMike Christie /**
93530bd7df8SMike Christie  * scsi_try_target_reset - Ask host to perform a target reset
93630bd7df8SMike Christie  * @scmd:	SCSI cmd used to send a target reset
93730bd7df8SMike Christie  *
93830bd7df8SMike Christie  * Notes:
93930bd7df8SMike Christie  *    There is no timeout for this operation.  if this operation is
94030bd7df8SMike Christie  *    unreliable for a given host, then the host itself needs to put a
94130bd7df8SMike Christie  *    timer on it, and set the host back to a consistent state prior to
94230bd7df8SMike Christie  *    returning.
94330bd7df8SMike Christie  */
scsi_try_target_reset(struct scsi_cmnd * scmd)944b8e162f9SBart Van Assche static enum scsi_disposition scsi_try_target_reset(struct scsi_cmnd *scmd)
94530bd7df8SMike Christie {
94630bd7df8SMike Christie 	unsigned long flags;
947b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
9480bf8c869SJesper Juhl 	struct Scsi_Host *host = scmd->device->host;
94931435de9SBart Van Assche 	const struct scsi_host_template *hostt = host->hostt;
95030bd7df8SMike Christie 
9510bf8c869SJesper Juhl 	if (!hostt->eh_target_reset_handler)
95230bd7df8SMike Christie 		return FAILED;
95330bd7df8SMike Christie 
9540bf8c869SJesper Juhl 	rtn = hostt->eh_target_reset_handler(scmd);
95530bd7df8SMike Christie 	if (rtn == SUCCESS) {
9560bf8c869SJesper Juhl 		spin_lock_irqsave(host->host_lock, flags);
95730bd7df8SMike Christie 		__starget_for_each_device(scsi_target(scmd->device), NULL,
95830bd7df8SMike Christie 					  __scsi_report_device_reset);
9590bf8c869SJesper Juhl 		spin_unlock_irqrestore(host->host_lock, flags);
96030bd7df8SMike Christie 	}
96130bd7df8SMike Christie 
96230bd7df8SMike Christie 	return rtn;
96330bd7df8SMike Christie }
96430bd7df8SMike Christie 
965292148f8SBrian King /**
966292148f8SBrian King  * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev
967292148f8SBrian King  * @scmd:	SCSI cmd used to send BDR
968292148f8SBrian King  *
969292148f8SBrian King  * Notes:
970292148f8SBrian King  *    There is no timeout for this operation.  if this operation is
971292148f8SBrian King  *    unreliable for a given host, then the host itself needs to put a
972292148f8SBrian King  *    timer on it, and set the host back to a consistent state prior to
973292148f8SBrian King  *    returning.
974dc8875e1SRandy Dunlap  */
scsi_try_bus_device_reset(struct scsi_cmnd * scmd)975b8e162f9SBart Van Assche static enum scsi_disposition scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
976292148f8SBrian King {
977b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
97831435de9SBart Van Assche 	const struct scsi_host_template *hostt = scmd->device->host->hostt;
979292148f8SBrian King 
9800bf8c869SJesper Juhl 	if (!hostt->eh_device_reset_handler)
981292148f8SBrian King 		return FAILED;
982292148f8SBrian King 
9830bf8c869SJesper Juhl 	rtn = hostt->eh_device_reset_handler(scmd);
98430bd7df8SMike Christie 	if (rtn == SUCCESS)
98530bd7df8SMike Christie 		__scsi_report_device_reset(scmd->device, NULL);
986292148f8SBrian King 	return rtn;
987292148f8SBrian King }
988292148f8SBrian King 
989883a030fSHannes Reinecke /**
990883a030fSHannes Reinecke  * scsi_try_to_abort_cmd - Ask host to abort a SCSI command
9916583f6fbSRandy Dunlap  * @hostt:	SCSI driver host template
992883a030fSHannes Reinecke  * @scmd:	SCSI cmd used to send a target reset
993883a030fSHannes Reinecke  *
994883a030fSHannes Reinecke  * Return value:
995883a030fSHannes Reinecke  *	SUCCESS, FAILED, or FAST_IO_FAIL
996883a030fSHannes Reinecke  *
997883a030fSHannes Reinecke  * Notes:
998883a030fSHannes Reinecke  *    SUCCESS does not necessarily indicate that the command
999883a030fSHannes Reinecke  *    has been aborted; it only indicates that the LLDDs
1000883a030fSHannes Reinecke  *    has cleared all references to that command.
1001883a030fSHannes Reinecke  *    LLDDs should return FAILED only if an abort was required
1002883a030fSHannes Reinecke  *    but could not be executed. LLDDs should return FAST_IO_FAIL
1003883a030fSHannes Reinecke  *    if the device is temporarily unavailable (eg due to a
1004883a030fSHannes Reinecke  *    link down on FibreChannel)
1005883a030fSHannes Reinecke  */
1006b8e162f9SBart Van Assche static enum scsi_disposition
scsi_try_to_abort_cmd(const struct scsi_host_template * hostt,struct scsi_cmnd * scmd)100731435de9SBart Van Assche scsi_try_to_abort_cmd(const struct scsi_host_template *hostt, struct scsi_cmnd *scmd)
1008292148f8SBrian King {
10090bf8c869SJesper Juhl 	if (!hostt->eh_abort_handler)
1010292148f8SBrian King 		return FAILED;
1011292148f8SBrian King 
10120bf8c869SJesper Juhl 	return hostt->eh_abort_handler(scmd);
1013292148f8SBrian King }
1014292148f8SBrian King 
scsi_abort_eh_cmnd(struct scsi_cmnd * scmd)1015292148f8SBrian King static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
1016292148f8SBrian King {
10170bf8c869SJesper Juhl 	if (scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd) != SUCCESS)
1018292148f8SBrian King 		if (scsi_try_bus_device_reset(scmd) != SUCCESS)
101930bd7df8SMike Christie 			if (scsi_try_target_reset(scmd) != SUCCESS)
1020292148f8SBrian King 				if (scsi_try_bus_reset(scmd) != SUCCESS)
1021292148f8SBrian King 					scsi_try_host_reset(scmd);
1022292148f8SBrian King }
1023292148f8SBrian King 
1024292148f8SBrian King /**
10253b729f76SSantosh Y  * scsi_eh_prep_cmnd  - Save a scsi command info as part of error recovery
10262dc611deSChristoph Hellwig  * @scmd:       SCSI command structure to hijack
1027e1c23468SBoaz Harrosh  * @ses:        structure to save restore information
102855db6c1bSBoaz Harrosh  * @cmnd:       CDB to send. Can be NULL if no new cmnd is needed
1029ce70fd9aSChristoph Hellwig  * @cmnd_size:  size in bytes of @cmnd (must be <= MAX_COMMAND_SIZE)
103055db6c1bSBoaz Harrosh  * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored)
10312dc611deSChristoph Hellwig  *
1032e1c23468SBoaz Harrosh  * This function is used to save a scsi command information before re-execution
103355db6c1bSBoaz Harrosh  * as part of the error recovery process.  If @sense_bytes is 0 the command
103455db6c1bSBoaz Harrosh  * sent must be one that does not transfer any data.  If @sense_bytes != 0
103555db6c1bSBoaz Harrosh  * @cmnd is ignored and this functions sets up a REQUEST_SENSE command
103655db6c1bSBoaz Harrosh  * and cmnd buffers to read @sense_bytes into @scmd->sense_buffer.
1037dc8875e1SRandy Dunlap  */
scsi_eh_prep_cmnd(struct scsi_cmnd * scmd,struct scsi_eh_save * ses,unsigned char * cmnd,int cmnd_size,unsigned sense_bytes)1038e1c23468SBoaz Harrosh void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
1039e1c23468SBoaz Harrosh 			unsigned char *cmnd, int cmnd_size, unsigned sense_bytes)
10401da177e4SLinus Torvalds {
1041f59114b7S 	struct scsi_device *sdev = scmd->device;
10421da177e4SLinus Torvalds 
1043631c228cSChristoph Hellwig 	/*
1044631c228cSChristoph Hellwig 	 * We need saved copies of a number of fields - this is because
1045631c228cSChristoph Hellwig 	 * error handling may need to overwrite these with different values
1046631c228cSChristoph Hellwig 	 * to run different commands, and once error handling is complete,
1047631c228cSChristoph Hellwig 	 * we will need to restore these values prior to running the actual
1048631c228cSChristoph Hellwig 	 * command.
1049631c228cSChristoph Hellwig 	 */
1050e1c23468SBoaz Harrosh 	ses->cmd_len = scmd->cmd_len;
1051e1c23468SBoaz Harrosh 	ses->data_direction = scmd->sc_data_direction;
105230b0c37bSBoaz Harrosh 	ses->sdb = scmd->sdb;
1053e1c23468SBoaz Harrosh 	ses->result = scmd->result;
1054a9a4ea11SChristoph Hellwig 	ses->resid_len = scmd->resid_len;
105512265709SAlan Stern 	ses->underflow = scmd->underflow;
1056db007fc5SMartin K. Petersen 	ses->prot_op = scmd->prot_op;
10578e8c9d01SHannes Reinecke 	ses->eh_eflags = scmd->eh_eflags;
1058631c228cSChristoph Hellwig 
1059db007fc5SMartin K. Petersen 	scmd->prot_op = SCSI_PROT_NORMAL;
1060c69e6f81SJames Bottomley 	scmd->eh_eflags = 0;
1061ce70fd9aSChristoph Hellwig 	memcpy(ses->cmnd, scmd->cmnd, sizeof(ses->cmnd));
1062ce70fd9aSChristoph Hellwig 	memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
106330b0c37bSBoaz Harrosh 	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
1064644373a4SAlan Stern 	scmd->result = 0;
1065a9a4ea11SChristoph Hellwig 	scmd->resid_len = 0;
106630b0c37bSBoaz Harrosh 
106755db6c1bSBoaz Harrosh 	if (sense_bytes) {
106830b0c37bSBoaz Harrosh 		scmd->sdb.length = min_t(unsigned, SCSI_SENSE_BUFFERSIZE,
106930b0c37bSBoaz Harrosh 					 sense_bytes);
1070e1c23468SBoaz Harrosh 		sg_init_one(&ses->sense_sgl, scmd->sense_buffer,
107130b0c37bSBoaz Harrosh 			    scmd->sdb.length);
107230b0c37bSBoaz Harrosh 		scmd->sdb.table.sgl = &ses->sense_sgl;
107355db6c1bSBoaz Harrosh 		scmd->sc_data_direction = DMA_FROM_DEVICE;
10740c958eccSTony Battersby 		scmd->sdb.table.nents = scmd->sdb.table.orig_nents = 1;
107555db6c1bSBoaz Harrosh 		scmd->cmnd[0] = REQUEST_SENSE;
107630b0c37bSBoaz Harrosh 		scmd->cmnd[4] = scmd->sdb.length;
107755db6c1bSBoaz Harrosh 		scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
1078631c228cSChristoph Hellwig 	} else {
1079631c228cSChristoph Hellwig 		scmd->sc_data_direction = DMA_NONE;
108055db6c1bSBoaz Harrosh 		if (cmnd) {
1081ce70fd9aSChristoph Hellwig 			BUG_ON(cmnd_size > sizeof(scmd->cmnd));
108255db6c1bSBoaz Harrosh 			memcpy(scmd->cmnd, cmnd, cmnd_size);
108355db6c1bSBoaz Harrosh 			scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
108455db6c1bSBoaz Harrosh 		}
1085631c228cSChristoph Hellwig 	}
1086631c228cSChristoph Hellwig 
1087631c228cSChristoph Hellwig 	scmd->underflow = 0;
1088631c228cSChristoph Hellwig 
108955db6c1bSBoaz Harrosh 	if (sdev->scsi_level <= SCSI_2 && sdev->scsi_level != SCSI_UNKNOWN)
10901da177e4SLinus Torvalds 		scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) |
1091f59114b7S 			(sdev->lun << 5 & 0xe0);
10921da177e4SLinus Torvalds 
1093631c228cSChristoph Hellwig 	/*
1094631c228cSChristoph Hellwig 	 * Zero the sense buffer.  The scsi spec mandates that any
1095631c228cSChristoph Hellwig 	 * untransferred sense data should be interpreted as being zero.
1096631c228cSChristoph Hellwig 	 */
1097b80ca4f7SFUJITA Tomonori 	memset(scmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
1098e1c23468SBoaz Harrosh }
1099e1c23468SBoaz Harrosh EXPORT_SYMBOL(scsi_eh_prep_cmnd);
1100631c228cSChristoph Hellwig 
1101e1c23468SBoaz Harrosh /**
11023b729f76SSantosh Y  * scsi_eh_restore_cmnd  - Restore a scsi command info as part of error recovery
1103e1c23468SBoaz Harrosh  * @scmd:       SCSI command structure to restore
1104477e608cSBartlomiej Zolnierkiewicz  * @ses:        saved information from a coresponding call to scsi_eh_prep_cmnd
1105e1c23468SBoaz Harrosh  *
1106477e608cSBartlomiej Zolnierkiewicz  * Undo any damage done by above scsi_eh_prep_cmnd().
1107dc8875e1SRandy Dunlap  */
scsi_eh_restore_cmnd(struct scsi_cmnd * scmd,struct scsi_eh_save * ses)1108e1c23468SBoaz Harrosh void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
1109e1c23468SBoaz Harrosh {
1110e1c23468SBoaz Harrosh 	/*
1111e1c23468SBoaz Harrosh 	 * Restore original data
1112e1c23468SBoaz Harrosh 	 */
1113e1c23468SBoaz Harrosh 	scmd->cmd_len = ses->cmd_len;
1114ce70fd9aSChristoph Hellwig 	memcpy(scmd->cmnd, ses->cmnd, sizeof(ses->cmnd));
1115e1c23468SBoaz Harrosh 	scmd->sc_data_direction = ses->data_direction;
111630b0c37bSBoaz Harrosh 	scmd->sdb = ses->sdb;
1117e1c23468SBoaz Harrosh 	scmd->result = ses->result;
1118a9a4ea11SChristoph Hellwig 	scmd->resid_len = ses->resid_len;
111912265709SAlan Stern 	scmd->underflow = ses->underflow;
1120db007fc5SMartin K. Petersen 	scmd->prot_op = ses->prot_op;
11218e8c9d01SHannes Reinecke 	scmd->eh_eflags = ses->eh_eflags;
1122e1c23468SBoaz Harrosh }
1123e1c23468SBoaz Harrosh EXPORT_SYMBOL(scsi_eh_restore_cmnd);
1124e1c23468SBoaz Harrosh 
1125e1c23468SBoaz Harrosh /**
11263b729f76SSantosh Y  * scsi_send_eh_cmnd  - submit a scsi command as part of error recovery
1127e1c23468SBoaz Harrosh  * @scmd:       SCSI command structure to hijack
1128e1c23468SBoaz Harrosh  * @cmnd:       CDB to send
1129e1c23468SBoaz Harrosh  * @cmnd_size:  size in bytes of @cmnd
1130e1c23468SBoaz Harrosh  * @timeout:    timeout for this request
1131e1c23468SBoaz Harrosh  * @sense_bytes: size of sense data to copy or 0
1132e1c23468SBoaz Harrosh  *
1133e1c23468SBoaz Harrosh  * This function is used to send a scsi command down to a target device
1134e1c23468SBoaz Harrosh  * as part of the error recovery process. See also scsi_eh_prep_cmnd() above.
1135e1c23468SBoaz Harrosh  *
1136e1c23468SBoaz Harrosh  * Return value:
1137e1c23468SBoaz Harrosh  *    SUCCESS or FAILED or NEEDS_RETRY
1138dc8875e1SRandy Dunlap  */
scsi_send_eh_cmnd(struct scsi_cmnd * scmd,unsigned char * cmnd,int cmnd_size,int timeout,unsigned sense_bytes)1139b8e162f9SBart Van Assche static enum scsi_disposition scsi_send_eh_cmnd(struct scsi_cmnd *scmd,
1140b8e162f9SBart Van Assche 	unsigned char *cmnd, int cmnd_size, int timeout, unsigned sense_bytes)
1141e1c23468SBoaz Harrosh {
1142e1c23468SBoaz Harrosh 	struct scsi_device *sdev = scmd->device;
1143e1c23468SBoaz Harrosh 	struct Scsi_Host *shost = sdev->host;
1144e1c23468SBoaz Harrosh 	DECLARE_COMPLETION_ONSTACK(done);
1145bbe9fb0dSBart Van Assche 	unsigned long timeleft = timeout, delay;
1146e1c23468SBoaz Harrosh 	struct scsi_eh_save ses;
1147fc73648aSHannes Reinecke 	const unsigned long stall_for = msecs_to_jiffies(100);
1148e1c23468SBoaz Harrosh 	int rtn;
1149e1c23468SBoaz Harrosh 
1150fc73648aSHannes Reinecke retry:
1151e1c23468SBoaz Harrosh 	scsi_eh_prep_cmnd(scmd, &ses, cmnd, cmnd_size, sense_bytes);
11527dfdc9a5SChristoph Hellwig 	shost->eh_action = &done;
11531da177e4SLinus Torvalds 
11541da177e4SLinus Torvalds 	scsi_log_send(scmd);
1155bf23e619SBart Van Assche 	scmd->submitter = SUBMITTED_BY_SCSI_ERROR_HANDLER;
1156d7ef2eeeSAlexander Atanasov 	scmd->flags |= SCMD_LAST;
1157bbe9fb0dSBart Van Assche 
1158bbe9fb0dSBart Van Assche 	/*
1159bbe9fb0dSBart Van Assche 	 * Lock sdev->state_mutex to avoid that scsi_device_quiesce() can
1160bbe9fb0dSBart Van Assche 	 * change the SCSI device state after we have examined it and before
1161bbe9fb0dSBart Van Assche 	 * .queuecommand() is called.
1162bbe9fb0dSBart Van Assche 	 */
1163bbe9fb0dSBart Van Assche 	mutex_lock(&sdev->state_mutex);
1164bbe9fb0dSBart Van Assche 	while (sdev->sdev_state == SDEV_BLOCK && timeleft > 0) {
1165bbe9fb0dSBart Van Assche 		mutex_unlock(&sdev->state_mutex);
1166bbe9fb0dSBart Van Assche 		SCSI_LOG_ERROR_RECOVERY(5, sdev_printk(KERN_DEBUG, sdev,
1167bbe9fb0dSBart Van Assche 			"%s: state %d <> %d\n", __func__, sdev->sdev_state,
1168bbe9fb0dSBart Van Assche 			SDEV_BLOCK));
1169bbe9fb0dSBart Van Assche 		delay = min(timeleft, stall_for);
1170bbe9fb0dSBart Van Assche 		timeleft -= delay;
1171bbe9fb0dSBart Van Assche 		msleep(jiffies_to_msecs(delay));
1172bbe9fb0dSBart Van Assche 		mutex_lock(&sdev->state_mutex);
1173bbe9fb0dSBart Van Assche 	}
1174bbe9fb0dSBart Van Assche 	if (sdev->sdev_state != SDEV_BLOCK)
1175fc73648aSHannes Reinecke 		rtn = shost->hostt->queuecommand(shost, scmd);
1176bbe9fb0dSBart Van Assche 	else
1177280e91b0SBart Van Assche 		rtn = FAILED;
1178bbe9fb0dSBart Van Assche 	mutex_unlock(&sdev->state_mutex);
1179bbe9fb0dSBart Van Assche 
1180fc73648aSHannes Reinecke 	if (rtn) {
1181fc73648aSHannes Reinecke 		if (timeleft > stall_for) {
1182fc73648aSHannes Reinecke 			scsi_eh_restore_cmnd(scmd, &ses);
1183bf23e619SBart Van Assche 
1184fc73648aSHannes Reinecke 			timeleft -= stall_for;
1185fc73648aSHannes Reinecke 			msleep(jiffies_to_msecs(stall_for));
1186fc73648aSHannes Reinecke 			goto retry;
1187fc73648aSHannes Reinecke 		}
1188fc73648aSHannes Reinecke 		/* signal not to enter either branch of the if () below */
1189fc73648aSHannes Reinecke 		timeleft = 0;
1190511833acSAlan Stern 		rtn = FAILED;
1191fc73648aSHannes Reinecke 	} else {
11927dfdc9a5SChristoph Hellwig 		timeleft = wait_for_completion_timeout(&done, timeout);
1193ac61d195SHannes Reinecke 		rtn = SUCCESS;
1194fc73648aSHannes Reinecke 	}
11951da177e4SLinus Torvalds 
11967dfdc9a5SChristoph Hellwig 	shost->eh_action = NULL;
11971da177e4SLinus Torvalds 
1198fc73648aSHannes Reinecke 	scsi_log_completion(scmd, rtn);
11997dfdc9a5SChristoph Hellwig 
120091921e01SHannes Reinecke 	SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
1201470613b4SHannes Reinecke 			"%s timeleft: %ld\n",
1202470613b4SHannes Reinecke 			__func__, timeleft));
12031da177e4SLinus Torvalds 
12041da177e4SLinus Torvalds 	/*
1205fc73648aSHannes Reinecke 	 * If there is time left scsi_eh_done got called, and we will examine
1206fc73648aSHannes Reinecke 	 * the actual status codes to see whether the command actually did
1207fc73648aSHannes Reinecke 	 * complete normally, else if we have a zero return and no time left,
1208fc73648aSHannes Reinecke 	 * the command must still be pending, so abort it and return FAILED.
1209fc73648aSHannes Reinecke 	 * If we never actually managed to issue the command, because
1210fc73648aSHannes Reinecke 	 * ->queuecommand() kept returning non zero, use the rtn = FAILED
1211fc73648aSHannes Reinecke 	 * value above (so don't execute either branch of the if)
12121da177e4SLinus Torvalds 	 */
12137dfdc9a5SChristoph Hellwig 	if (timeleft) {
12141da177e4SLinus Torvalds 		rtn = scsi_eh_completed_normally(scmd);
121591921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
121691921e01SHannes Reinecke 			"%s: scsi_eh_completed_normally %x\n", __func__, rtn));
12177dfdc9a5SChristoph Hellwig 
12181da177e4SLinus Torvalds 		switch (rtn) {
12191da177e4SLinus Torvalds 		case SUCCESS:
12201da177e4SLinus Torvalds 		case NEEDS_RETRY:
12211da177e4SLinus Torvalds 		case FAILED:
12221da177e4SLinus Torvalds 			break;
12236e883b0eSHannes Reinecke 		case ADD_TO_MLQUEUE:
12246e883b0eSHannes Reinecke 			rtn = NEEDS_RETRY;
12256e883b0eSHannes Reinecke 			break;
12261da177e4SLinus Torvalds 		default:
12271da177e4SLinus Torvalds 			rtn = FAILED;
12281da177e4SLinus Torvalds 			break;
12291da177e4SLinus Torvalds 		}
1230511833acSAlan Stern 	} else if (rtn != FAILED) {
1231292148f8SBrian King 		scsi_abort_eh_cmnd(scmd);
12327dfdc9a5SChristoph Hellwig 		rtn = FAILED;
12331da177e4SLinus Torvalds 	}
12341da177e4SLinus Torvalds 
1235e1c23468SBoaz Harrosh 	scsi_eh_restore_cmnd(scmd, &ses);
123618a4d0a2SMartin K. Petersen 
12371da177e4SLinus Torvalds 	return rtn;
12381da177e4SLinus Torvalds }
12391da177e4SLinus Torvalds 
12401da177e4SLinus Torvalds /**
12411da177e4SLinus Torvalds  * scsi_request_sense - Request sense data from a particular target.
12421da177e4SLinus Torvalds  * @scmd:	SCSI cmd for request sense.
12431da177e4SLinus Torvalds  *
12441da177e4SLinus Torvalds  * Notes:
12451da177e4SLinus Torvalds  *    Some hosts automatically obtain this information, others require
12461da177e4SLinus Torvalds  *    that we obtain it on our own. This function will *not* return until
12471da177e4SLinus Torvalds  *    the command either times out, or it completes.
1248dc8875e1SRandy Dunlap  */
scsi_request_sense(struct scsi_cmnd * scmd)1249b8e162f9SBart Van Assche static enum scsi_disposition scsi_request_sense(struct scsi_cmnd *scmd)
12501da177e4SLinus Torvalds {
12510816c925SMartin K. Petersen 	return scsi_send_eh_cmnd(scmd, NULL, 0, scmd->device->eh_timeout, ~0);
12521da177e4SLinus Torvalds }
12531da177e4SLinus Torvalds 
1254b8e162f9SBart Van Assche static enum scsi_disposition
scsi_eh_action(struct scsi_cmnd * scmd,enum scsi_disposition rtn)1255b8e162f9SBart Van Assche scsi_eh_action(struct scsi_cmnd *scmd, enum scsi_disposition rtn)
12562451079bSJames Bottomley {
1257aa8e25e5SBart Van Assche 	if (!blk_rq_is_passthrough(scsi_cmd_to_rq(scmd))) {
12582451079bSJames Bottomley 		struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd);
12592451079bSJames Bottomley 		if (sdrv->eh_action)
12602451079bSJames Bottomley 			rtn = sdrv->eh_action(scmd, rtn);
12612451079bSJames Bottomley 	}
12622451079bSJames Bottomley 	return rtn;
12632451079bSJames Bottomley }
12642451079bSJames Bottomley 
12651da177e4SLinus Torvalds /**
12661da177e4SLinus Torvalds  * scsi_eh_finish_cmd - Handle a cmd that eh is finished with.
12671da177e4SLinus Torvalds  * @scmd:	Original SCSI cmd that eh has finished.
12681da177e4SLinus Torvalds  * @done_q:	Queue for processed commands.
12691da177e4SLinus Torvalds  *
12701da177e4SLinus Torvalds  * Notes:
12711da177e4SLinus Torvalds  *    We don't want to use the normal command completion while we are are
12721da177e4SLinus Torvalds  *    still handling errors - it may cause other commands to be queued,
1273eb44820cSRob Landley  *    and that would disturb what we are doing.  Thus we really want to
12741da177e4SLinus Torvalds  *    keep a list of pending commands for final completion, and once we
12751da177e4SLinus Torvalds  *    are ready to leave error handling we handle completion for real.
1276dc8875e1SRandy Dunlap  */
scsi_eh_finish_cmd(struct scsi_cmnd * scmd,struct list_head * done_q)1277041c5fc3STejun Heo void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
12781da177e4SLinus Torvalds {
12791da177e4SLinus Torvalds 	list_move_tail(&scmd->eh_entry, done_q);
12801da177e4SLinus Torvalds }
1281041c5fc3STejun Heo EXPORT_SYMBOL(scsi_eh_finish_cmd);
12821da177e4SLinus Torvalds 
12831da177e4SLinus Torvalds /**
12841da177e4SLinus Torvalds  * scsi_eh_get_sense - Get device sense data.
12851da177e4SLinus Torvalds  * @work_q:	Queue of commands to process.
1286eb44820cSRob Landley  * @done_q:	Queue of processed commands.
12871da177e4SLinus Torvalds  *
12881da177e4SLinus Torvalds  * Description:
12891da177e4SLinus Torvalds  *    See if we need to request sense information.  if so, then get it
12901da177e4SLinus Torvalds  *    now, so we have a better idea of what to do.
12911da177e4SLinus Torvalds  *
12921da177e4SLinus Torvalds  * Notes:
12931da177e4SLinus Torvalds  *    This has the unfortunate side effect that if a shost adapter does
1294eb44820cSRob Landley  *    not automatically request sense information, we end up shutting
12951da177e4SLinus Torvalds  *    it down before we request it.
12961da177e4SLinus Torvalds  *
12971da177e4SLinus Torvalds  *    All drivers should request sense information internally these days,
12981da177e4SLinus Torvalds  *    so for now all I have to say is tough noogies if you end up in here.
12991da177e4SLinus Torvalds  *
13001da177e4SLinus Torvalds  *    XXX: Long term this code should go away, but that needs an audit of
13011da177e4SLinus Torvalds  *         all LLDDs first.
1302dc8875e1SRandy Dunlap  */
scsi_eh_get_sense(struct list_head * work_q,struct list_head * done_q)1303dca84e46SDarrick J. Wong int scsi_eh_get_sense(struct list_head *work_q,
13041da177e4SLinus Torvalds 		      struct list_head *done_q)
13051da177e4SLinus Torvalds {
1306937abeaaSChristoph Hellwig 	struct scsi_cmnd *scmd, *next;
1307b4562022SHannes Reinecke 	struct Scsi_Host *shost;
1308b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
13091da177e4SLinus Torvalds 
1310709c75b5Sjiang.biao2@zte.com.cn 	/*
1311709c75b5Sjiang.biao2@zte.com.cn 	 * If SCSI_EH_ABORT_SCHEDULED has been set, it is timeout IO,
1312709c75b5Sjiang.biao2@zte.com.cn 	 * should not get sense.
1313709c75b5Sjiang.biao2@zte.com.cn 	 */
1314937abeaaSChristoph Hellwig 	list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
1315a0658632SHannes Reinecke 		if ((scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) ||
13161da177e4SLinus Torvalds 		    SCSI_SENSE_VALID(scmd))
13171da177e4SLinus Torvalds 			continue;
13181da177e4SLinus Torvalds 
1319b4562022SHannes Reinecke 		shost = scmd->device->host;
1320b4562022SHannes Reinecke 		if (scsi_host_eh_past_deadline(shost)) {
1321b4562022SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
1322a222b1e2SHannes Reinecke 				scmd_printk(KERN_INFO, scmd,
1323a222b1e2SHannes Reinecke 					    "%s: skip request sense, past eh deadline\n",
1324a222b1e2SHannes Reinecke 					     current->comm));
1325b4562022SHannes Reinecke 			break;
1326b4562022SHannes Reinecke 		}
1327d0672a03SHannes Reinecke 		if (!scsi_status_is_check_condition(scmd->result))
1328d555a2abSJames Bottomley 			/*
1329d555a2abSJames Bottomley 			 * don't request sense if there's no check condition
1330d555a2abSJames Bottomley 			 * status because the error we're processing isn't one
1331d555a2abSJames Bottomley 			 * that has a sense code (and some devices get
1332d555a2abSJames Bottomley 			 * confused by sense requests out of the blue)
1333d555a2abSJames Bottomley 			 */
1334d555a2abSJames Bottomley 			continue;
1335d555a2abSJames Bottomley 
13363bf743e7SJeff Garzik 		SCSI_LOG_ERROR_RECOVERY(2, scmd_printk(KERN_INFO, scmd,
13373bf743e7SJeff Garzik 						  "%s: requesting sense\n",
13383bf743e7SJeff Garzik 						  current->comm));
13391da177e4SLinus Torvalds 		rtn = scsi_request_sense(scmd);
13401da177e4SLinus Torvalds 		if (rtn != SUCCESS)
13411da177e4SLinus Torvalds 			continue;
13421da177e4SLinus Torvalds 
134391921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
1344470613b4SHannes Reinecke 			"sense requested, result %x\n", scmd->result));
1345d811b848SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3, scsi_print_sense(scmd));
13461da177e4SLinus Torvalds 
13471da177e4SLinus Torvalds 		rtn = scsi_decide_disposition(scmd);
13481da177e4SLinus Torvalds 
13491da177e4SLinus Torvalds 		/*
13501da177e4SLinus Torvalds 		 * if the result was normal, then just pass it along to the
13511da177e4SLinus Torvalds 		 * upper level.
13521da177e4SLinus Torvalds 		 */
13531da177e4SLinus Torvalds 		if (rtn == SUCCESS)
13542a242d59SMike Christie 			/*
13552a242d59SMike Christie 			 * We don't want this command reissued, just finished
13562a242d59SMike Christie 			 * with the sense data, so set retries to the max
13572a242d59SMike Christie 			 * allowed to ensure it won't get reissued. If the user
13582a242d59SMike Christie 			 * has requested infinite retries, we also want to
13592a242d59SMike Christie 			 * finish this command, so force completion by setting
13602a242d59SMike Christie 			 * retries and allowed to the same value.
13612a242d59SMike Christie 			 */
13622a242d59SMike Christie 			if (scmd->allowed == SCSI_CMD_RETRIES_NO_LIMIT)
13632a242d59SMike Christie 				scmd->retries = scmd->allowed = 1;
13642a242d59SMike Christie 			else
13651da177e4SLinus Torvalds 				scmd->retries = scmd->allowed;
13661da177e4SLinus Torvalds 		else if (rtn != NEEDS_RETRY)
13671da177e4SLinus Torvalds 			continue;
13681da177e4SLinus Torvalds 
13691da177e4SLinus Torvalds 		scsi_eh_finish_cmd(scmd, done_q);
13701da177e4SLinus Torvalds 	}
13711da177e4SLinus Torvalds 
13721da177e4SLinus Torvalds 	return list_empty(work_q);
13731da177e4SLinus Torvalds }
1374dca84e46SDarrick J. Wong EXPORT_SYMBOL_GPL(scsi_eh_get_sense);
13751da177e4SLinus Torvalds 
13761da177e4SLinus Torvalds /**
13771da177e4SLinus Torvalds  * scsi_eh_tur - Send TUR to device.
1378eb44820cSRob Landley  * @scmd:	&scsi_cmnd to send TUR
13791da177e4SLinus Torvalds  *
13801da177e4SLinus Torvalds  * Return value:
13811da177e4SLinus Torvalds  *    0 - Device is ready. 1 - Device NOT ready.
1382dc8875e1SRandy Dunlap  */
scsi_eh_tur(struct scsi_cmnd * scmd)13831da177e4SLinus Torvalds static int scsi_eh_tur(struct scsi_cmnd *scmd)
13841da177e4SLinus Torvalds {
13851da177e4SLinus Torvalds 	static unsigned char tur_command[6] = {TEST_UNIT_READY, 0, 0, 0, 0, 0};
1386b8e162f9SBart Van Assche 	int retry_cnt = 1;
1387b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
13881da177e4SLinus Torvalds 
13891da177e4SLinus Torvalds retry_tur:
13900816c925SMartin K. Petersen 	rtn = scsi_send_eh_cmnd(scmd, tur_command, 6,
13910816c925SMartin K. Petersen 				scmd->device->eh_timeout, 0);
13921da177e4SLinus Torvalds 
139391921e01SHannes Reinecke 	SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
1394470613b4SHannes Reinecke 		"%s return: %x\n", __func__, rtn));
1395631c228cSChristoph Hellwig 
1396631c228cSChristoph Hellwig 	switch (rtn) {
1397631c228cSChristoph Hellwig 	case NEEDS_RETRY:
13981da177e4SLinus Torvalds 		if (retry_cnt--)
13991da177e4SLinus Torvalds 			goto retry_tur;
1400df561f66SGustavo A. R. Silva 		fallthrough;
1401631c228cSChristoph Hellwig 	case SUCCESS:
1402e47373ecSAlan Stern 		return 0;
1403631c228cSChristoph Hellwig 	default:
14041da177e4SLinus Torvalds 		return 1;
14051da177e4SLinus Torvalds 	}
1406631c228cSChristoph Hellwig }
14071da177e4SLinus Torvalds 
14081da177e4SLinus Torvalds /**
14093eef6257SDavid Jeffery  * scsi_eh_test_devices - check if devices are responding from error recovery.
14103eef6257SDavid Jeffery  * @cmd_list:	scsi commands in error recovery.
14113eef6257SDavid Jeffery  * @work_q:	queue for commands which still need more error recovery
14123eef6257SDavid Jeffery  * @done_q:	queue for commands which are finished
14133eef6257SDavid Jeffery  * @try_stu:	boolean on if a STU command should be tried in addition to TUR.
14143eef6257SDavid Jeffery  *
14153eef6257SDavid Jeffery  * Decription:
14163eef6257SDavid Jeffery  *    Tests if devices are in a working state.  Commands to devices now in
14173eef6257SDavid Jeffery  *    a working state are sent to the done_q while commands to devices which
14183eef6257SDavid Jeffery  *    are still failing to respond are returned to the work_q for more
14193eef6257SDavid Jeffery  *    processing.
14203eef6257SDavid Jeffery  **/
scsi_eh_test_devices(struct list_head * cmd_list,struct list_head * work_q,struct list_head * done_q,int try_stu)14213eef6257SDavid Jeffery static int scsi_eh_test_devices(struct list_head *cmd_list,
14223eef6257SDavid Jeffery 				struct list_head *work_q,
14233eef6257SDavid Jeffery 				struct list_head *done_q, int try_stu)
14243eef6257SDavid Jeffery {
14253eef6257SDavid Jeffery 	struct scsi_cmnd *scmd, *next;
14263eef6257SDavid Jeffery 	struct scsi_device *sdev;
14273eef6257SDavid Jeffery 	int finish_cmds;
14283eef6257SDavid Jeffery 
14293eef6257SDavid Jeffery 	while (!list_empty(cmd_list)) {
14303eef6257SDavid Jeffery 		scmd = list_entry(cmd_list->next, struct scsi_cmnd, eh_entry);
14313eef6257SDavid Jeffery 		sdev = scmd->device;
14323eef6257SDavid Jeffery 
1433b4562022SHannes Reinecke 		if (!try_stu) {
1434b4562022SHannes Reinecke 			if (scsi_host_eh_past_deadline(sdev->host)) {
1435b4562022SHannes Reinecke 				/* Push items back onto work_q */
1436b4562022SHannes Reinecke 				list_splice_init(cmd_list, work_q);
1437b4562022SHannes Reinecke 				SCSI_LOG_ERROR_RECOVERY(3,
1438a222b1e2SHannes Reinecke 					sdev_printk(KERN_INFO, sdev,
1439a222b1e2SHannes Reinecke 						    "%s: skip test device, past eh deadline",
1440a222b1e2SHannes Reinecke 						    current->comm));
1441b4562022SHannes Reinecke 				break;
1442b4562022SHannes Reinecke 			}
1443b4562022SHannes Reinecke 		}
1444b4562022SHannes Reinecke 
14453eef6257SDavid Jeffery 		finish_cmds = !scsi_device_online(scmd->device) ||
14463eef6257SDavid Jeffery 			(try_stu && !scsi_eh_try_stu(scmd) &&
14473eef6257SDavid Jeffery 			 !scsi_eh_tur(scmd)) ||
14483eef6257SDavid Jeffery 			!scsi_eh_tur(scmd);
14493eef6257SDavid Jeffery 
14503eef6257SDavid Jeffery 		list_for_each_entry_safe(scmd, next, cmd_list, eh_entry)
14513eef6257SDavid Jeffery 			if (scmd->device == sdev) {
14522451079bSJames Bottomley 				if (finish_cmds &&
14532451079bSJames Bottomley 				    (try_stu ||
14542451079bSJames Bottomley 				     scsi_eh_action(scmd, SUCCESS) == SUCCESS))
14553eef6257SDavid Jeffery 					scsi_eh_finish_cmd(scmd, done_q);
14563eef6257SDavid Jeffery 				else
14573eef6257SDavid Jeffery 					list_move_tail(&scmd->eh_entry, work_q);
14583eef6257SDavid Jeffery 			}
14593eef6257SDavid Jeffery 	}
14603eef6257SDavid Jeffery 	return list_empty(work_q);
14613eef6257SDavid Jeffery }
14623eef6257SDavid Jeffery 
14631da177e4SLinus Torvalds /**
14641da177e4SLinus Torvalds  * scsi_eh_try_stu - Send START_UNIT to device.
1465eb44820cSRob Landley  * @scmd:	&scsi_cmnd to send START_UNIT
14661da177e4SLinus Torvalds  *
14671da177e4SLinus Torvalds  * Return value:
14681da177e4SLinus Torvalds  *    0 - Device is ready. 1 - Device NOT ready.
1469dc8875e1SRandy Dunlap  */
scsi_eh_try_stu(struct scsi_cmnd * scmd)14701da177e4SLinus Torvalds static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
14711da177e4SLinus Torvalds {
14721da177e4SLinus Torvalds 	static unsigned char stu_command[6] = {START_STOP, 0, 0, 0, 1, 0};
14731da177e4SLinus Torvalds 
1474631c228cSChristoph Hellwig 	if (scmd->device->allow_restart) {
1475b8e162f9SBart Van Assche 		int i;
1476b8e162f9SBart Van Assche 		enum scsi_disposition rtn = NEEDS_RETRY;
14771da177e4SLinus Torvalds 
1478ed773e66SBrian King 		for (i = 0; rtn == NEEDS_RETRY && i < 2; i++)
1479adcc796bSChunguang Xu 			rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
1480adcc796bSChunguang Xu 						scmd->device->eh_timeout, 0);
1481ed773e66SBrian King 
14821da177e4SLinus Torvalds 		if (rtn == SUCCESS)
14831da177e4SLinus Torvalds 			return 0;
1484631c228cSChristoph Hellwig 	}
1485631c228cSChristoph Hellwig 
14861da177e4SLinus Torvalds 	return 1;
14871da177e4SLinus Torvalds }
14881da177e4SLinus Torvalds 
14891da177e4SLinus Torvalds  /**
14901da177e4SLinus Torvalds  * scsi_eh_stu - send START_UNIT if needed
1491eb44820cSRob Landley  * @shost:	&scsi host being recovered.
1492eb44820cSRob Landley  * @work_q:	&list_head for pending commands.
1493eb44820cSRob Landley  * @done_q:	&list_head for processed commands.
14941da177e4SLinus Torvalds  *
14951da177e4SLinus Torvalds  * Notes:
14961da177e4SLinus Torvalds  *    If commands are failing due to not ready, initializing command required,
14971da177e4SLinus Torvalds  *	try revalidating the device, which will end up sending a start unit.
1498dc8875e1SRandy Dunlap  */
scsi_eh_stu(struct Scsi_Host * shost,struct list_head * work_q,struct list_head * done_q)14991da177e4SLinus Torvalds static int scsi_eh_stu(struct Scsi_Host *shost,
15001da177e4SLinus Torvalds 			      struct list_head *work_q,
15011da177e4SLinus Torvalds 			      struct list_head *done_q)
15021da177e4SLinus Torvalds {
1503937abeaaSChristoph Hellwig 	struct scsi_cmnd *scmd, *stu_scmd, *next;
15041da177e4SLinus Torvalds 	struct scsi_device *sdev;
15051da177e4SLinus Torvalds 
15061da177e4SLinus Torvalds 	shost_for_each_device(sdev, shost) {
1507b4562022SHannes Reinecke 		if (scsi_host_eh_past_deadline(shost)) {
1508b4562022SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
1509a222b1e2SHannes Reinecke 				sdev_printk(KERN_INFO, sdev,
1510a222b1e2SHannes Reinecke 					    "%s: skip START_UNIT, past eh deadline\n",
1511a222b1e2SHannes Reinecke 					    current->comm));
15124dea170fSYe Bin 			scsi_device_put(sdev);
1513b4562022SHannes Reinecke 			break;
1514b4562022SHannes Reinecke 		}
15151da177e4SLinus Torvalds 		stu_scmd = NULL;
15161da177e4SLinus Torvalds 		list_for_each_entry(scmd, work_q, eh_entry)
15171da177e4SLinus Torvalds 			if (scmd->device == sdev && SCSI_SENSE_VALID(scmd) &&
15181da177e4SLinus Torvalds 			    scsi_check_sense(scmd) == FAILED ) {
15191da177e4SLinus Torvalds 				stu_scmd = scmd;
15201da177e4SLinus Torvalds 				break;
15211da177e4SLinus Torvalds 			}
15221da177e4SLinus Torvalds 
15231da177e4SLinus Torvalds 		if (!stu_scmd)
15241da177e4SLinus Torvalds 			continue;
15251da177e4SLinus Torvalds 
152691921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3,
1527a222b1e2SHannes Reinecke 			sdev_printk(KERN_INFO, sdev,
1528a222b1e2SHannes Reinecke 				     "%s: Sending START_UNIT\n",
1529a222b1e2SHannes Reinecke 				    current->comm));
15301da177e4SLinus Torvalds 
15311da177e4SLinus Torvalds 		if (!scsi_eh_try_stu(stu_scmd)) {
15321da177e4SLinus Torvalds 			if (!scsi_device_online(sdev) ||
15331da177e4SLinus Torvalds 			    !scsi_eh_tur(stu_scmd)) {
1534937abeaaSChristoph Hellwig 				list_for_each_entry_safe(scmd, next,
1535937abeaaSChristoph Hellwig 							  work_q, eh_entry) {
15362451079bSJames Bottomley 					if (scmd->device == sdev &&
15372451079bSJames Bottomley 					    scsi_eh_action(scmd, SUCCESS) == SUCCESS)
15381da177e4SLinus Torvalds 						scsi_eh_finish_cmd(scmd, done_q);
15391da177e4SLinus Torvalds 				}
15401da177e4SLinus Torvalds 			}
15411da177e4SLinus Torvalds 		} else {
15421da177e4SLinus Torvalds 			SCSI_LOG_ERROR_RECOVERY(3,
1543a222b1e2SHannes Reinecke 				sdev_printk(KERN_INFO, sdev,
1544a222b1e2SHannes Reinecke 					    "%s: START_UNIT failed\n",
1545a222b1e2SHannes Reinecke 					    current->comm));
15461da177e4SLinus Torvalds 		}
15471da177e4SLinus Torvalds 	}
15481da177e4SLinus Torvalds 
15491da177e4SLinus Torvalds 	return list_empty(work_q);
15501da177e4SLinus Torvalds }
15511da177e4SLinus Torvalds 
15521da177e4SLinus Torvalds 
15531da177e4SLinus Torvalds /**
15541da177e4SLinus Torvalds  * scsi_eh_bus_device_reset - send bdr if needed
15551da177e4SLinus Torvalds  * @shost:	scsi host being recovered.
1556eb44820cSRob Landley  * @work_q:	&list_head for pending commands.
1557eb44820cSRob Landley  * @done_q:	&list_head for processed commands.
15581da177e4SLinus Torvalds  *
15591da177e4SLinus Torvalds  * Notes:
1560eb44820cSRob Landley  *    Try a bus device reset.  Still, look to see whether we have multiple
15611da177e4SLinus Torvalds  *    devices that are jammed or not - if we have multiple devices, it
15621da177e4SLinus Torvalds  *    makes no sense to try bus_device_reset - we really would need to try
15631da177e4SLinus Torvalds  *    a bus_reset instead.
1564dc8875e1SRandy Dunlap  */
scsi_eh_bus_device_reset(struct Scsi_Host * shost,struct list_head * work_q,struct list_head * done_q)15651da177e4SLinus Torvalds static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
15661da177e4SLinus Torvalds 				    struct list_head *work_q,
15671da177e4SLinus Torvalds 				    struct list_head *done_q)
15681da177e4SLinus Torvalds {
1569937abeaaSChristoph Hellwig 	struct scsi_cmnd *scmd, *bdr_scmd, *next;
15701da177e4SLinus Torvalds 	struct scsi_device *sdev;
1571b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
15721da177e4SLinus Torvalds 
15731da177e4SLinus Torvalds 	shost_for_each_device(sdev, shost) {
1574b4562022SHannes Reinecke 		if (scsi_host_eh_past_deadline(shost)) {
1575b4562022SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
1576a222b1e2SHannes Reinecke 				sdev_printk(KERN_INFO, sdev,
1577a222b1e2SHannes Reinecke 					    "%s: skip BDR, past eh deadline\n",
1578a222b1e2SHannes Reinecke 					     current->comm));
15794dea170fSYe Bin 			scsi_device_put(sdev);
1580b4562022SHannes Reinecke 			break;
1581b4562022SHannes Reinecke 		}
15821da177e4SLinus Torvalds 		bdr_scmd = NULL;
15831da177e4SLinus Torvalds 		list_for_each_entry(scmd, work_q, eh_entry)
15841da177e4SLinus Torvalds 			if (scmd->device == sdev) {
15851da177e4SLinus Torvalds 				bdr_scmd = scmd;
15861da177e4SLinus Torvalds 				break;
15871da177e4SLinus Torvalds 			}
15881da177e4SLinus Torvalds 
15891da177e4SLinus Torvalds 		if (!bdr_scmd)
15901da177e4SLinus Torvalds 			continue;
15911da177e4SLinus Torvalds 
159291921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3,
1593a222b1e2SHannes Reinecke 			sdev_printk(KERN_INFO, sdev,
1594a222b1e2SHannes Reinecke 				     "%s: Sending BDR\n", current->comm));
15951da177e4SLinus Torvalds 		rtn = scsi_try_bus_device_reset(bdr_scmd);
15962f2eb587SChristof Schmitt 		if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
15971da177e4SLinus Torvalds 			if (!scsi_device_online(sdev) ||
15982f2eb587SChristof Schmitt 			    rtn == FAST_IO_FAIL ||
15991da177e4SLinus Torvalds 			    !scsi_eh_tur(bdr_scmd)) {
1600937abeaaSChristoph Hellwig 				list_for_each_entry_safe(scmd, next,
1601937abeaaSChristoph Hellwig 							 work_q, eh_entry) {
16022451079bSJames Bottomley 					if (scmd->device == sdev &&
16032451079bSJames Bottomley 					    scsi_eh_action(scmd, rtn) != FAILED)
16041da177e4SLinus Torvalds 						scsi_eh_finish_cmd(scmd,
16051da177e4SLinus Torvalds 								   done_q);
16061da177e4SLinus Torvalds 				}
16071da177e4SLinus Torvalds 			}
16081da177e4SLinus Torvalds 		} else {
160991921e01SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
1610a222b1e2SHannes Reinecke 				sdev_printk(KERN_INFO, sdev,
1611a222b1e2SHannes Reinecke 					    "%s: BDR failed\n", current->comm));
16121da177e4SLinus Torvalds 		}
16131da177e4SLinus Torvalds 	}
16141da177e4SLinus Torvalds 
16151da177e4SLinus Torvalds 	return list_empty(work_q);
16161da177e4SLinus Torvalds }
16171da177e4SLinus Torvalds 
16181da177e4SLinus Torvalds /**
161930bd7df8SMike Christie  * scsi_eh_target_reset - send target reset if needed
162030bd7df8SMike Christie  * @shost:	scsi host being recovered.
162130bd7df8SMike Christie  * @work_q:	&list_head for pending commands.
162230bd7df8SMike Christie  * @done_q:	&list_head for processed commands.
162330bd7df8SMike Christie  *
162430bd7df8SMike Christie  * Notes:
162530bd7df8SMike Christie  *    Try a target reset.
162630bd7df8SMike Christie  */
scsi_eh_target_reset(struct Scsi_Host * shost,struct list_head * work_q,struct list_head * done_q)162730bd7df8SMike Christie static int scsi_eh_target_reset(struct Scsi_Host *shost,
162830bd7df8SMike Christie 				struct list_head *work_q,
162930bd7df8SMike Christie 				struct list_head *done_q)
163030bd7df8SMike Christie {
163198db5195SJames Bottomley 	LIST_HEAD(tmp_list);
16323eef6257SDavid Jeffery 	LIST_HEAD(check_list);
163330bd7df8SMike Christie 
163498db5195SJames Bottomley 	list_splice_init(work_q, &tmp_list);
163598db5195SJames Bottomley 
163698db5195SJames Bottomley 	while (!list_empty(&tmp_list)) {
163798db5195SJames Bottomley 		struct scsi_cmnd *next, *scmd;
1638b8e162f9SBart Van Assche 		enum scsi_disposition rtn;
163998db5195SJames Bottomley 		unsigned int id;
1640b4562022SHannes Reinecke 
1641b4562022SHannes Reinecke 		if (scsi_host_eh_past_deadline(shost)) {
1642b4562022SHannes Reinecke 			/* push back on work queue for further processing */
1643b4562022SHannes Reinecke 			list_splice_init(&check_list, work_q);
1644b4562022SHannes Reinecke 			list_splice_init(&tmp_list, work_q);
1645b4562022SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
1646b4562022SHannes Reinecke 				shost_printk(KERN_INFO, shost,
1647a222b1e2SHannes Reinecke 					    "%s: Skip target reset, past eh deadline\n",
1648a222b1e2SHannes Reinecke 					     current->comm));
1649b4562022SHannes Reinecke 			return list_empty(work_q);
1650b4562022SHannes Reinecke 		}
165198db5195SJames Bottomley 
165298db5195SJames Bottomley 		scmd = list_entry(tmp_list.next, struct scsi_cmnd, eh_entry);
165398db5195SJames Bottomley 		id = scmd_id(scmd);
165430bd7df8SMike Christie 
165591921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3,
165691921e01SHannes Reinecke 			shost_printk(KERN_INFO, shost,
165791921e01SHannes Reinecke 				     "%s: Sending target reset to target %d\n",
165830bd7df8SMike Christie 				     current->comm, id));
165998db5195SJames Bottomley 		rtn = scsi_try_target_reset(scmd);
166098db5195SJames Bottomley 		if (rtn != SUCCESS && rtn != FAST_IO_FAIL)
166191921e01SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
166291921e01SHannes Reinecke 				shost_printk(KERN_INFO, shost,
166391921e01SHannes Reinecke 					     "%s: Target reset failed"
166491921e01SHannes Reinecke 					     " target: %d\n",
166530bd7df8SMike Christie 					     current->comm, id));
166698db5195SJames Bottomley 		list_for_each_entry_safe(scmd, next, &tmp_list, eh_entry) {
166798db5195SJames Bottomley 			if (scmd_id(scmd) != id)
166898db5195SJames Bottomley 				continue;
166998db5195SJames Bottomley 
16703eef6257SDavid Jeffery 			if (rtn == SUCCESS)
16713eef6257SDavid Jeffery 				list_move_tail(&scmd->eh_entry, &check_list);
16723eef6257SDavid Jeffery 			else if (rtn == FAST_IO_FAIL)
167398db5195SJames Bottomley 				scsi_eh_finish_cmd(scmd, done_q);
167498db5195SJames Bottomley 			else
167598db5195SJames Bottomley 				/* push back on work queue for further processing */
167698db5195SJames Bottomley 				list_move(&scmd->eh_entry, work_q);
167798db5195SJames Bottomley 		}
167898db5195SJames Bottomley 	}
167930bd7df8SMike Christie 
16803eef6257SDavid Jeffery 	return scsi_eh_test_devices(&check_list, work_q, done_q, 0);
168130bd7df8SMike Christie }
168230bd7df8SMike Christie 
168330bd7df8SMike Christie /**
16841da177e4SLinus Torvalds  * scsi_eh_bus_reset - send a bus reset
1685eb44820cSRob Landley  * @shost:	&scsi host being recovered.
1686eb44820cSRob Landley  * @work_q:	&list_head for pending commands.
1687eb44820cSRob Landley  * @done_q:	&list_head for processed commands.
1688dc8875e1SRandy Dunlap  */
scsi_eh_bus_reset(struct Scsi_Host * shost,struct list_head * work_q,struct list_head * done_q)16891da177e4SLinus Torvalds static int scsi_eh_bus_reset(struct Scsi_Host *shost,
16901da177e4SLinus Torvalds 			     struct list_head *work_q,
16911da177e4SLinus Torvalds 			     struct list_head *done_q)
16921da177e4SLinus Torvalds {
1693937abeaaSChristoph Hellwig 	struct scsi_cmnd *scmd, *chan_scmd, *next;
16943eef6257SDavid Jeffery 	LIST_HEAD(check_list);
16951da177e4SLinus Torvalds 	unsigned int channel;
1696b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
16971da177e4SLinus Torvalds 
16981da177e4SLinus Torvalds 	/*
16991da177e4SLinus Torvalds 	 * we really want to loop over the various channels, and do this on
17001da177e4SLinus Torvalds 	 * a channel by channel basis.  we should also check to see if any
17011da177e4SLinus Torvalds 	 * of the failed commands are on soft_reset devices, and if so, skip
17021da177e4SLinus Torvalds 	 * the reset.
17031da177e4SLinus Torvalds 	 */
17041da177e4SLinus Torvalds 
17051da177e4SLinus Torvalds 	for (channel = 0; channel <= shost->max_channel; channel++) {
1706b4562022SHannes Reinecke 		if (scsi_host_eh_past_deadline(shost)) {
1707b4562022SHannes Reinecke 			list_splice_init(&check_list, work_q);
1708b4562022SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
1709b4562022SHannes Reinecke 				shost_printk(KERN_INFO, shost,
1710a222b1e2SHannes Reinecke 					    "%s: skip BRST, past eh deadline\n",
1711a222b1e2SHannes Reinecke 					     current->comm));
1712b4562022SHannes Reinecke 			return list_empty(work_q);
1713b4562022SHannes Reinecke 		}
1714b4562022SHannes Reinecke 
17151da177e4SLinus Torvalds 		chan_scmd = NULL;
17161da177e4SLinus Torvalds 		list_for_each_entry(scmd, work_q, eh_entry) {
1717422c0d61SJeff Garzik 			if (channel == scmd_channel(scmd)) {
17181da177e4SLinus Torvalds 				chan_scmd = scmd;
17191da177e4SLinus Torvalds 				break;
17201da177e4SLinus Torvalds 				/*
17211da177e4SLinus Torvalds 				 * FIXME add back in some support for
17221da177e4SLinus Torvalds 				 * soft_reset devices.
17231da177e4SLinus Torvalds 				 */
17241da177e4SLinus Torvalds 			}
17251da177e4SLinus Torvalds 		}
17261da177e4SLinus Torvalds 
17271da177e4SLinus Torvalds 		if (!chan_scmd)
17281da177e4SLinus Torvalds 			continue;
172991921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3,
173091921e01SHannes Reinecke 			shost_printk(KERN_INFO, shost,
173191921e01SHannes Reinecke 				     "%s: Sending BRST chan: %d\n",
173291921e01SHannes Reinecke 				     current->comm, channel));
17331da177e4SLinus Torvalds 		rtn = scsi_try_bus_reset(chan_scmd);
17342f2eb587SChristof Schmitt 		if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
1735937abeaaSChristoph Hellwig 			list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
17363eef6257SDavid Jeffery 				if (channel == scmd_channel(scmd)) {
17373eef6257SDavid Jeffery 					if (rtn == FAST_IO_FAIL)
17381da177e4SLinus Torvalds 						scsi_eh_finish_cmd(scmd,
17391da177e4SLinus Torvalds 								   done_q);
17403eef6257SDavid Jeffery 					else
17413eef6257SDavid Jeffery 						list_move_tail(&scmd->eh_entry,
17423eef6257SDavid Jeffery 							       &check_list);
17433eef6257SDavid Jeffery 				}
17441da177e4SLinus Torvalds 			}
17451da177e4SLinus Torvalds 		} else {
174691921e01SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
174791921e01SHannes Reinecke 				shost_printk(KERN_INFO, shost,
174891921e01SHannes Reinecke 					     "%s: BRST failed chan: %d\n",
174991921e01SHannes Reinecke 					     current->comm, channel));
17501da177e4SLinus Torvalds 		}
17511da177e4SLinus Torvalds 	}
17523eef6257SDavid Jeffery 	return scsi_eh_test_devices(&check_list, work_q, done_q, 0);
17531da177e4SLinus Torvalds }
17541da177e4SLinus Torvalds 
17551da177e4SLinus Torvalds /**
17561da177e4SLinus Torvalds  * scsi_eh_host_reset - send a host reset
175774cf298fSRandy Dunlap  * @shost:	host to be reset.
175874cf298fSRandy Dunlap  * @work_q:	&list_head for pending commands.
175974cf298fSRandy Dunlap  * @done_q:	&list_head for processed commands.
1760dc8875e1SRandy Dunlap  */
scsi_eh_host_reset(struct Scsi_Host * shost,struct list_head * work_q,struct list_head * done_q)176191921e01SHannes Reinecke static int scsi_eh_host_reset(struct Scsi_Host *shost,
176291921e01SHannes Reinecke 			      struct list_head *work_q,
17631da177e4SLinus Torvalds 			      struct list_head *done_q)
17641da177e4SLinus Torvalds {
1765937abeaaSChristoph Hellwig 	struct scsi_cmnd *scmd, *next;
17663eef6257SDavid Jeffery 	LIST_HEAD(check_list);
1767b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
17681da177e4SLinus Torvalds 
17691da177e4SLinus Torvalds 	if (!list_empty(work_q)) {
17701da177e4SLinus Torvalds 		scmd = list_entry(work_q->next,
17711da177e4SLinus Torvalds 				  struct scsi_cmnd, eh_entry);
17721da177e4SLinus Torvalds 
177391921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3,
177491921e01SHannes Reinecke 			shost_printk(KERN_INFO, shost,
177591921e01SHannes Reinecke 				     "%s: Sending HRST\n",
177691921e01SHannes Reinecke 				     current->comm));
17771da177e4SLinus Torvalds 
17781da177e4SLinus Torvalds 		rtn = scsi_try_host_reset(scmd);
17793eef6257SDavid Jeffery 		if (rtn == SUCCESS) {
17803eef6257SDavid Jeffery 			list_splice_init(work_q, &check_list);
17813eef6257SDavid Jeffery 		} else if (rtn == FAST_IO_FAIL) {
1782937abeaaSChristoph Hellwig 			list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
17831da177e4SLinus Torvalds 					scsi_eh_finish_cmd(scmd, done_q);
17841da177e4SLinus Torvalds 			}
17851da177e4SLinus Torvalds 		} else {
178691921e01SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
178791921e01SHannes Reinecke 				shost_printk(KERN_INFO, shost,
178891921e01SHannes Reinecke 					     "%s: HRST failed\n",
17891da177e4SLinus Torvalds 					     current->comm));
17901da177e4SLinus Torvalds 		}
17911da177e4SLinus Torvalds 	}
17923eef6257SDavid Jeffery 	return scsi_eh_test_devices(&check_list, work_q, done_q, 1);
17931da177e4SLinus Torvalds }
17941da177e4SLinus Torvalds 
17951da177e4SLinus Torvalds /**
17961da177e4SLinus Torvalds  * scsi_eh_offline_sdevs - offline scsi devices that fail to recover
179774cf298fSRandy Dunlap  * @work_q:	&list_head for pending commands.
179874cf298fSRandy Dunlap  * @done_q:	&list_head for processed commands.
1799dc8875e1SRandy Dunlap  */
scsi_eh_offline_sdevs(struct list_head * work_q,struct list_head * done_q)18001da177e4SLinus Torvalds static void scsi_eh_offline_sdevs(struct list_head *work_q,
18011da177e4SLinus Torvalds 				  struct list_head *done_q)
18021da177e4SLinus Torvalds {
1803937abeaaSChristoph Hellwig 	struct scsi_cmnd *scmd, *next;
18040db6ca8aSBart Van Assche 	struct scsi_device *sdev;
18051da177e4SLinus Torvalds 
1806937abeaaSChristoph Hellwig 	list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
180731765d7dSMatthew Wilcox 		sdev_printk(KERN_INFO, scmd->device, "Device offlined - "
180831765d7dSMatthew Wilcox 			    "not ready after error recovery\n");
18090db6ca8aSBart Van Assche 		sdev = scmd->device;
18100db6ca8aSBart Van Assche 
18110db6ca8aSBart Van Assche 		mutex_lock(&sdev->state_mutex);
18120db6ca8aSBart Van Assche 		scsi_device_set_state(sdev, SDEV_OFFLINE);
18130db6ca8aSBart Van Assche 		mutex_unlock(&sdev->state_mutex);
18140db6ca8aSBart Van Assche 
18151da177e4SLinus Torvalds 		scsi_eh_finish_cmd(scmd, done_q);
18161da177e4SLinus Torvalds 	}
18171da177e4SLinus Torvalds 	return;
18181da177e4SLinus Torvalds }
18191da177e4SLinus Torvalds 
18201da177e4SLinus Torvalds /**
1821e494f6a7SHannes Reinecke  * scsi_noretry_cmd - determine if command should be failed fast
18224a27446fSMike Christie  * @scmd:	SCSI cmd to examine.
18234a27446fSMike Christie  */
scsi_noretry_cmd(struct scsi_cmnd * scmd)182488b32c3cSBart Van Assche bool scsi_noretry_cmd(struct scsi_cmnd *scmd)
18254a27446fSMike Christie {
1826aa8e25e5SBart Van Assche 	struct request *req = scsi_cmd_to_rq(scmd);
1827aa8e25e5SBart Van Assche 
18284a27446fSMike Christie 	switch (host_byte(scmd->result)) {
18294a27446fSMike Christie 	case DID_OK:
18304a27446fSMike Christie 		break;
1831e494f6a7SHannes Reinecke 	case DID_TIME_OUT:
1832e494f6a7SHannes Reinecke 		goto check_type;
18334a27446fSMike Christie 	case DID_BUS_BUSY:
183488b32c3cSBart Van Assche 		return !!(req->cmd_flags & REQ_FAILFAST_TRANSPORT);
18354a27446fSMike Christie 	case DID_PARITY:
183688b32c3cSBart Van Assche 		return !!(req->cmd_flags & REQ_FAILFAST_DEV);
18374a27446fSMike Christie 	case DID_ERROR:
18383d45cefcSHannes Reinecke 		if (get_status_byte(scmd) == SAM_STAT_RESERVATION_CONFLICT)
183988b32c3cSBart Van Assche 			return false;
1840df561f66SGustavo A. R. Silva 		fallthrough;
18414a27446fSMike Christie 	case DID_SOFT_ERROR:
184288b32c3cSBart Van Assche 		return !!(req->cmd_flags & REQ_FAILFAST_DRIVER);
18434a27446fSMike Christie 	}
18444a27446fSMike Christie 
1845390e2d1aSNiklas Cassel 	/* Never retry commands aborted due to a duration limit timeout */
1846390e2d1aSNiklas Cassel 	if (scsi_ml_byte(scmd->result) == SCSIML_STAT_DL_TIMEOUT)
1847390e2d1aSNiklas Cassel 		return true;
1848390e2d1aSNiklas Cassel 
1849d0672a03SHannes Reinecke 	if (!scsi_status_is_check_condition(scmd->result))
185088b32c3cSBart Van Assche 		return false;
1851e494f6a7SHannes Reinecke 
1852e494f6a7SHannes Reinecke check_type:
18534a27446fSMike Christie 	/*
1854e494f6a7SHannes Reinecke 	 * assume caller has checked sense and determined
18554a27446fSMike Christie 	 * the check condition was retryable.
18564a27446fSMike Christie 	 */
1857aa8e25e5SBart Van Assche 	if (req->cmd_flags & REQ_FAILFAST_DEV || blk_rq_is_passthrough(req))
185888b32c3cSBart Van Assche 		return true;
1859342c81eeSDamien Le Moal 
186088b32c3cSBart Van Assche 	return false;
18614a27446fSMike Christie }
18624a27446fSMike Christie 
18634a27446fSMike Christie /**
18641da177e4SLinus Torvalds  * scsi_decide_disposition - Disposition a cmd on return from LLD.
18651da177e4SLinus Torvalds  * @scmd:	SCSI cmd to examine.
18661da177e4SLinus Torvalds  *
18671da177e4SLinus Torvalds  * Notes:
18681da177e4SLinus Torvalds  *    This is *only* called when we are examining the status after sending
18691da177e4SLinus Torvalds  *    out the actual data command.  any commands that are queued for error
18701da177e4SLinus Torvalds  *    recovery (e.g. test_unit_ready) do *not* come through here.
18711da177e4SLinus Torvalds  *
18721da177e4SLinus Torvalds  *    When this routine returns failed, it means the error handler thread
18731da177e4SLinus Torvalds  *    is woken.  In cases where the error code indicates an error that
18741da177e4SLinus Torvalds  *    doesn't require the error handler read (i.e. we don't need to
18751da177e4SLinus Torvalds  *    abort/reset), this function should return SUCCESS.
1876dc8875e1SRandy Dunlap  */
scsi_decide_disposition(struct scsi_cmnd * scmd)1877b8e162f9SBart Van Assche enum scsi_disposition scsi_decide_disposition(struct scsi_cmnd *scmd)
18781da177e4SLinus Torvalds {
1879b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
18801da177e4SLinus Torvalds 
18811da177e4SLinus Torvalds 	/*
18821da177e4SLinus Torvalds 	 * if the device is offline, then we clearly just pass the result back
18831da177e4SLinus Torvalds 	 * up to the top level.
18841da177e4SLinus Torvalds 	 */
18851da177e4SLinus Torvalds 	if (!scsi_device_online(scmd->device)) {
188691921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(5, scmd_printk(KERN_INFO, scmd,
188791921e01SHannes Reinecke 			"%s: device offline - report as SUCCESS\n", __func__));
18881da177e4SLinus Torvalds 		return SUCCESS;
18891da177e4SLinus Torvalds 	}
18901da177e4SLinus Torvalds 
18911da177e4SLinus Torvalds 	/*
18921da177e4SLinus Torvalds 	 * first check the host byte, to see if there is anything in there
18931da177e4SLinus Torvalds 	 * that would indicate what we need to do.
18941da177e4SLinus Torvalds 	 */
18951da177e4SLinus Torvalds 	switch (host_byte(scmd->result)) {
18961da177e4SLinus Torvalds 	case DID_PASSTHROUGH:
18971da177e4SLinus Torvalds 		/*
18981da177e4SLinus Torvalds 		 * no matter what, pass this through to the upper layer.
18991da177e4SLinus Torvalds 		 * nuke this special code so that it looks like we are saying
19001da177e4SLinus Torvalds 		 * did_ok.
19011da177e4SLinus Torvalds 		 */
19021da177e4SLinus Torvalds 		scmd->result &= 0xff00ffff;
19031da177e4SLinus Torvalds 		return SUCCESS;
19041da177e4SLinus Torvalds 	case DID_OK:
19051da177e4SLinus Torvalds 		/*
19061da177e4SLinus Torvalds 		 * looks good.  drop through, and check the next byte.
19071da177e4SLinus Torvalds 		 */
19081da177e4SLinus Torvalds 		break;
1909e494f6a7SHannes Reinecke 	case DID_ABORT:
1910e494f6a7SHannes Reinecke 		if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) {
19118922a908SUlrich Obergfell 			set_host_byte(scmd, DID_TIME_OUT);
1912e494f6a7SHannes Reinecke 			return SUCCESS;
1913e494f6a7SHannes Reinecke 		}
1914df561f66SGustavo A. R. Silva 		fallthrough;
19151da177e4SLinus Torvalds 	case DID_NO_CONNECT:
19161da177e4SLinus Torvalds 	case DID_BAD_TARGET:
19171da177e4SLinus Torvalds 		/*
19181da177e4SLinus Torvalds 		 * note - this means that we just report the status back
19191da177e4SLinus Torvalds 		 * to the top level driver, not that we actually think
19201da177e4SLinus Torvalds 		 * that it indicates SUCCESS.
19211da177e4SLinus Torvalds 		 */
19221da177e4SLinus Torvalds 		return SUCCESS;
1923ad95028aSPetros Koutoupis 	case DID_SOFT_ERROR:
19241da177e4SLinus Torvalds 		/*
19251da177e4SLinus Torvalds 		 * when the low level driver returns did_soft_error,
19261da177e4SLinus Torvalds 		 * it is responsible for keeping an internal retry counter
19271da177e4SLinus Torvalds 		 * in order to avoid endless loops (db)
19281da177e4SLinus Torvalds 		 */
19291da177e4SLinus Torvalds 		goto maybe_retry;
19301da177e4SLinus Torvalds 	case DID_IMM_RETRY:
19311da177e4SLinus Torvalds 		return NEEDS_RETRY;
19321da177e4SLinus Torvalds 
1933bf341919S 	case DID_REQUEUE:
1934bf341919S 		return ADD_TO_MLQUEUE;
1935a4dfaa6fSMike Christie 	case DID_TRANSPORT_DISRUPTED:
1936a4dfaa6fSMike Christie 		/*
1937a4dfaa6fSMike Christie 		 * LLD/transport was disrupted during processing of the IO.
1938a4dfaa6fSMike Christie 		 * The transport class is now blocked/blocking,
1939a4dfaa6fSMike Christie 		 * and the transport will decide what to do with the IO
1940939c2288SMike Christie 		 * based on its timers and recovery capablilities if
1941939c2288SMike Christie 		 * there are enough retries.
1942a4dfaa6fSMike Christie 		 */
1943939c2288SMike Christie 		goto maybe_retry;
1944a4dfaa6fSMike Christie 	case DID_TRANSPORT_FAILFAST:
1945a4dfaa6fSMike Christie 		/*
1946a4dfaa6fSMike Christie 		 * The transport decided to failfast the IO (most likely
1947a4dfaa6fSMike Christie 		 * the fast io fail tmo fired), so send IO directly upwards.
1948a4dfaa6fSMike Christie 		 */
1949a4dfaa6fSMike Christie 		return SUCCESS;
1950962c8dcdSMuneendra Kumar 	case DID_TRANSPORT_MARGINAL:
1951962c8dcdSMuneendra Kumar 		/*
1952962c8dcdSMuneendra Kumar 		 * caller has decided not to do retries on
1953962c8dcdSMuneendra Kumar 		 * abort success, so send IO directly upwards
1954962c8dcdSMuneendra Kumar 		 */
1955962c8dcdSMuneendra Kumar 		return SUCCESS;
19561da177e4SLinus Torvalds 	case DID_ERROR:
19573d45cefcSHannes Reinecke 		if (get_status_byte(scmd) == SAM_STAT_RESERVATION_CONFLICT)
19581da177e4SLinus Torvalds 			/*
19591da177e4SLinus Torvalds 			 * execute reservation conflict processing code
19601da177e4SLinus Torvalds 			 * lower down
19611da177e4SLinus Torvalds 			 */
19621da177e4SLinus Torvalds 			break;
1963df561f66SGustavo A. R. Silva 		fallthrough;
19641da177e4SLinus Torvalds 	case DID_BUS_BUSY:
19651da177e4SLinus Torvalds 	case DID_PARITY:
19661da177e4SLinus Torvalds 		goto maybe_retry;
19671da177e4SLinus Torvalds 	case DID_TIME_OUT:
19681da177e4SLinus Torvalds 		/*
19691da177e4SLinus Torvalds 		 * when we scan the bus, we get timeout messages for
19701da177e4SLinus Torvalds 		 * these commands if there is no device available.
19711da177e4SLinus Torvalds 		 * other hosts report did_no_connect for the same thing.
19721da177e4SLinus Torvalds 		 */
19731da177e4SLinus Torvalds 		if ((scmd->cmnd[0] == TEST_UNIT_READY ||
19741da177e4SLinus Torvalds 		     scmd->cmnd[0] == INQUIRY)) {
19751da177e4SLinus Torvalds 			return SUCCESS;
19761da177e4SLinus Torvalds 		} else {
19771da177e4SLinus Torvalds 			return FAILED;
19781da177e4SLinus Torvalds 		}
19791da177e4SLinus Torvalds 	case DID_RESET:
19801da177e4SLinus Torvalds 		return SUCCESS;
19811da177e4SLinus Torvalds 	default:
19821da177e4SLinus Torvalds 		return FAILED;
19831da177e4SLinus Torvalds 	}
19841da177e4SLinus Torvalds 
19851da177e4SLinus Torvalds 	/*
19861da177e4SLinus Torvalds 	 * check the status byte to see if this indicates anything special.
19871da177e4SLinus Torvalds 	 */
19883d45cefcSHannes Reinecke 	switch (get_status_byte(scmd)) {
19893d45cefcSHannes Reinecke 	case SAM_STAT_TASK_SET_FULL:
199042a6a918SMike Christie 		scsi_handle_queue_full(scmd->device);
19911da177e4SLinus Torvalds 		/*
19921da177e4SLinus Torvalds 		 * the case of trying to send too many commands to a
19931da177e4SLinus Torvalds 		 * tagged queueing device.
19941da177e4SLinus Torvalds 		 */
1995df561f66SGustavo A. R. Silva 		fallthrough;
19963d45cefcSHannes Reinecke 	case SAM_STAT_BUSY:
19971da177e4SLinus Torvalds 		/*
19981da177e4SLinus Torvalds 		 * device can't talk to us at the moment.  Should only
19991da177e4SLinus Torvalds 		 * occur (SAM-3) when the task queue is empty, so will cause
20001da177e4SLinus Torvalds 		 * the empty queue handling to trigger a stall in the
20011da177e4SLinus Torvalds 		 * device.
20021da177e4SLinus Torvalds 		 */
20031da177e4SLinus Torvalds 		return ADD_TO_MLQUEUE;
20043d45cefcSHannes Reinecke 	case SAM_STAT_GOOD:
2005279afdfeSEwan D. Milne 		if (scmd->cmnd[0] == REPORT_LUNS)
2006279afdfeSEwan D. Milne 			scmd->device->sdev_target->expecting_lun_change = 0;
20074a84067dSVasu Dev 		scsi_handle_queue_ramp_up(scmd->device);
2008390e2d1aSNiklas Cassel 		if (scmd->sense_buffer && SCSI_SENSE_VALID(scmd))
2009390e2d1aSNiklas Cassel 			/*
2010390e2d1aSNiklas Cassel 			 * If we have sense data, call scsi_check_sense() in
2011390e2d1aSNiklas Cassel 			 * order to set the correct SCSI ML byte (if any).
2012390e2d1aSNiklas Cassel 			 * No point in checking the return value, since the
2013390e2d1aSNiklas Cassel 			 * command has already completed successfully.
2014390e2d1aSNiklas Cassel 			 */
2015390e2d1aSNiklas Cassel 			scsi_check_sense(scmd);
2016df561f66SGustavo A. R. Silva 		fallthrough;
20173d45cefcSHannes Reinecke 	case SAM_STAT_COMMAND_TERMINATED:
20181da177e4SLinus Torvalds 		return SUCCESS;
20193d45cefcSHannes Reinecke 	case SAM_STAT_TASK_ABORTED:
2020a9b589d9SVladislav Bolkhovitin 		goto maybe_retry;
20213d45cefcSHannes Reinecke 	case SAM_STAT_CHECK_CONDITION:
20221da177e4SLinus Torvalds 		rtn = scsi_check_sense(scmd);
20231da177e4SLinus Torvalds 		if (rtn == NEEDS_RETRY)
20241da177e4SLinus Torvalds 			goto maybe_retry;
20251da177e4SLinus Torvalds 		/* if rtn == FAILED, we have no sense information;
20261da177e4SLinus Torvalds 		 * returning FAILED will wake the error handler thread
20271da177e4SLinus Torvalds 		 * to collect the sense and redo the decide
20281da177e4SLinus Torvalds 		 * disposition */
20291da177e4SLinus Torvalds 		return rtn;
20303d45cefcSHannes Reinecke 	case SAM_STAT_CONDITION_MET:
20313d45cefcSHannes Reinecke 	case SAM_STAT_INTERMEDIATE:
20323d45cefcSHannes Reinecke 	case SAM_STAT_INTERMEDIATE_CONDITION_MET:
20333d45cefcSHannes Reinecke 	case SAM_STAT_ACA_ACTIVE:
20341da177e4SLinus Torvalds 		/*
20351da177e4SLinus Torvalds 		 * who knows?  FIXME(eric)
20361da177e4SLinus Torvalds 		 */
20371da177e4SLinus Torvalds 		return SUCCESS;
20381da177e4SLinus Torvalds 
20393d45cefcSHannes Reinecke 	case SAM_STAT_RESERVATION_CONFLICT:
20409ccfc756SJames Bottomley 		sdev_printk(KERN_INFO, scmd->device,
20419ccfc756SJames Bottomley 			    "reservation conflict\n");
20427dfaae6aSMike Christie 		set_scsi_ml_byte(scmd, SCSIML_STAT_RESV_CONFLICT);
20431da177e4SLinus Torvalds 		return SUCCESS; /* causes immediate i/o error */
20441da177e4SLinus Torvalds 	}
20451da177e4SLinus Torvalds 	return FAILED;
20461da177e4SLinus Torvalds 
20471da177e4SLinus Torvalds maybe_retry:
20481da177e4SLinus Torvalds 
20491da177e4SLinus Torvalds 	/* we requeue for retry because the error was retryable, and
20501da177e4SLinus Torvalds 	 * the request was not marked fast fail.  Note that above,
20511da177e4SLinus Torvalds 	 * even if the request is marked fast fail, we still requeue
20521da177e4SLinus Torvalds 	 * for queue congestion conditions (QUEUE_FULL or BUSY) */
20532a242d59SMike Christie 	if (scsi_cmd_retry_allowed(scmd) && !scsi_noretry_cmd(scmd)) {
20541da177e4SLinus Torvalds 		return NEEDS_RETRY;
20551da177e4SLinus Torvalds 	} else {
20561da177e4SLinus Torvalds 		/*
20571da177e4SLinus Torvalds 		 * no more retries - report this one back to upper level.
20581da177e4SLinus Torvalds 		 */
20591da177e4SLinus Torvalds 		return SUCCESS;
20601da177e4SLinus Torvalds 	}
20611da177e4SLinus Torvalds }
20621da177e4SLinus Torvalds 
eh_lock_door_done(struct request * req,blk_status_t status)2063de671d61SJens Axboe static enum rq_end_io_ret eh_lock_door_done(struct request *req,
2064de671d61SJens Axboe 					    blk_status_t status)
2065f078727bSFUJITA Tomonori {
20660bf6d96cSChristoph Hellwig 	blk_mq_free_request(req);
2067de671d61SJens Axboe 	return RQ_END_IO_NONE;
2068f078727bSFUJITA Tomonori }
2069f078727bSFUJITA Tomonori 
20701da177e4SLinus Torvalds /**
20711da177e4SLinus Torvalds  * scsi_eh_lock_door - Prevent medium removal for the specified device
20721da177e4SLinus Torvalds  * @sdev:	SCSI device to prevent medium removal
20731da177e4SLinus Torvalds  *
20741da177e4SLinus Torvalds  * Locking:
207591bc31fbSJames Bottomley  * 	We must be called from process context.
20761da177e4SLinus Torvalds  *
20771da177e4SLinus Torvalds  * Notes:
20781da177e4SLinus Torvalds  * 	We queue up an asynchronous "ALLOW MEDIUM REMOVAL" request on the
20791da177e4SLinus Torvalds  * 	head of the devices request queue, and continue.
2080dc8875e1SRandy Dunlap  */
scsi_eh_lock_door(struct scsi_device * sdev)20811da177e4SLinus Torvalds static void scsi_eh_lock_door(struct scsi_device *sdev)
20821da177e4SLinus Torvalds {
2083ce70fd9aSChristoph Hellwig 	struct scsi_cmnd *scmd;
2084f078727bSFUJITA Tomonori 	struct request *req;
20851da177e4SLinus Torvalds 
208668ec3b81SChristoph Hellwig 	req = scsi_alloc_request(sdev->request_queue, REQ_OP_DRV_IN, 0);
2087a492f075SJoe Lawrence 	if (IS_ERR(req))
2088eb571eeaSJoe Lawrence 		return;
2089ce70fd9aSChristoph Hellwig 	scmd = blk_mq_rq_to_pdu(req);
20901da177e4SLinus Torvalds 
2091ce70fd9aSChristoph Hellwig 	scmd->cmnd[0] = ALLOW_MEDIUM_REMOVAL;
2092ce70fd9aSChristoph Hellwig 	scmd->cmnd[1] = 0;
2093ce70fd9aSChristoph Hellwig 	scmd->cmnd[2] = 0;
2094ce70fd9aSChristoph Hellwig 	scmd->cmnd[3] = 0;
2095ce70fd9aSChristoph Hellwig 	scmd->cmnd[4] = SCSI_REMOVAL_PREVENT;
2096ce70fd9aSChristoph Hellwig 	scmd->cmnd[5] = 0;
2097ce70fd9aSChristoph Hellwig 	scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
2098e2e53086SChristoph Hellwig 	scmd->allowed = 5;
2099f078727bSFUJITA Tomonori 
2100e8064021SChristoph Hellwig 	req->rq_flags |= RQF_QUIET;
2101f078727bSFUJITA Tomonori 	req->timeout = 10 * HZ;
2102e2e53086SChristoph Hellwig 	req->end_io = eh_lock_door_done;
2103f078727bSFUJITA Tomonori 
2104e2e53086SChristoph Hellwig 	blk_execute_rq_nowait(req, true);
21051da177e4SLinus Torvalds }
21061da177e4SLinus Torvalds 
21071da177e4SLinus Torvalds /**
21081da177e4SLinus Torvalds  * scsi_restart_operations - restart io operations to the specified host.
21091da177e4SLinus Torvalds  * @shost:	Host we are restarting.
21101da177e4SLinus Torvalds  *
21111da177e4SLinus Torvalds  * Notes:
21121da177e4SLinus Torvalds  *    When we entered the error handler, we blocked all further i/o to
21131da177e4SLinus Torvalds  *    this device.  we need to 'reverse' this process.
2114dc8875e1SRandy Dunlap  */
scsi_restart_operations(struct Scsi_Host * shost)21151da177e4SLinus Torvalds static void scsi_restart_operations(struct Scsi_Host *shost)
21161da177e4SLinus Torvalds {
21171da177e4SLinus Torvalds 	struct scsi_device *sdev;
2118939647eeSJames Bottomley 	unsigned long flags;
21191da177e4SLinus Torvalds 
21201da177e4SLinus Torvalds 	/*
21211da177e4SLinus Torvalds 	 * If the door was locked, we need to insert a door lock request
21221da177e4SLinus Torvalds 	 * onto the head of the SCSI request queue for the device.  There
21231da177e4SLinus Torvalds 	 * is no point trying to lock the door of an off-line device.
21241da177e4SLinus Torvalds 	 */
21251da177e4SLinus Torvalds 	shost_for_each_device(sdev, shost) {
212648379270SChristoph Hellwig 		if (scsi_device_online(sdev) && sdev->was_reset && sdev->locked) {
21271da177e4SLinus Torvalds 			scsi_eh_lock_door(sdev);
212848379270SChristoph Hellwig 			sdev->was_reset = 0;
212948379270SChristoph Hellwig 		}
21301da177e4SLinus Torvalds 	}
21311da177e4SLinus Torvalds 
21321da177e4SLinus Torvalds 	/*
21331da177e4SLinus Torvalds 	 * next free up anything directly waiting upon the host.  this
21341da177e4SLinus Torvalds 	 * will be requests for character device operations, and also for
21351da177e4SLinus Torvalds 	 * ioctls to queued block devices.
21361da177e4SLinus Torvalds 	 */
2137b4562022SHannes Reinecke 	SCSI_LOG_ERROR_RECOVERY(3,
213891921e01SHannes Reinecke 		shost_printk(KERN_INFO, shost, "waking up host to restart\n"));
21391da177e4SLinus Torvalds 
2140939647eeSJames Bottomley 	spin_lock_irqsave(shost->host_lock, flags);
2141939647eeSJames Bottomley 	if (scsi_host_set_state(shost, SHOST_RUNNING))
2142939647eeSJames Bottomley 		if (scsi_host_set_state(shost, SHOST_CANCEL))
2143939647eeSJames Bottomley 			BUG_ON(scsi_host_set_state(shost, SHOST_DEL));
2144939647eeSJames Bottomley 	spin_unlock_irqrestore(shost->host_lock, flags);
21451da177e4SLinus Torvalds 
21461da177e4SLinus Torvalds 	wake_up(&shost->host_wait);
21471da177e4SLinus Torvalds 
21481da177e4SLinus Torvalds 	/*
21491da177e4SLinus Torvalds 	 * finally we need to re-initiate requests that may be pending.  we will
21501da177e4SLinus Torvalds 	 * have had everything blocked while error handling is taking place, and
21511da177e4SLinus Torvalds 	 * now that error recovery is done, we will need to ensure that these
21521da177e4SLinus Torvalds 	 * requests are started.
21531da177e4SLinus Torvalds 	 */
21541da177e4SLinus Torvalds 	scsi_run_host_queues(shost);
215557fc2e33SDan Williams 
215657fc2e33SDan Williams 	/*
215757fc2e33SDan Williams 	 * if eh is active and host_eh_scheduled is pending we need to re-run
215857fc2e33SDan Williams 	 * recovery.  we do this check after scsi_run_host_queues() to allow
215957fc2e33SDan Williams 	 * everything pent up since the last eh run a chance to make forward
216057fc2e33SDan Williams 	 * progress before we sync again.  Either we'll immediately re-run
216157fc2e33SDan Williams 	 * recovery or scsi_device_unbusy() will wake us again when these
216257fc2e33SDan Williams 	 * pending commands complete.
216357fc2e33SDan Williams 	 */
216457fc2e33SDan Williams 	spin_lock_irqsave(shost->host_lock, flags);
216557fc2e33SDan Williams 	if (shost->host_eh_scheduled)
216657fc2e33SDan Williams 		if (scsi_host_set_state(shost, SHOST_RECOVERY))
216757fc2e33SDan Williams 			WARN_ON(scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY));
216857fc2e33SDan Williams 	spin_unlock_irqrestore(shost->host_lock, flags);
21691da177e4SLinus Torvalds }
21701da177e4SLinus Torvalds 
21711da177e4SLinus Torvalds /**
21721da177e4SLinus Torvalds  * scsi_eh_ready_devs - check device ready state and recover if not.
21731da177e4SLinus Torvalds  * @shost:	host to be recovered.
2174eb44820cSRob Landley  * @work_q:	&list_head for pending commands.
2175eb44820cSRob Landley  * @done_q:	&list_head for processed commands.
2176dc8875e1SRandy Dunlap  */
scsi_eh_ready_devs(struct Scsi_Host * shost,struct list_head * work_q,struct list_head * done_q)2177dca84e46SDarrick J. Wong void scsi_eh_ready_devs(struct Scsi_Host *shost,
21781da177e4SLinus Torvalds 			struct list_head *work_q,
21791da177e4SLinus Torvalds 			struct list_head *done_q)
21801da177e4SLinus Torvalds {
21811da177e4SLinus Torvalds 	if (!scsi_eh_stu(shost, work_q, done_q))
21821da177e4SLinus Torvalds 		if (!scsi_eh_bus_device_reset(shost, work_q, done_q))
218330bd7df8SMike Christie 			if (!scsi_eh_target_reset(shost, work_q, done_q))
21841da177e4SLinus Torvalds 				if (!scsi_eh_bus_reset(shost, work_q, done_q))
218591921e01SHannes Reinecke 					if (!scsi_eh_host_reset(shost, work_q, done_q))
218630bd7df8SMike Christie 						scsi_eh_offline_sdevs(work_q,
218730bd7df8SMike Christie 								      done_q);
21881da177e4SLinus Torvalds }
2189dca84e46SDarrick J. Wong EXPORT_SYMBOL_GPL(scsi_eh_ready_devs);
21901da177e4SLinus Torvalds 
21911da177e4SLinus Torvalds /**
21921da177e4SLinus Torvalds  * scsi_eh_flush_done_q - finish processed commands or retry them.
21931da177e4SLinus Torvalds  * @done_q:	list_head of processed commands.
2194dc8875e1SRandy Dunlap  */
scsi_eh_flush_done_q(struct list_head * done_q)2195041c5fc3STejun Heo void scsi_eh_flush_done_q(struct list_head *done_q)
21961da177e4SLinus Torvalds {
2197937abeaaSChristoph Hellwig 	struct scsi_cmnd *scmd, *next;
21981da177e4SLinus Torvalds 
2199937abeaaSChristoph Hellwig 	list_for_each_entry_safe(scmd, next, done_q, eh_entry) {
22003b4b35d7SNiklas Cassel 		struct scsi_device *sdev = scmd->device;
22013b4b35d7SNiklas Cassel 
2202937abeaaSChristoph Hellwig 		list_del_init(&scmd->eh_entry);
22033b4b35d7SNiklas Cassel 		if (scsi_device_online(sdev) && !scsi_noretry_cmd(scmd) &&
22043b4b35d7SNiklas Cassel 		    scsi_cmd_retry_allowed(scmd) &&
220560bee27bSMuneendra Kumar 		    scsi_eh_should_retry_cmd(scmd)) {
220691921e01SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
220791921e01SHannes Reinecke 				scmd_printk(KERN_INFO, scmd,
2208470613b4SHannes Reinecke 					     "%s: flush retry cmd\n",
2209470613b4SHannes Reinecke 					     current->comm));
22101da177e4SLinus Torvalds 				scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY);
22113b4b35d7SNiklas Cassel 				blk_mq_kick_requeue_list(sdev->request_queue);
22121da177e4SLinus Torvalds 		} else {
2213793698ceSPatrick Mansfield  			/*
2214793698ceSPatrick Mansfield  			 * If just we got sense for the device (called
2215793698ceSPatrick Mansfield  			 * scsi_eh_get_sense), scmd->result is already
22164bd51e54SHannes Reinecke 			 * set, do not set DID_TIME_OUT.
2217793698ceSPatrick Mansfield  			 */
22183d848ca1SNiklas Cassel 			if (!scmd->result &&
22193d848ca1SNiklas Cassel 			    !(scmd->flags & SCMD_FORCE_EH_SUCCESS))
22204bd51e54SHannes Reinecke 				scmd->result |= (DID_TIME_OUT << 16);
222191921e01SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
222291921e01SHannes Reinecke 				scmd_printk(KERN_INFO, scmd,
2223470613b4SHannes Reinecke 					     "%s: flush finish cmd\n",
2224470613b4SHannes Reinecke 					     current->comm));
22251da177e4SLinus Torvalds 			scsi_finish_command(scmd);
22261da177e4SLinus Torvalds 		}
22271da177e4SLinus Torvalds 	}
22281da177e4SLinus Torvalds }
2229041c5fc3STejun Heo EXPORT_SYMBOL(scsi_eh_flush_done_q);
22301da177e4SLinus Torvalds 
22311da177e4SLinus Torvalds /**
22321da177e4SLinus Torvalds  * scsi_unjam_host - Attempt to fix a host which has a cmd that failed.
22331da177e4SLinus Torvalds  * @shost:	Host to unjam.
22341da177e4SLinus Torvalds  *
22351da177e4SLinus Torvalds  * Notes:
22361da177e4SLinus Torvalds  *    When we come in here, we *know* that all commands on the bus have
22371da177e4SLinus Torvalds  *    either completed, failed or timed out.  we also know that no further
22381da177e4SLinus Torvalds  *    commands are being sent to the host, so things are relatively quiet
22391da177e4SLinus Torvalds  *    and we have freedom to fiddle with things as we wish.
22401da177e4SLinus Torvalds  *
22411da177e4SLinus Torvalds  *    This is only the *default* implementation.  it is possible for
22421da177e4SLinus Torvalds  *    individual drivers to supply their own version of this function, and
22431da177e4SLinus Torvalds  *    if the maintainer wishes to do this, it is strongly suggested that
22441da177e4SLinus Torvalds  *    this function be taken as a template and modified.  this function
22451da177e4SLinus Torvalds  *    was designed to correctly handle problems for about 95% of the
22461da177e4SLinus Torvalds  *    different cases out there, and it should always provide at least a
22471da177e4SLinus Torvalds  *    reasonable amount of error recovery.
22481da177e4SLinus Torvalds  *
22491da177e4SLinus Torvalds  *    Any command marked 'failed' or 'timeout' must eventually have
22501da177e4SLinus Torvalds  *    scsi_finish_cmd() called for it.  we do all of the retry stuff
22511da177e4SLinus Torvalds  *    here, so when we restart the host after we return it should have an
22521da177e4SLinus Torvalds  *    empty queue.
2253dc8875e1SRandy Dunlap  */
scsi_unjam_host(struct Scsi_Host * shost)22541da177e4SLinus Torvalds static void scsi_unjam_host(struct Scsi_Host *shost)
22551da177e4SLinus Torvalds {
22561da177e4SLinus Torvalds 	unsigned long flags;
22571da177e4SLinus Torvalds 	LIST_HEAD(eh_work_q);
22581da177e4SLinus Torvalds 	LIST_HEAD(eh_done_q);
22591da177e4SLinus Torvalds 
22601da177e4SLinus Torvalds 	spin_lock_irqsave(shost->host_lock, flags);
22611da177e4SLinus Torvalds 	list_splice_init(&shost->eh_cmd_q, &eh_work_q);
22621da177e4SLinus Torvalds 	spin_unlock_irqrestore(shost->host_lock, flags);
22631da177e4SLinus Torvalds 
22641da177e4SLinus Torvalds 	SCSI_LOG_ERROR_RECOVERY(1, scsi_eh_prt_fail_stats(shost, &eh_work_q));
22651da177e4SLinus Torvalds 
22661da177e4SLinus Torvalds 	if (!scsi_eh_get_sense(&eh_work_q, &eh_done_q))
22671da177e4SLinus Torvalds 		scsi_eh_ready_devs(shost, &eh_work_q, &eh_done_q);
22681da177e4SLinus Torvalds 
2269b4562022SHannes Reinecke 	spin_lock_irqsave(shost->host_lock, flags);
2270bb3b621aSRen Mingxin 	if (shost->eh_deadline != -1)
2271b4562022SHannes Reinecke 		shost->last_reset = 0;
2272b4562022SHannes Reinecke 	spin_unlock_irqrestore(shost->host_lock, flags);
22731da177e4SLinus Torvalds 	scsi_eh_flush_done_q(&eh_done_q);
22741da177e4SLinus Torvalds }
22751da177e4SLinus Torvalds 
22761da177e4SLinus Torvalds /**
2277ad42eb1bSChristoph Hellwig  * scsi_error_handler - SCSI error handler thread
22781da177e4SLinus Torvalds  * @data:	Host for which we are running.
22791da177e4SLinus Torvalds  *
22801da177e4SLinus Torvalds  * Notes:
2281ad42eb1bSChristoph Hellwig  *    This is the main error handling loop.  This is run as a kernel thread
2282ad42eb1bSChristoph Hellwig  *    for every SCSI host and handles all error handling activity.
2283dc8875e1SRandy Dunlap  */
scsi_error_handler(void * data)22841da177e4SLinus Torvalds int scsi_error_handler(void *data)
22851da177e4SLinus Torvalds {
2286ad42eb1bSChristoph Hellwig 	struct Scsi_Host *shost = data;
22871da177e4SLinus Torvalds 
22881da177e4SLinus Torvalds 	/*
2289ad42eb1bSChristoph Hellwig 	 * We use TASK_INTERRUPTIBLE so that the thread is not
2290ad42eb1bSChristoph Hellwig 	 * counted against the load average as a running process.
2291ad42eb1bSChristoph Hellwig 	 * We never actually get interrupted because kthread_run
2292c03264a7SFrederik Schwarzer 	 * disables signal delivery for the created thread.
22931da177e4SLinus Torvalds 	 */
2294537b604cSMichal Hocko 	while (true) {
2295537b604cSMichal Hocko 		/*
2296537b604cSMichal Hocko 		 * The sequence in kthread_stop() sets the stop flag first
2297537b604cSMichal Hocko 		 * then wakes the process.  To avoid missed wakeups, the task
2298537b604cSMichal Hocko 		 * should always be in a non running state before the stop
2299537b604cSMichal Hocko 		 * flag is checked
2300537b604cSMichal Hocko 		 */
2301b9d5c6b7SDan Williams 		set_current_state(TASK_INTERRUPTIBLE);
2302537b604cSMichal Hocko 		if (kthread_should_stop())
2303537b604cSMichal Hocko 			break;
2304537b604cSMichal Hocko 
2305ee7863bcSTejun Heo 		if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) ||
2306c84b023aSMing Lei 		    shost->host_failed != scsi_host_busy(shost)) {
2307ad42eb1bSChristoph Hellwig 			SCSI_LOG_ERROR_RECOVERY(1,
230891921e01SHannes Reinecke 				shost_printk(KERN_INFO, shost,
230991921e01SHannes Reinecke 					     "scsi_eh_%d: sleeping\n",
23103ed7a470SJames Bottomley 					     shost->host_no));
23113ed7a470SJames Bottomley 			schedule();
23123ed7a470SJames Bottomley 			continue;
23133ed7a470SJames Bottomley 		}
23141da177e4SLinus Torvalds 
23153ed7a470SJames Bottomley 		__set_current_state(TASK_RUNNING);
2316ad42eb1bSChristoph Hellwig 		SCSI_LOG_ERROR_RECOVERY(1,
231791921e01SHannes Reinecke 			shost_printk(KERN_INFO, shost,
231891921e01SHannes Reinecke 				     "scsi_eh_%d: waking up %d/%d/%d\n",
2319b4562022SHannes Reinecke 				     shost->host_no, shost->host_eh_scheduled,
232074665016SChristoph Hellwig 				     shost->host_failed,
2321c84b023aSMing Lei 				     scsi_host_busy(shost)));
23221da177e4SLinus Torvalds 
23231da177e4SLinus Torvalds 		/*
23241da177e4SLinus Torvalds 		 * We have a host that is failing for some reason.  Figure out
23251da177e4SLinus Torvalds 		 * what we need to do to get it up and online again (if we can).
23261da177e4SLinus Torvalds 		 * If we fail, we end up taking the thing offline.
23271da177e4SLinus Torvalds 		 */
2328ae0751ffSLin Ming 		if (!shost->eh_noresume && scsi_autopm_get_host(shost) != 0) {
2329bc4f2401SAlan Stern 			SCSI_LOG_ERROR_RECOVERY(1,
2330a222b1e2SHannes Reinecke 				shost_printk(KERN_ERR, shost,
2331a222b1e2SHannes Reinecke 					     "scsi_eh_%d: unable to autoresume\n",
2332bc4f2401SAlan Stern 					     shost->host_no));
2333bc4f2401SAlan Stern 			continue;
2334bc4f2401SAlan Stern 		}
2335bc4f2401SAlan Stern 
23369227c33dSChristoph Hellwig 		if (shost->transportt->eh_strategy_handler)
23379227c33dSChristoph Hellwig 			shost->transportt->eh_strategy_handler(shost);
23381da177e4SLinus Torvalds 		else
23391da177e4SLinus Torvalds 			scsi_unjam_host(shost);
23401da177e4SLinus Torvalds 
234172d8c36eSWei Fang 		/* All scmds have been handled */
234272d8c36eSWei Fang 		shost->host_failed = 0;
234372d8c36eSWei Fang 
23441da177e4SLinus Torvalds 		/*
23451da177e4SLinus Torvalds 		 * Note - if the above fails completely, the action is to take
23461da177e4SLinus Torvalds 		 * individual devices offline and flush the queue of any
23471da177e4SLinus Torvalds 		 * outstanding requests that may have been pending.  When we
23481da177e4SLinus Torvalds 		 * restart, we restart any I/O to any other devices on the bus
23491da177e4SLinus Torvalds 		 * which are still online.
23501da177e4SLinus Torvalds 		 */
23511da177e4SLinus Torvalds 		scsi_restart_operations(shost);
2352ae0751ffSLin Ming 		if (!shost->eh_noresume)
2353bc4f2401SAlan Stern 			scsi_autopm_put_host(shost);
23541da177e4SLinus Torvalds 	}
2355461a0ffbSSteven Rostedt 	__set_current_state(TASK_RUNNING);
2356461a0ffbSSteven Rostedt 
2357ad42eb1bSChristoph Hellwig 	SCSI_LOG_ERROR_RECOVERY(1,
235891921e01SHannes Reinecke 		shost_printk(KERN_INFO, shost,
235991921e01SHannes Reinecke 			     "Error handler scsi_eh_%d exiting\n",
236091921e01SHannes Reinecke 			     shost->host_no));
23613ed7a470SJames Bottomley 	shost->ehandler = NULL;
23621da177e4SLinus Torvalds 	return 0;
23631da177e4SLinus Torvalds }
23641da177e4SLinus Torvalds 
23651da177e4SLinus Torvalds /*
23661da177e4SLinus Torvalds  * Function:    scsi_report_bus_reset()
23671da177e4SLinus Torvalds  *
23681da177e4SLinus Torvalds  * Purpose:     Utility function used by low-level drivers to report that
23691da177e4SLinus Torvalds  *		they have observed a bus reset on the bus being handled.
23701da177e4SLinus Torvalds  *
23711da177e4SLinus Torvalds  * Arguments:   shost       - Host in question
23721da177e4SLinus Torvalds  *		channel     - channel on which reset was observed.
23731da177e4SLinus Torvalds  *
23741da177e4SLinus Torvalds  * Returns:     Nothing
23751da177e4SLinus Torvalds  *
23761da177e4SLinus Torvalds  * Lock status: Host lock must be held.
23771da177e4SLinus Torvalds  *
23781da177e4SLinus Torvalds  * Notes:       This only needs to be called if the reset is one which
23791da177e4SLinus Torvalds  *		originates from an unknown location.  Resets originated
23801da177e4SLinus Torvalds  *		by the mid-level itself don't need to call this, but there
23811da177e4SLinus Torvalds  *		should be no harm.
23821da177e4SLinus Torvalds  *
23831da177e4SLinus Torvalds  *		The main purpose of this is to make sure that a CHECK_CONDITION
23841da177e4SLinus Torvalds  *		is properly treated.
23851da177e4SLinus Torvalds  */
scsi_report_bus_reset(struct Scsi_Host * shost,int channel)23861da177e4SLinus Torvalds void scsi_report_bus_reset(struct Scsi_Host *shost, int channel)
23871da177e4SLinus Torvalds {
23881da177e4SLinus Torvalds 	struct scsi_device *sdev;
23891da177e4SLinus Torvalds 
23901da177e4SLinus Torvalds 	__shost_for_each_device(sdev, shost) {
239130bd7df8SMike Christie 		if (channel == sdev_channel(sdev))
239230bd7df8SMike Christie 			__scsi_report_device_reset(sdev, NULL);
23931da177e4SLinus Torvalds 	}
23941da177e4SLinus Torvalds }
23951da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_report_bus_reset);
23961da177e4SLinus Torvalds 
23971da177e4SLinus Torvalds /*
23981da177e4SLinus Torvalds  * Function:    scsi_report_device_reset()
23991da177e4SLinus Torvalds  *
24001da177e4SLinus Torvalds  * Purpose:     Utility function used by low-level drivers to report that
24011da177e4SLinus Torvalds  *		they have observed a device reset on the device being handled.
24021da177e4SLinus Torvalds  *
24031da177e4SLinus Torvalds  * Arguments:   shost       - Host in question
24041da177e4SLinus Torvalds  *		channel     - channel on which reset was observed
24051da177e4SLinus Torvalds  *		target	    - target on which reset was observed
24061da177e4SLinus Torvalds  *
24071da177e4SLinus Torvalds  * Returns:     Nothing
24081da177e4SLinus Torvalds  *
24091da177e4SLinus Torvalds  * Lock status: Host lock must be held
24101da177e4SLinus Torvalds  *
24111da177e4SLinus Torvalds  * Notes:       This only needs to be called if the reset is one which
24121da177e4SLinus Torvalds  *		originates from an unknown location.  Resets originated
24131da177e4SLinus Torvalds  *		by the mid-level itself don't need to call this, but there
24141da177e4SLinus Torvalds  *		should be no harm.
24151da177e4SLinus Torvalds  *
24161da177e4SLinus Torvalds  *		The main purpose of this is to make sure that a CHECK_CONDITION
24171da177e4SLinus Torvalds  *		is properly treated.
24181da177e4SLinus Torvalds  */
scsi_report_device_reset(struct Scsi_Host * shost,int channel,int target)24191da177e4SLinus Torvalds void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target)
24201da177e4SLinus Torvalds {
24211da177e4SLinus Torvalds 	struct scsi_device *sdev;
24221da177e4SLinus Torvalds 
24231da177e4SLinus Torvalds 	__shost_for_each_device(sdev, shost) {
2424422c0d61SJeff Garzik 		if (channel == sdev_channel(sdev) &&
242530bd7df8SMike Christie 		    target == sdev_id(sdev))
242630bd7df8SMike Christie 			__scsi_report_device_reset(sdev, NULL);
24271da177e4SLinus Torvalds 	}
24281da177e4SLinus Torvalds }
24291da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_report_device_reset);
24301da177e4SLinus Torvalds 
2431176aa9d6SChristoph Hellwig /**
2432176aa9d6SChristoph Hellwig  * scsi_ioctl_reset: explicitly reset a host/bus/target/device
2433176aa9d6SChristoph Hellwig  * @dev:	scsi_device to operate on
2434176aa9d6SChristoph Hellwig  * @arg:	reset type (see sg.h)
24351da177e4SLinus Torvalds  */
24361da177e4SLinus Torvalds int
scsi_ioctl_reset(struct scsi_device * dev,int __user * arg)2437176aa9d6SChristoph Hellwig scsi_ioctl_reset(struct scsi_device *dev, int __user *arg)
24381da177e4SLinus Torvalds {
2439bc4f2401SAlan Stern 	struct scsi_cmnd *scmd;
2440d7a1bb0aSJames Smart 	struct Scsi_Host *shost = dev->host;
2441e9c787e6SChristoph Hellwig 	struct request *rq;
2442d7a1bb0aSJames Smart 	unsigned long flags;
2443b8e162f9SBart Van Assche 	int error = 0, val;
2444b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
2445176aa9d6SChristoph Hellwig 
2446176aa9d6SChristoph Hellwig 	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
2447176aa9d6SChristoph Hellwig 		return -EACCES;
2448176aa9d6SChristoph Hellwig 
2449176aa9d6SChristoph Hellwig 	error = get_user(val, arg);
2450176aa9d6SChristoph Hellwig 	if (error)
2451176aa9d6SChristoph Hellwig 		return error;
24521da177e4SLinus Torvalds 
2453bc4f2401SAlan Stern 	if (scsi_autopm_get_host(shost) < 0)
2454176aa9d6SChristoph Hellwig 		return -EIO;
2455bc4f2401SAlan Stern 
2456176aa9d6SChristoph Hellwig 	error = -EIO;
2457e9c787e6SChristoph Hellwig 	rq = kzalloc(sizeof(struct request) + sizeof(struct scsi_cmnd) +
2458e9c787e6SChristoph Hellwig 			shost->hostt->cmd_size, GFP_KERNEL);
2459e9c787e6SChristoph Hellwig 	if (!rq)
246095eeb5f5SChristoph Hellwig 		goto out_put_autopm_host;
2461e9c787e6SChristoph Hellwig 	blk_rq_init(NULL, rq);
246295eeb5f5SChristoph Hellwig 
2463e9c787e6SChristoph Hellwig 	scmd = (struct scsi_cmnd *)(rq + 1);
2464e9c787e6SChristoph Hellwig 	scsi_init_command(dev, scmd);
24651da177e4SLinus Torvalds 
2466bf23e619SBart Van Assche 	scmd->submitter = SUBMITTED_BY_SCSI_RESET_IOCTL;
2467d7ef2eeeSAlexander Atanasov 	scmd->flags |= SCMD_LAST;
246830b0c37bSBoaz Harrosh 	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
24691da177e4SLinus Torvalds 
24701da177e4SLinus Torvalds 	scmd->cmd_len			= 0;
24711da177e4SLinus Torvalds 
24721da177e4SLinus Torvalds 	scmd->sc_data_direction		= DMA_BIDIRECTIONAL;
24731da177e4SLinus Torvalds 
2474d7a1bb0aSJames Smart 	spin_lock_irqsave(shost->host_lock, flags);
2475d7a1bb0aSJames Smart 	shost->tmf_in_progress = 1;
2476d7a1bb0aSJames Smart 	spin_unlock_irqrestore(shost->host_lock, flags);
2477d7a1bb0aSJames Smart 
2478176aa9d6SChristoph Hellwig 	switch (val & ~SG_SCSI_RESET_NO_ESCALATE) {
2479176aa9d6SChristoph Hellwig 	case SG_SCSI_RESET_NOTHING:
2480176aa9d6SChristoph Hellwig 		rtn = SUCCESS;
2481176aa9d6SChristoph Hellwig 		break;
2482176aa9d6SChristoph Hellwig 	case SG_SCSI_RESET_DEVICE:
24831da177e4SLinus Torvalds 		rtn = scsi_try_bus_device_reset(scmd);
2484176aa9d6SChristoph Hellwig 		if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE))
24851da177e4SLinus Torvalds 			break;
2486df561f66SGustavo A. R. Silva 		fallthrough;
2487176aa9d6SChristoph Hellwig 	case SG_SCSI_RESET_TARGET:
248830bd7df8SMike Christie 		rtn = scsi_try_target_reset(scmd);
2489176aa9d6SChristoph Hellwig 		if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE))
249030bd7df8SMike Christie 			break;
2491df561f66SGustavo A. R. Silva 		fallthrough;
2492176aa9d6SChristoph Hellwig 	case SG_SCSI_RESET_BUS:
24931da177e4SLinus Torvalds 		rtn = scsi_try_bus_reset(scmd);
2494176aa9d6SChristoph Hellwig 		if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE))
24951da177e4SLinus Torvalds 			break;
2496df561f66SGustavo A. R. Silva 		fallthrough;
2497176aa9d6SChristoph Hellwig 	case SG_SCSI_RESET_HOST:
24981da177e4SLinus Torvalds 		rtn = scsi_try_host_reset(scmd);
2499176aa9d6SChristoph Hellwig 		if (rtn == SUCCESS)
250026cf591eSDouglas Gilbert 			break;
2501df561f66SGustavo A. R. Silva 		fallthrough;
25023bf2ff67SBart Van Assche 	default:
25031da177e4SLinus Torvalds 		rtn = FAILED;
2504176aa9d6SChristoph Hellwig 		break;
25051da177e4SLinus Torvalds 	}
25061da177e4SLinus Torvalds 
2507176aa9d6SChristoph Hellwig 	error = (rtn == SUCCESS) ? 0 : -EIO;
2508176aa9d6SChristoph Hellwig 
2509d7a1bb0aSJames Smart 	spin_lock_irqsave(shost->host_lock, flags);
2510d7a1bb0aSJames Smart 	shost->tmf_in_progress = 0;
2511d7a1bb0aSJames Smart 	spin_unlock_irqrestore(shost->host_lock, flags);
2512d7a1bb0aSJames Smart 
2513d7a1bb0aSJames Smart 	/*
2514d7a1bb0aSJames Smart 	 * be sure to wake up anyone who was sleeping or had their queue
2515d7a1bb0aSJames Smart 	 * suspended while we performed the TMF.
2516d7a1bb0aSJames Smart 	 */
2517d7a1bb0aSJames Smart 	SCSI_LOG_ERROR_RECOVERY(3,
251891921e01SHannes Reinecke 		shost_printk(KERN_INFO, shost,
251991921e01SHannes Reinecke 			     "waking up host to restart after TMF\n"));
2520d7a1bb0aSJames Smart 
2521d7a1bb0aSJames Smart 	wake_up(&shost->host_wait);
2522d7a1bb0aSJames Smart 	scsi_run_host_queues(shost);
2523d7a1bb0aSJames Smart 
2524e9c787e6SChristoph Hellwig 	kfree(rq);
25250f121dd8SChristoph Hellwig 
252604796336SChristoph Hellwig out_put_autopm_host:
2527bc4f2401SAlan Stern 	scsi_autopm_put_host(shost);
2528176aa9d6SChristoph Hellwig 	return error;
25291da177e4SLinus Torvalds }
25301da177e4SLinus Torvalds 
scsi_command_normalize_sense(const struct scsi_cmnd * cmd,struct scsi_sense_hdr * sshdr)25314753cbc0SHannes Reinecke bool scsi_command_normalize_sense(const struct scsi_cmnd *cmd,
25321da177e4SLinus Torvalds 				  struct scsi_sense_hdr *sshdr)
25331da177e4SLinus Torvalds {
25341da177e4SLinus Torvalds 	return scsi_normalize_sense(cmd->sense_buffer,
2535b80ca4f7SFUJITA Tomonori 			SCSI_SENSE_BUFFERSIZE, sshdr);
25361da177e4SLinus Torvalds }
25371da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_command_normalize_sense);
25381da177e4SLinus Torvalds 
25391da177e4SLinus Torvalds /**
2540eb44820cSRob Landley  * scsi_get_sense_info_fld - get information field from sense data (either fixed or descriptor format)
25411da177e4SLinus Torvalds  * @sense_buffer:	byte array of sense data
25421da177e4SLinus Torvalds  * @sb_len:		number of valid bytes in sense_buffer
25431da177e4SLinus Torvalds  * @info_out:		pointer to 64 integer where 8 or 4 byte information
25441da177e4SLinus Torvalds  *			field will be placed if found.
25451da177e4SLinus Torvalds  *
25461da177e4SLinus Torvalds  * Return value:
25472908769cSDamien Le Moal  *	true if information field found, false if not found.
2548dc8875e1SRandy Dunlap  */
scsi_get_sense_info_fld(const u8 * sense_buffer,int sb_len,u64 * info_out)25492908769cSDamien Le Moal bool scsi_get_sense_info_fld(const u8 *sense_buffer, int sb_len,
25501da177e4SLinus Torvalds 			     u64 *info_out)
25511da177e4SLinus Torvalds {
25521da177e4SLinus Torvalds 	const u8 * ucp;
25531da177e4SLinus Torvalds 
25541da177e4SLinus Torvalds 	if (sb_len < 7)
25552908769cSDamien Le Moal 		return false;
25561da177e4SLinus Torvalds 	switch (sense_buffer[0] & 0x7f) {
25571da177e4SLinus Torvalds 	case 0x70:
25581da177e4SLinus Torvalds 	case 0x71:
25591da177e4SLinus Torvalds 		if (sense_buffer[0] & 0x80) {
25602908769cSDamien Le Moal 			*info_out = get_unaligned_be32(&sense_buffer[3]);
25612908769cSDamien Le Moal 			return true;
25622908769cSDamien Le Moal 		}
25632908769cSDamien Le Moal 		return false;
25641da177e4SLinus Torvalds 	case 0x72:
25651da177e4SLinus Torvalds 	case 0x73:
25661da177e4SLinus Torvalds 		ucp = scsi_sense_desc_find(sense_buffer, sb_len,
25671da177e4SLinus Torvalds 					   0 /* info desc */);
25681da177e4SLinus Torvalds 		if (ucp && (0xa == ucp[1])) {
25692908769cSDamien Le Moal 			*info_out = get_unaligned_be64(&ucp[4]);
25702908769cSDamien Le Moal 			return true;
25711da177e4SLinus Torvalds 		}
25722908769cSDamien Le Moal 		return false;
25731da177e4SLinus Torvalds 	default:
25742908769cSDamien Le Moal 		return false;
25751da177e4SLinus Torvalds 	}
25761da177e4SLinus Torvalds }
25771da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_get_sense_info_fld);
2578