xref: /openbmc/linux/drivers/scsi/scsi_error.c (revision 31435de9746670d884f84a3c094a401aa27747aa)
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);
61*31435de9SBart Van Assche static enum scsi_disposition scsi_try_to_abort_cmd(const struct scsi_host_template *,
62e494f6a7SHannes Reinecke 						   struct scsi_cmnd *);
633eef6257SDavid Jeffery 
641da177e4SLinus Torvalds void scsi_eh_wakeup(struct Scsi_Host *shost)
651da177e4SLinus Torvalds {
66f0317e88SBart Van Assche 	lockdep_assert_held(shost->host_lock);
67f0317e88SBart Van Assche 
68c84b023aSMing Lei 	if (scsi_host_busy(shost) == 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  */
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++;
91f8bbfc24STejun Heo 		scsi_eh_wakeup(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 
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 
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 
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
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
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  */
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 
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;
2853bd6f43fSBart Van Assche 	unsigned long flags;
2863bd6f43fSBart Van Assche 
2873bd6f43fSBart Van Assche 	spin_lock_irqsave(shost->host_lock, flags);
2883bd6f43fSBart Van Assche 	shost->host_failed++;
2893bd6f43fSBart Van Assche 	scsi_eh_wakeup(shost);
2903bd6f43fSBart Van Assche 	spin_unlock_irqrestore(shost->host_lock, flags);
2913bd6f43fSBart Van Assche }
2923bd6f43fSBart Van Assche 
2937a38dc0bSHannes Reinecke /**
2941da177e4SLinus Torvalds  * scsi_eh_scmd_add - add scsi cmd to error handling.
2951da177e4SLinus Torvalds  * @scmd:	scmd to run eh on.
296dc8875e1SRandy Dunlap  */
297a0658632SHannes Reinecke void scsi_eh_scmd_add(struct scsi_cmnd *scmd)
2981da177e4SLinus Torvalds {
2991da177e4SLinus Torvalds 	struct Scsi_Host *shost = scmd->device->host;
3001da177e4SLinus Torvalds 	unsigned long flags;
3012171b6d0SHannes Reinecke 	int ret;
3021da177e4SLinus Torvalds 
3032171b6d0SHannes Reinecke 	WARN_ON_ONCE(!shost->ehandler);
3041da177e4SLinus Torvalds 
3051da177e4SLinus Torvalds 	spin_lock_irqsave(shost->host_lock, flags);
3062171b6d0SHannes Reinecke 	if (scsi_host_set_state(shost, SHOST_RECOVERY)) {
3072171b6d0SHannes Reinecke 		ret = scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY);
3082171b6d0SHannes Reinecke 		WARN_ON_ONCE(ret);
3092171b6d0SHannes Reinecke 	}
310bb3b621aSRen Mingxin 	if (shost->eh_deadline != -1 && !shost->last_reset)
311b4562022SHannes Reinecke 		shost->last_reset = jiffies;
312b4562022SHannes Reinecke 
3137a38dc0bSHannes Reinecke 	scsi_eh_reset(scmd);
3141da177e4SLinus Torvalds 	list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
3151da177e4SLinus Torvalds 	spin_unlock_irqrestore(shost->host_lock, flags);
3163bd6f43fSBart Van Assche 	/*
3173bd6f43fSBart Van Assche 	 * Ensure that all tasks observe the host state change before the
3183bd6f43fSBart Van Assche 	 * host_failed change.
3193bd6f43fSBart Van Assche 	 */
32054d87b0aSUladzislau Rezki 	call_rcu_hurry(&scmd->rcu, scsi_eh_inc_host_failed);
3211da177e4SLinus Torvalds }
3221da177e4SLinus Torvalds 
3231da177e4SLinus Torvalds /**
324deef1be1SJohn Garry  * scsi_timeout - Timeout function for normal scsi commands.
325242f9dcbSJens Axboe  * @req:	request that is timing out.
3261da177e4SLinus Torvalds  *
3271da177e4SLinus Torvalds  * Notes:
3281da177e4SLinus Torvalds  *     We do not need to lock this.  There is the potential for a race
3291da177e4SLinus Torvalds  *     only in that the normal completion handling might run, but if the
3301da177e4SLinus Torvalds  *     normal completion function determines that the timer has already
3311da177e4SLinus Torvalds  *     fired, then it mustn't do anything.
332dc8875e1SRandy Dunlap  */
3339bdb4833SJohn Garry enum blk_eh_timer_return scsi_timeout(struct request *req)
3341da177e4SLinus Torvalds {
335bed2213dSBart Van Assche 	struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(req);
3360bf8c869SJesper Juhl 	struct Scsi_Host *host = scmd->device->host;
3376c5f8ce1SJames Bottomley 
338bf816235SKei Tokunaga 	trace_scsi_dispatch_cmd_timeout(scmd);
3391da177e4SLinus Torvalds 	scsi_log_completion(scmd, TIMEOUT_ERROR);
3401da177e4SLinus Torvalds 
34148517eefSWu Bo 	atomic_inc(&scmd->device->iotmo_cnt);
342bb3b621aSRen Mingxin 	if (host->eh_deadline != -1 && !host->last_reset)
343b4562022SHannes Reinecke 		host->last_reset = jiffies;
344b4562022SHannes Reinecke 
345dee7121eSBart Van Assche 	if (host->hostt->eh_timed_out) {
346dee7121eSBart Van Assche 		switch (host->hostt->eh_timed_out(scmd)) {
347dee7121eSBart Van Assche 		case SCSI_EH_DONE:
348dee7121eSBart Van Assche 			return BLK_EH_DONE;
349dee7121eSBart Van Assche 		case SCSI_EH_RESET_TIMER:
350dee7121eSBart Van Assche 			return BLK_EH_RESET_TIMER;
351dee7121eSBart Van Assche 		case SCSI_EH_NOT_HANDLED:
352dee7121eSBart Van Assche 			break;
353dee7121eSBart Van Assche 		}
354dee7121eSBart Van Assche 	}
3556c5f8ce1SJames Bottomley 
356065990bdSKeith Busch 	/*
357dee7121eSBart Van Assche 	 * If scsi_done() has already set SCMD_STATE_COMPLETE, do not modify
358dee7121eSBart Van Assche 	 * *scmd.
359065990bdSKeith Busch 	 */
360f1342709SKeith Busch 	if (test_and_set_bit(SCMD_STATE_COMPLETE, &scmd->state))
361978b7922SBart Van Assche 		return BLK_EH_DONE;
362ec9780e4SWenchao Hao 	atomic_inc(&scmd->device->iodone_cnt);
363a0658632SHannes Reinecke 	if (scsi_abort_command(scmd) != SUCCESS) {
3648922a908SUlrich Obergfell 		set_host_byte(scmd, DID_TIME_OUT);
365a0658632SHannes Reinecke 		scsi_eh_scmd_add(scmd);
3662171b6d0SHannes Reinecke 	}
367242f9dcbSJens Axboe 
368dee7121eSBart Van Assche 	return BLK_EH_DONE;
3691da177e4SLinus Torvalds }
3701da177e4SLinus Torvalds 
3711da177e4SLinus Torvalds /**
3721da177e4SLinus Torvalds  * scsi_block_when_processing_errors - Prevent cmds from being queued.
3731da177e4SLinus Torvalds  * @sdev:	Device on which we are performing recovery.
3741da177e4SLinus Torvalds  *
3751da177e4SLinus Torvalds  * Description:
3761da177e4SLinus Torvalds  *     We block until the host is out of error recovery, and then check to
3771da177e4SLinus Torvalds  *     see whether the host or the device is offline.
3781da177e4SLinus Torvalds  *
3791da177e4SLinus Torvalds  * Return value:
3801da177e4SLinus Torvalds  *     0 when dev was taken offline by error recovery. 1 OK to proceed.
381dc8875e1SRandy Dunlap  */
3821da177e4SLinus Torvalds int scsi_block_when_processing_errors(struct scsi_device *sdev)
3831da177e4SLinus Torvalds {
3841da177e4SLinus Torvalds 	int online;
3851da177e4SLinus Torvalds 
386939647eeSJames Bottomley 	wait_event(sdev->host->host_wait, !scsi_host_in_recovery(sdev->host));
3871da177e4SLinus Torvalds 
3881da177e4SLinus Torvalds 	online = scsi_device_online(sdev);
3891da177e4SLinus Torvalds 
3901da177e4SLinus Torvalds 	return online;
3911da177e4SLinus Torvalds }
3921da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_block_when_processing_errors);
3931da177e4SLinus Torvalds 
3941da177e4SLinus Torvalds #ifdef CONFIG_SCSI_LOGGING
3951da177e4SLinus Torvalds /**
3961da177e4SLinus Torvalds  * scsi_eh_prt_fail_stats - Log info on failures.
3971da177e4SLinus Torvalds  * @shost:	scsi host being recovered.
3981da177e4SLinus Torvalds  * @work_q:	Queue of scsi cmds to process.
399dc8875e1SRandy Dunlap  */
4001da177e4SLinus Torvalds static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
4011da177e4SLinus Torvalds 					  struct list_head *work_q)
4021da177e4SLinus Torvalds {
4031da177e4SLinus Torvalds 	struct scsi_cmnd *scmd;
4041da177e4SLinus Torvalds 	struct scsi_device *sdev;
4051da177e4SLinus Torvalds 	int total_failures = 0;
4061da177e4SLinus Torvalds 	int cmd_failed = 0;
4071da177e4SLinus Torvalds 	int cmd_cancel = 0;
4081da177e4SLinus Torvalds 	int devices_failed = 0;
4091da177e4SLinus Torvalds 
4101da177e4SLinus Torvalds 	shost_for_each_device(sdev, shost) {
4111da177e4SLinus Torvalds 		list_for_each_entry(scmd, work_q, eh_entry) {
4121da177e4SLinus Torvalds 			if (scmd->device == sdev) {
4131da177e4SLinus Torvalds 				++total_failures;
414a0658632SHannes Reinecke 				if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED)
4151da177e4SLinus Torvalds 					++cmd_cancel;
4161da177e4SLinus Torvalds 				else
4171da177e4SLinus Torvalds 					++cmd_failed;
4181da177e4SLinus Torvalds 			}
4191da177e4SLinus Torvalds 		}
4201da177e4SLinus Torvalds 
4211da177e4SLinus Torvalds 		if (cmd_cancel || cmd_failed) {
4221da177e4SLinus Torvalds 			SCSI_LOG_ERROR_RECOVERY(3,
423a3a790dcSHannes Reinecke 				shost_printk(KERN_INFO, shost,
4249ccfc756SJames Bottomley 					    "%s: cmds failed: %d, cancel: %d\n",
425cadbd4a5SHarvey Harrison 					    __func__, cmd_failed,
4269ccfc756SJames Bottomley 					    cmd_cancel));
4271da177e4SLinus Torvalds 			cmd_cancel = 0;
4281da177e4SLinus Torvalds 			cmd_failed = 0;
4291da177e4SLinus Torvalds 			++devices_failed;
4301da177e4SLinus Torvalds 		}
4311da177e4SLinus Torvalds 	}
4321da177e4SLinus Torvalds 
43391921e01SHannes Reinecke 	SCSI_LOG_ERROR_RECOVERY(2, shost_printk(KERN_INFO, shost,
43491921e01SHannes Reinecke 				   "Total of %d commands on %d"
4351da177e4SLinus Torvalds 				   " devices require eh work\n",
4361da177e4SLinus Torvalds 				   total_failures, devices_failed));
4371da177e4SLinus Torvalds }
4381da177e4SLinus Torvalds #endif
4391da177e4SLinus Torvalds 
4401da177e4SLinus Torvalds  /**
441279afdfeSEwan D. Milne  * scsi_report_lun_change - Set flag on all *other* devices on the same target
442279afdfeSEwan D. Milne  *                          to indicate that a UNIT ATTENTION is expected.
443279afdfeSEwan D. Milne  * @sdev:	Device reporting the UNIT ATTENTION
444279afdfeSEwan D. Milne  */
445279afdfeSEwan D. Milne static void scsi_report_lun_change(struct scsi_device *sdev)
446279afdfeSEwan D. Milne {
447279afdfeSEwan D. Milne 	sdev->sdev_target->expecting_lun_change = 1;
448279afdfeSEwan D. Milne }
449279afdfeSEwan D. Milne 
450279afdfeSEwan D. Milne /**
451279afdfeSEwan D. Milne  * scsi_report_sense - Examine scsi sense information and log messages for
452279afdfeSEwan D. Milne  *		       certain conditions, also issue uevents for some of them.
453279afdfeSEwan D. Milne  * @sdev:	Device reporting the sense code
454279afdfeSEwan D. Milne  * @sshdr:	sshdr to be examined
455279afdfeSEwan D. Milne  */
456279afdfeSEwan D. Milne static void scsi_report_sense(struct scsi_device *sdev,
457279afdfeSEwan D. Milne 			      struct scsi_sense_hdr *sshdr)
458279afdfeSEwan D. Milne {
459279afdfeSEwan D. Milne 	enum scsi_device_event evt_type = SDEV_EVT_MAXBITS;	/* i.e. none */
460279afdfeSEwan D. Milne 
461279afdfeSEwan D. Milne 	if (sshdr->sense_key == UNIT_ATTENTION) {
462279afdfeSEwan D. Milne 		if (sshdr->asc == 0x3f && sshdr->ascq == 0x03) {
463279afdfeSEwan D. Milne 			evt_type = SDEV_EVT_INQUIRY_CHANGE_REPORTED;
464279afdfeSEwan D. Milne 			sdev_printk(KERN_WARNING, sdev,
465279afdfeSEwan D. Milne 				    "Inquiry data has changed");
466279afdfeSEwan D. Milne 		} else if (sshdr->asc == 0x3f && sshdr->ascq == 0x0e) {
467279afdfeSEwan D. Milne 			evt_type = SDEV_EVT_LUN_CHANGE_REPORTED;
468279afdfeSEwan D. Milne 			scsi_report_lun_change(sdev);
469279afdfeSEwan D. Milne 			sdev_printk(KERN_WARNING, sdev,
470279afdfeSEwan D. Milne 				    "LUN assignments on this target have "
471279afdfeSEwan D. Milne 				    "changed. The Linux SCSI layer does not "
472279afdfeSEwan D. Milne 				    "automatically remap LUN assignments.\n");
473279afdfeSEwan D. Milne 		} else if (sshdr->asc == 0x3f)
474279afdfeSEwan D. Milne 			sdev_printk(KERN_WARNING, sdev,
475a2417db3SLi Zhijian 				    "Operating parameters on this target have "
476279afdfeSEwan D. Milne 				    "changed. The Linux SCSI layer does not "
477279afdfeSEwan D. Milne 				    "automatically adjust these parameters.\n");
478279afdfeSEwan D. Milne 
479279afdfeSEwan D. Milne 		if (sshdr->asc == 0x38 && sshdr->ascq == 0x07) {
480279afdfeSEwan D. Milne 			evt_type = SDEV_EVT_SOFT_THRESHOLD_REACHED_REPORTED;
481279afdfeSEwan D. Milne 			sdev_printk(KERN_WARNING, sdev,
482279afdfeSEwan D. Milne 				    "Warning! Received an indication that the "
483279afdfeSEwan D. Milne 				    "LUN reached a thin provisioning soft "
484279afdfeSEwan D. Milne 				    "threshold.\n");
485279afdfeSEwan D. Milne 		}
486279afdfeSEwan D. Milne 
487cf3431bbSHannes Reinecke 		if (sshdr->asc == 0x29) {
488cf3431bbSHannes Reinecke 			evt_type = SDEV_EVT_POWER_ON_RESET_OCCURRED;
489af4edb1dSAdrian Hunter 			/*
490af4edb1dSAdrian Hunter 			 * Do not print message if it is an expected side-effect
491af4edb1dSAdrian Hunter 			 * of runtime PM.
492af4edb1dSAdrian Hunter 			 */
493af4edb1dSAdrian Hunter 			if (!sdev->silence_suspend)
494cf3431bbSHannes Reinecke 				sdev_printk(KERN_WARNING, sdev,
495cf3431bbSHannes Reinecke 					    "Power-on or device reset occurred\n");
496cf3431bbSHannes Reinecke 		}
497cf3431bbSHannes Reinecke 
498279afdfeSEwan D. Milne 		if (sshdr->asc == 0x2a && sshdr->ascq == 0x01) {
499279afdfeSEwan D. Milne 			evt_type = SDEV_EVT_MODE_PARAMETER_CHANGE_REPORTED;
500279afdfeSEwan D. Milne 			sdev_printk(KERN_WARNING, sdev,
501279afdfeSEwan D. Milne 				    "Mode parameters changed");
50214c3e677SHannes Reinecke 		} else if (sshdr->asc == 0x2a && sshdr->ascq == 0x06) {
50314c3e677SHannes Reinecke 			evt_type = SDEV_EVT_ALUA_STATE_CHANGE_REPORTED;
50414c3e677SHannes Reinecke 			sdev_printk(KERN_WARNING, sdev,
50514c3e677SHannes Reinecke 				    "Asymmetric access state changed");
506279afdfeSEwan D. Milne 		} else if (sshdr->asc == 0x2a && sshdr->ascq == 0x09) {
507279afdfeSEwan D. Milne 			evt_type = SDEV_EVT_CAPACITY_CHANGE_REPORTED;
508279afdfeSEwan D. Milne 			sdev_printk(KERN_WARNING, sdev,
509279afdfeSEwan D. Milne 				    "Capacity data has changed");
510279afdfeSEwan D. Milne 		} else if (sshdr->asc == 0x2a)
511279afdfeSEwan D. Milne 			sdev_printk(KERN_WARNING, sdev,
512279afdfeSEwan D. Milne 				    "Parameters changed");
513279afdfeSEwan D. Milne 	}
514279afdfeSEwan D. Milne 
515279afdfeSEwan D. Milne 	if (evt_type != SDEV_EVT_MAXBITS) {
516279afdfeSEwan D. Milne 		set_bit(evt_type, sdev->pending_events);
517279afdfeSEwan D. Milne 		schedule_work(&sdev->event_work);
518279afdfeSEwan D. Milne 	}
519279afdfeSEwan D. Milne }
520279afdfeSEwan D. Milne 
52136ebf1e2SMike Christie static inline void set_scsi_ml_byte(struct scsi_cmnd *cmd, u8 status)
52236ebf1e2SMike Christie {
52336ebf1e2SMike Christie 	cmd->result = (cmd->result & 0xffff00ff) | (status << 8);
52436ebf1e2SMike Christie }
52536ebf1e2SMike Christie 
526279afdfeSEwan D. Milne /**
5271da177e4SLinus Torvalds  * scsi_check_sense - Examine scsi cmd sense
5281da177e4SLinus Torvalds  * @scmd:	Cmd to have sense checked.
5291da177e4SLinus Torvalds  *
5301da177e4SLinus Torvalds  * Return value:
53187f14e65SHannes Reinecke  *	SUCCESS or FAILED or NEEDS_RETRY or ADD_TO_MLQUEUE
5321da177e4SLinus Torvalds  *
5331da177e4SLinus Torvalds  * Notes:
5341da177e4SLinus Torvalds  *	When a deferred error is detected the current command has
5351da177e4SLinus Torvalds  *	not been executed and needs retrying.
536dc8875e1SRandy Dunlap  */
537b8e162f9SBart Van Assche enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd)
5381da177e4SLinus Torvalds {
539a6a8d9f8SChandra Seetharaman 	struct scsi_device *sdev = scmd->device;
5401da177e4SLinus Torvalds 	struct scsi_sense_hdr sshdr;
5411da177e4SLinus Torvalds 
5421da177e4SLinus Torvalds 	if (! scsi_command_normalize_sense(scmd, &sshdr))
5431da177e4SLinus Torvalds 		return FAILED;	/* no valid sense data */
5441da177e4SLinus Torvalds 
545279afdfeSEwan D. Milne 	scsi_report_sense(sdev, &sshdr);
546279afdfeSEwan D. Milne 
5471da177e4SLinus Torvalds 	if (scsi_sense_is_deferred(&sshdr))
5481da177e4SLinus Torvalds 		return NEEDS_RETRY;
5491da177e4SLinus Torvalds 
550ee14c674SChristoph Hellwig 	if (sdev->handler && sdev->handler->check_sense) {
551b8e162f9SBart Van Assche 		enum scsi_disposition rc;
552a6a8d9f8SChandra Seetharaman 
553ee14c674SChristoph Hellwig 		rc = sdev->handler->check_sense(sdev, &sshdr);
554a6a8d9f8SChandra Seetharaman 		if (rc != SCSI_RETURN_NOT_HANDLED)
555a6a8d9f8SChandra Seetharaman 			return rc;
556a6a8d9f8SChandra Seetharaman 		/* handler does not care. Drop down to default handling */
557a6a8d9f8SChandra Seetharaman 	}
558a6a8d9f8SChandra Seetharaman 
559bf23e619SBart Van Assche 	if (scmd->cmnd[0] == TEST_UNIT_READY &&
560bf23e619SBart Van Assche 	    scmd->submitter != SUBMITTED_BY_SCSI_ERROR_HANDLER)
561e925cc43SChristoph Hellwig 		/*
562e925cc43SChristoph Hellwig 		 * nasty: for mid-layer issued TURs, we need to return the
563e925cc43SChristoph Hellwig 		 * actual sense data without any recovery attempt.  For eh
564e925cc43SChristoph Hellwig 		 * issued ones, we need to try to recover and interpret
565e925cc43SChristoph Hellwig 		 */
566e925cc43SChristoph Hellwig 		return SUCCESS;
567e925cc43SChristoph Hellwig 
5681da177e4SLinus Torvalds 	/*
5691da177e4SLinus Torvalds 	 * Previous logic looked for FILEMARK, EOM or ILI which are
5701da177e4SLinus Torvalds 	 * mainly associated with tapes and returned SUCCESS.
5711da177e4SLinus Torvalds 	 */
5721da177e4SLinus Torvalds 	if (sshdr.response_code == 0x70) {
5731da177e4SLinus Torvalds 		/* fixed format */
5741da177e4SLinus Torvalds 		if (scmd->sense_buffer[2] & 0xe0)
5751da177e4SLinus Torvalds 			return SUCCESS;
5761da177e4SLinus Torvalds 	} else {
5771da177e4SLinus Torvalds 		/*
5781da177e4SLinus Torvalds 		 * descriptor format: look for "stream commands sense data
5791da177e4SLinus Torvalds 		 * descriptor" (see SSC-3). Assume single sense data
5801da177e4SLinus Torvalds 		 * descriptor. Ignore ILI from SBC-2 READ LONG and WRITE LONG.
5811da177e4SLinus Torvalds 		 */
5821da177e4SLinus Torvalds 		if ((sshdr.additional_length > 3) &&
5831da177e4SLinus Torvalds 		    (scmd->sense_buffer[8] == 0x4) &&
5841da177e4SLinus Torvalds 		    (scmd->sense_buffer[11] & 0xe0))
5851da177e4SLinus Torvalds 			return SUCCESS;
5861da177e4SLinus Torvalds 	}
5871da177e4SLinus Torvalds 
5881da177e4SLinus Torvalds 	switch (sshdr.sense_key) {
5891da177e4SLinus Torvalds 	case NO_SENSE:
5901da177e4SLinus Torvalds 		return SUCCESS;
5911da177e4SLinus Torvalds 	case RECOVERED_ERROR:
5921da177e4SLinus Torvalds 		return /* soft_error */ SUCCESS;
5931da177e4SLinus Torvalds 
5941da177e4SLinus Torvalds 	case ABORTED_COMMAND:
595511e44f4SMartin K. Petersen 		if (sshdr.asc == 0x10) /* DIF */
596511e44f4SMartin K. Petersen 			return SUCCESS;
597511e44f4SMartin K. Petersen 
59829cfc2abSMartin Wilck 		if (sshdr.asc == 0x44 && sdev->sdev_bflags & BLIST_RETRY_ITF)
59929cfc2abSMartin Wilck 			return ADD_TO_MLQUEUE;
600c3606520SMartin Wilck 		if (sshdr.asc == 0xc1 && sshdr.ascq == 0x01 &&
601c3606520SMartin Wilck 		    sdev->sdev_bflags & BLIST_RETRY_ASC_C1)
602c3606520SMartin Wilck 			return ADD_TO_MLQUEUE;
60329cfc2abSMartin Wilck 
6041da177e4SLinus Torvalds 		return NEEDS_RETRY;
6051da177e4SLinus Torvalds 	case NOT_READY:
6061da177e4SLinus Torvalds 	case UNIT_ATTENTION:
6071da177e4SLinus Torvalds 		/*
6081da177e4SLinus Torvalds 		 * if we are expecting a cc/ua because of a bus reset that we
6091da177e4SLinus Torvalds 		 * performed, treat this just as a retry.  otherwise this is
6101da177e4SLinus Torvalds 		 * information that we should pass up to the upper-level driver
6111da177e4SLinus Torvalds 		 * so that we can deal with it there.
6121da177e4SLinus Torvalds 		 */
6131da177e4SLinus Torvalds 		if (scmd->device->expecting_cc_ua) {
614dfcf7775STARUISI Hiroaki 			/*
615dfcf7775STARUISI Hiroaki 			 * Because some device does not queue unit
616dfcf7775STARUISI Hiroaki 			 * attentions correctly, we carefully check
617dfcf7775STARUISI Hiroaki 			 * additional sense code and qualifier so as
618dfcf7775STARUISI Hiroaki 			 * not to squash media change unit attention.
619dfcf7775STARUISI Hiroaki 			 */
620dfcf7775STARUISI Hiroaki 			if (sshdr.asc != 0x28 || sshdr.ascq != 0x00) {
6211da177e4SLinus Torvalds 				scmd->device->expecting_cc_ua = 0;
6221da177e4SLinus Torvalds 				return NEEDS_RETRY;
6231da177e4SLinus Torvalds 			}
624dfcf7775STARUISI Hiroaki 		}
6251da177e4SLinus Torvalds 		/*
626279afdfeSEwan D. Milne 		 * we might also expect a cc/ua if another LUN on the target
627279afdfeSEwan D. Milne 		 * reported a UA with an ASC/ASCQ of 3F 0E -
628279afdfeSEwan D. Milne 		 * REPORTED LUNS DATA HAS CHANGED.
629279afdfeSEwan D. Milne 		 */
630279afdfeSEwan D. Milne 		if (scmd->device->sdev_target->expecting_lun_change &&
631279afdfeSEwan D. Milne 		    sshdr.asc == 0x3f && sshdr.ascq == 0x0e)
632279afdfeSEwan D. Milne 			return NEEDS_RETRY;
633279afdfeSEwan D. Milne 		/*
6341da177e4SLinus Torvalds 		 * if the device is in the process of becoming ready, we
6351da177e4SLinus Torvalds 		 * should retry.
6361da177e4SLinus Torvalds 		 */
6371da177e4SLinus Torvalds 		if ((sshdr.asc == 0x04) && (sshdr.ascq == 0x01))
6381da177e4SLinus Torvalds 			return NEEDS_RETRY;
6391da177e4SLinus Torvalds 		/*
6401da177e4SLinus Torvalds 		 * if the device is not started, we need to wake
6411da177e4SLinus Torvalds 		 * the error handler to start the motor
6421da177e4SLinus Torvalds 		 */
6431da177e4SLinus Torvalds 		if (scmd->device->allow_restart &&
6441da177e4SLinus Torvalds 		    (sshdr.asc == 0x04) && (sshdr.ascq == 0x02))
6451da177e4SLinus Torvalds 			return FAILED;
64677a42297SJames Bottomley 		/*
64702e031cbSChristoph Hellwig 		 * Pass the UA upwards for a determination in the completion
64802e031cbSChristoph Hellwig 		 * functions.
64977a42297SJames Bottomley 		 */
6501da177e4SLinus Torvalds 		return SUCCESS;
6511da177e4SLinus Torvalds 
65263583ccaSHannes Reinecke 		/* these are not supported */
653a9d6ceb8SHannes Reinecke 	case DATA_PROTECT:
654a9d6ceb8SHannes Reinecke 		if (sshdr.asc == 0x27 && sshdr.ascq == 0x07) {
655a9d6ceb8SHannes Reinecke 			/* Thin provisioning hard threshold reached */
6567dfaae6aSMike Christie 			set_scsi_ml_byte(scmd, SCSIML_STAT_NOSPC);
657a9d6ceb8SHannes Reinecke 			return SUCCESS;
658a9d6ceb8SHannes Reinecke 		}
659df561f66SGustavo A. R. Silva 		fallthrough;
6601da177e4SLinus Torvalds 	case COPY_ABORTED:
6611da177e4SLinus Torvalds 	case VOLUME_OVERFLOW:
6621da177e4SLinus Torvalds 	case MISCOMPARE:
66363583ccaSHannes Reinecke 	case BLANK_CHECK:
6647dfaae6aSMike Christie 		set_scsi_ml_byte(scmd, SCSIML_STAT_TGT_FAILURE);
66587f14e65SHannes Reinecke 		return SUCCESS;
6661da177e4SLinus Torvalds 
6671da177e4SLinus Torvalds 	case MEDIUM_ERROR:
668fd1b494dSLuben Tuikov 		if (sshdr.asc == 0x11 || /* UNRECOVERED READ ERR */
669fd1b494dSLuben Tuikov 		    sshdr.asc == 0x13 || /* AMNF DATA FIELD */
670fd1b494dSLuben Tuikov 		    sshdr.asc == 0x14) { /* RECORD NOT FOUND */
6717dfaae6aSMike Christie 			set_scsi_ml_byte(scmd, SCSIML_STAT_MED_ERROR);
67287f14e65SHannes Reinecke 			return SUCCESS;
673fd1b494dSLuben Tuikov 		}
6741da177e4SLinus Torvalds 		return NEEDS_RETRY;
6751da177e4SLinus Torvalds 
6761da177e4SLinus Torvalds 	case HARDWARE_ERROR:
6771da177e4SLinus Torvalds 		if (scmd->device->retry_hwerror)
678bb0003c1SMike Anderson 			return ADD_TO_MLQUEUE;
6791da177e4SLinus Torvalds 		else
6807dfaae6aSMike Christie 			set_scsi_ml_byte(scmd, SCSIML_STAT_TGT_FAILURE);
681df561f66SGustavo A. R. Silva 		fallthrough;
6821da177e4SLinus Torvalds 
6831da177e4SLinus Torvalds 	case ILLEGAL_REQUEST:
68447ac56dbSMike Snitzer 		if (sshdr.asc == 0x20 || /* Invalid command operation code */
68547ac56dbSMike Snitzer 		    sshdr.asc == 0x21 || /* Logical block address out of range */
686a8bbb2abSHannes Reinecke 		    sshdr.asc == 0x22 || /* Invalid function */
68747ac56dbSMike Snitzer 		    sshdr.asc == 0x24 || /* Invalid field in cdb */
688d0b7a909SMartin Wilck 		    sshdr.asc == 0x26 || /* Parameter value invalid */
689d0b7a909SMartin Wilck 		    sshdr.asc == 0x27) { /* Write protected */
6907dfaae6aSMike Christie 			set_scsi_ml_byte(scmd, SCSIML_STAT_TGT_FAILURE);
69147ac56dbSMike Snitzer 		}
69247ac56dbSMike Snitzer 		return SUCCESS;
69347ac56dbSMike Snitzer 
6941da177e4SLinus Torvalds 	default:
6951da177e4SLinus Torvalds 		return SUCCESS;
6961da177e4SLinus Torvalds 	}
6971da177e4SLinus Torvalds }
6983852e373SHannes Reinecke EXPORT_SYMBOL_GPL(scsi_check_sense);
6991da177e4SLinus Torvalds 
7004a84067dSVasu Dev static void scsi_handle_queue_ramp_up(struct scsi_device *sdev)
7014a84067dSVasu Dev {
702*31435de9SBart Van Assche 	const struct scsi_host_template *sht = sdev->host->hostt;
7034a84067dSVasu Dev 	struct scsi_device *tmp_sdev;
7044a84067dSVasu Dev 
705c40ecc12SChristoph Hellwig 	if (!sht->track_queue_depth ||
7064a84067dSVasu Dev 	    sdev->queue_depth >= sdev->max_queue_depth)
7074a84067dSVasu Dev 		return;
7084a84067dSVasu Dev 
7094a84067dSVasu Dev 	if (time_before(jiffies,
7104a84067dSVasu Dev 	    sdev->last_queue_ramp_up + sdev->queue_ramp_up_period))
7114a84067dSVasu Dev 		return;
7124a84067dSVasu Dev 
7134a84067dSVasu Dev 	if (time_before(jiffies,
7144a84067dSVasu Dev 	    sdev->last_queue_full_time + sdev->queue_ramp_up_period))
7154a84067dSVasu Dev 		return;
7164a84067dSVasu Dev 
7174a84067dSVasu Dev 	/*
7184a84067dSVasu Dev 	 * Walk all devices of a target and do
7194a84067dSVasu Dev 	 * ramp up on them.
7204a84067dSVasu Dev 	 */
7214a84067dSVasu Dev 	shost_for_each_device(tmp_sdev, sdev->host) {
7224a84067dSVasu Dev 		if (tmp_sdev->channel != sdev->channel ||
7234a84067dSVasu Dev 		    tmp_sdev->id != sdev->id ||
7244a84067dSVasu Dev 		    tmp_sdev->queue_depth == sdev->max_queue_depth)
7254a84067dSVasu Dev 			continue;
726c40ecc12SChristoph Hellwig 
727db5ed4dfSChristoph Hellwig 		scsi_change_queue_depth(tmp_sdev, tmp_sdev->queue_depth + 1);
7284a84067dSVasu Dev 		sdev->last_queue_ramp_up = jiffies;
7294a84067dSVasu Dev 	}
7304a84067dSVasu Dev }
7314a84067dSVasu Dev 
73242a6a918SMike Christie static void scsi_handle_queue_full(struct scsi_device *sdev)
73342a6a918SMike Christie {
734*31435de9SBart Van Assche 	const struct scsi_host_template *sht = sdev->host->hostt;
73542a6a918SMike Christie 	struct scsi_device *tmp_sdev;
73642a6a918SMike Christie 
737c40ecc12SChristoph Hellwig 	if (!sht->track_queue_depth)
73842a6a918SMike Christie 		return;
73942a6a918SMike Christie 
74042a6a918SMike Christie 	shost_for_each_device(tmp_sdev, sdev->host) {
74142a6a918SMike Christie 		if (tmp_sdev->channel != sdev->channel ||
74242a6a918SMike Christie 		    tmp_sdev->id != sdev->id)
74342a6a918SMike Christie 			continue;
74442a6a918SMike Christie 		/*
74542a6a918SMike Christie 		 * We do not know the number of commands that were at
74642a6a918SMike Christie 		 * the device when we got the queue full so we start
74742a6a918SMike Christie 		 * from the highest possible value and work our way down.
74842a6a918SMike Christie 		 */
749c40ecc12SChristoph Hellwig 		scsi_track_queue_full(tmp_sdev, tmp_sdev->queue_depth - 1);
75042a6a918SMike Christie 	}
75142a6a918SMike Christie }
75242a6a918SMike Christie 
7531da177e4SLinus Torvalds /**
7541da177e4SLinus Torvalds  * scsi_eh_completed_normally - Disposition a eh cmd on return from LLD.
7551da177e4SLinus Torvalds  * @scmd:	SCSI cmd to examine.
7561da177e4SLinus Torvalds  *
7571da177e4SLinus Torvalds  * Notes:
7581da177e4SLinus Torvalds  *    This is *only* called when we are examining the status of commands
7591da177e4SLinus Torvalds  *    queued during error recovery.  the main difference here is that we
7601da177e4SLinus Torvalds  *    don't allow for the possibility of retries here, and we are a lot
7611da177e4SLinus Torvalds  *    more restrictive about what we consider acceptable.
762dc8875e1SRandy Dunlap  */
763b8e162f9SBart Van Assche static enum scsi_disposition scsi_eh_completed_normally(struct scsi_cmnd *scmd)
7641da177e4SLinus Torvalds {
7651da177e4SLinus Torvalds 	/*
7661da177e4SLinus Torvalds 	 * first check the host byte, to see if there is anything in there
7671da177e4SLinus Torvalds 	 * that would indicate what we need to do.
7681da177e4SLinus Torvalds 	 */
7691da177e4SLinus Torvalds 	if (host_byte(scmd->result) == DID_RESET) {
7701da177e4SLinus Torvalds 		/*
7711da177e4SLinus Torvalds 		 * rats.  we are already in the error handler, so we now
7721da177e4SLinus Torvalds 		 * get to try and figure out what to do next.  if the sense
7731da177e4SLinus Torvalds 		 * is valid, we have a pretty good idea of what to do.
7741da177e4SLinus Torvalds 		 * if not, we mark it as FAILED.
7751da177e4SLinus Torvalds 		 */
7761da177e4SLinus Torvalds 		return scsi_check_sense(scmd);
7771da177e4SLinus Torvalds 	}
7781da177e4SLinus Torvalds 	if (host_byte(scmd->result) != DID_OK)
7791da177e4SLinus Torvalds 		return FAILED;
7801da177e4SLinus Torvalds 
7811da177e4SLinus Torvalds 	/*
7821da177e4SLinus Torvalds 	 * now, check the status byte to see if this indicates
7831da177e4SLinus Torvalds 	 * anything special.
7841da177e4SLinus Torvalds 	 */
7853d45cefcSHannes Reinecke 	switch (get_status_byte(scmd)) {
7863d45cefcSHannes Reinecke 	case SAM_STAT_GOOD:
7874a84067dSVasu Dev 		scsi_handle_queue_ramp_up(scmd->device);
788df561f66SGustavo A. R. Silva 		fallthrough;
7893d45cefcSHannes Reinecke 	case SAM_STAT_COMMAND_TERMINATED:
7901da177e4SLinus Torvalds 		return SUCCESS;
7913d45cefcSHannes Reinecke 	case SAM_STAT_CHECK_CONDITION:
7921da177e4SLinus Torvalds 		return scsi_check_sense(scmd);
7933d45cefcSHannes Reinecke 	case SAM_STAT_CONDITION_MET:
7943d45cefcSHannes Reinecke 	case SAM_STAT_INTERMEDIATE:
7953d45cefcSHannes Reinecke 	case SAM_STAT_INTERMEDIATE_CONDITION_MET:
7961da177e4SLinus Torvalds 		/*
7971da177e4SLinus Torvalds 		 * who knows?  FIXME(eric)
7981da177e4SLinus Torvalds 		 */
7991da177e4SLinus Torvalds 		return SUCCESS;
8003d45cefcSHannes Reinecke 	case SAM_STAT_RESERVATION_CONFLICT:
80167110dfdSJames Bottomley 		if (scmd->cmnd[0] == TEST_UNIT_READY)
80267110dfdSJames Bottomley 			/* it is a success, we probed the device and
80367110dfdSJames Bottomley 			 * found it */
8045f91bb05SMichael Reed 			return SUCCESS;
80567110dfdSJames Bottomley 		/* otherwise, we failed to send the command */
80667110dfdSJames Bottomley 		return FAILED;
8073d45cefcSHannes Reinecke 	case SAM_STAT_TASK_SET_FULL:
80842a6a918SMike Christie 		scsi_handle_queue_full(scmd->device);
809df561f66SGustavo A. R. Silva 		fallthrough;
8103d45cefcSHannes Reinecke 	case SAM_STAT_BUSY:
8113eb3a928SHannes Reinecke 		return NEEDS_RETRY;
8121da177e4SLinus Torvalds 	default:
8131da177e4SLinus Torvalds 		return FAILED;
8141da177e4SLinus Torvalds 	}
8151da177e4SLinus Torvalds 	return FAILED;
8161da177e4SLinus Torvalds }
8171da177e4SLinus Torvalds 
8181da177e4SLinus Torvalds /**
8191da177e4SLinus Torvalds  * scsi_eh_done - Completion function for error handling.
8201da177e4SLinus Torvalds  * @scmd:	Cmd that is done.
821dc8875e1SRandy Dunlap  */
822bf23e619SBart Van Assche void scsi_eh_done(struct scsi_cmnd *scmd)
8231da177e4SLinus Torvalds {
82485631672SMichael Reed 	struct completion *eh_action;
82585631672SMichael Reed 
82691921e01SHannes Reinecke 	SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
827470613b4SHannes Reinecke 			"%s result: %x\n", __func__, scmd->result));
82885631672SMichael Reed 
82985631672SMichael Reed 	eh_action = scmd->device->host->eh_action;
83085631672SMichael Reed 	if (eh_action)
83185631672SMichael Reed 		complete(eh_action);
8321da177e4SLinus Torvalds }
8331da177e4SLinus Torvalds 
8341da177e4SLinus Torvalds /**
835292148f8SBrian King  * scsi_try_host_reset - ask host adapter to reset itself
836c2b3ebd0SGeert Uytterhoeven  * @scmd:	SCSI cmd to send host reset.
837dc8875e1SRandy Dunlap  */
838b8e162f9SBart Van Assche static enum scsi_disposition scsi_try_host_reset(struct scsi_cmnd *scmd)
839292148f8SBrian King {
840292148f8SBrian King 	unsigned long flags;
841b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
8420bf8c869SJesper Juhl 	struct Scsi_Host *host = scmd->device->host;
843*31435de9SBart Van Assche 	const struct scsi_host_template *hostt = host->hostt;
844292148f8SBrian King 
84591921e01SHannes Reinecke 	SCSI_LOG_ERROR_RECOVERY(3,
84691921e01SHannes Reinecke 		shost_printk(KERN_INFO, host, "Snd Host RST\n"));
847292148f8SBrian King 
8480bf8c869SJesper Juhl 	if (!hostt->eh_host_reset_handler)
849292148f8SBrian King 		return FAILED;
850292148f8SBrian King 
8510bf8c869SJesper Juhl 	rtn = hostt->eh_host_reset_handler(scmd);
852292148f8SBrian King 
853292148f8SBrian King 	if (rtn == SUCCESS) {
8540bf8c869SJesper Juhl 		if (!hostt->skip_settle_delay)
855292148f8SBrian King 			ssleep(HOST_RESET_SETTLE_TIME);
8560bf8c869SJesper Juhl 		spin_lock_irqsave(host->host_lock, flags);
8570bf8c869SJesper Juhl 		scsi_report_bus_reset(host, scmd_channel(scmd));
8580bf8c869SJesper Juhl 		spin_unlock_irqrestore(host->host_lock, flags);
859292148f8SBrian King 	}
860292148f8SBrian King 
861292148f8SBrian King 	return rtn;
862292148f8SBrian King }
863292148f8SBrian King 
864292148f8SBrian King /**
865292148f8SBrian King  * scsi_try_bus_reset - ask host to perform a bus reset
866292148f8SBrian King  * @scmd:	SCSI cmd to send bus reset.
867dc8875e1SRandy Dunlap  */
868b8e162f9SBart Van Assche static enum scsi_disposition scsi_try_bus_reset(struct scsi_cmnd *scmd)
869292148f8SBrian King {
870292148f8SBrian King 	unsigned long flags;
871b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
8720bf8c869SJesper Juhl 	struct Scsi_Host *host = scmd->device->host;
873*31435de9SBart Van Assche 	const struct scsi_host_template *hostt = host->hostt;
874292148f8SBrian King 
87591921e01SHannes Reinecke 	SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
87691921e01SHannes Reinecke 		"%s: Snd Bus RST\n", __func__));
877292148f8SBrian King 
8780bf8c869SJesper Juhl 	if (!hostt->eh_bus_reset_handler)
879292148f8SBrian King 		return FAILED;
880292148f8SBrian King 
8810bf8c869SJesper Juhl 	rtn = hostt->eh_bus_reset_handler(scmd);
882292148f8SBrian King 
883292148f8SBrian King 	if (rtn == SUCCESS) {
8840bf8c869SJesper Juhl 		if (!hostt->skip_settle_delay)
885292148f8SBrian King 			ssleep(BUS_RESET_SETTLE_TIME);
8860bf8c869SJesper Juhl 		spin_lock_irqsave(host->host_lock, flags);
8870bf8c869SJesper Juhl 		scsi_report_bus_reset(host, scmd_channel(scmd));
8880bf8c869SJesper Juhl 		spin_unlock_irqrestore(host->host_lock, flags);
889292148f8SBrian King 	}
890292148f8SBrian King 
891292148f8SBrian King 	return rtn;
892292148f8SBrian King }
893292148f8SBrian King 
89430bd7df8SMike Christie static void __scsi_report_device_reset(struct scsi_device *sdev, void *data)
89530bd7df8SMike Christie {
89630bd7df8SMike Christie 	sdev->was_reset = 1;
89730bd7df8SMike Christie 	sdev->expecting_cc_ua = 1;
89830bd7df8SMike Christie }
89930bd7df8SMike Christie 
90030bd7df8SMike Christie /**
90130bd7df8SMike Christie  * scsi_try_target_reset - Ask host to perform a target reset
90230bd7df8SMike Christie  * @scmd:	SCSI cmd used to send a target reset
90330bd7df8SMike Christie  *
90430bd7df8SMike Christie  * Notes:
90530bd7df8SMike Christie  *    There is no timeout for this operation.  if this operation is
90630bd7df8SMike Christie  *    unreliable for a given host, then the host itself needs to put a
90730bd7df8SMike Christie  *    timer on it, and set the host back to a consistent state prior to
90830bd7df8SMike Christie  *    returning.
90930bd7df8SMike Christie  */
910b8e162f9SBart Van Assche static enum scsi_disposition scsi_try_target_reset(struct scsi_cmnd *scmd)
91130bd7df8SMike Christie {
91230bd7df8SMike Christie 	unsigned long flags;
913b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
9140bf8c869SJesper Juhl 	struct Scsi_Host *host = scmd->device->host;
915*31435de9SBart Van Assche 	const struct scsi_host_template *hostt = host->hostt;
91630bd7df8SMike Christie 
9170bf8c869SJesper Juhl 	if (!hostt->eh_target_reset_handler)
91830bd7df8SMike Christie 		return FAILED;
91930bd7df8SMike Christie 
9200bf8c869SJesper Juhl 	rtn = hostt->eh_target_reset_handler(scmd);
92130bd7df8SMike Christie 	if (rtn == SUCCESS) {
9220bf8c869SJesper Juhl 		spin_lock_irqsave(host->host_lock, flags);
92330bd7df8SMike Christie 		__starget_for_each_device(scsi_target(scmd->device), NULL,
92430bd7df8SMike Christie 					  __scsi_report_device_reset);
9250bf8c869SJesper Juhl 		spin_unlock_irqrestore(host->host_lock, flags);
92630bd7df8SMike Christie 	}
92730bd7df8SMike Christie 
92830bd7df8SMike Christie 	return rtn;
92930bd7df8SMike Christie }
93030bd7df8SMike Christie 
931292148f8SBrian King /**
932292148f8SBrian King  * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev
933292148f8SBrian King  * @scmd:	SCSI cmd used to send BDR
934292148f8SBrian King  *
935292148f8SBrian King  * Notes:
936292148f8SBrian King  *    There is no timeout for this operation.  if this operation is
937292148f8SBrian King  *    unreliable for a given host, then the host itself needs to put a
938292148f8SBrian King  *    timer on it, and set the host back to a consistent state prior to
939292148f8SBrian King  *    returning.
940dc8875e1SRandy Dunlap  */
941b8e162f9SBart Van Assche static enum scsi_disposition scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
942292148f8SBrian King {
943b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
944*31435de9SBart Van Assche 	const struct scsi_host_template *hostt = scmd->device->host->hostt;
945292148f8SBrian King 
9460bf8c869SJesper Juhl 	if (!hostt->eh_device_reset_handler)
947292148f8SBrian King 		return FAILED;
948292148f8SBrian King 
9490bf8c869SJesper Juhl 	rtn = hostt->eh_device_reset_handler(scmd);
95030bd7df8SMike Christie 	if (rtn == SUCCESS)
95130bd7df8SMike Christie 		__scsi_report_device_reset(scmd->device, NULL);
952292148f8SBrian King 	return rtn;
953292148f8SBrian King }
954292148f8SBrian King 
955883a030fSHannes Reinecke /**
956883a030fSHannes Reinecke  * scsi_try_to_abort_cmd - Ask host to abort a SCSI command
9576583f6fbSRandy Dunlap  * @hostt:	SCSI driver host template
958883a030fSHannes Reinecke  * @scmd:	SCSI cmd used to send a target reset
959883a030fSHannes Reinecke  *
960883a030fSHannes Reinecke  * Return value:
961883a030fSHannes Reinecke  *	SUCCESS, FAILED, or FAST_IO_FAIL
962883a030fSHannes Reinecke  *
963883a030fSHannes Reinecke  * Notes:
964883a030fSHannes Reinecke  *    SUCCESS does not necessarily indicate that the command
965883a030fSHannes Reinecke  *    has been aborted; it only indicates that the LLDDs
966883a030fSHannes Reinecke  *    has cleared all references to that command.
967883a030fSHannes Reinecke  *    LLDDs should return FAILED only if an abort was required
968883a030fSHannes Reinecke  *    but could not be executed. LLDDs should return FAST_IO_FAIL
969883a030fSHannes Reinecke  *    if the device is temporarily unavailable (eg due to a
970883a030fSHannes Reinecke  *    link down on FibreChannel)
971883a030fSHannes Reinecke  */
972b8e162f9SBart Van Assche static enum scsi_disposition
973*31435de9SBart Van Assche scsi_try_to_abort_cmd(const struct scsi_host_template *hostt, struct scsi_cmnd *scmd)
974292148f8SBrian King {
9750bf8c869SJesper Juhl 	if (!hostt->eh_abort_handler)
976292148f8SBrian King 		return FAILED;
977292148f8SBrian King 
9780bf8c869SJesper Juhl 	return hostt->eh_abort_handler(scmd);
979292148f8SBrian King }
980292148f8SBrian King 
981292148f8SBrian King static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
982292148f8SBrian King {
9830bf8c869SJesper Juhl 	if (scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd) != SUCCESS)
984292148f8SBrian King 		if (scsi_try_bus_device_reset(scmd) != SUCCESS)
98530bd7df8SMike Christie 			if (scsi_try_target_reset(scmd) != SUCCESS)
986292148f8SBrian King 				if (scsi_try_bus_reset(scmd) != SUCCESS)
987292148f8SBrian King 					scsi_try_host_reset(scmd);
988292148f8SBrian King }
989292148f8SBrian King 
990292148f8SBrian King /**
9913b729f76SSantosh Y  * scsi_eh_prep_cmnd  - Save a scsi command info as part of error recovery
9922dc611deSChristoph Hellwig  * @scmd:       SCSI command structure to hijack
993e1c23468SBoaz Harrosh  * @ses:        structure to save restore information
99455db6c1bSBoaz Harrosh  * @cmnd:       CDB to send. Can be NULL if no new cmnd is needed
995ce70fd9aSChristoph Hellwig  * @cmnd_size:  size in bytes of @cmnd (must be <= MAX_COMMAND_SIZE)
99655db6c1bSBoaz Harrosh  * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored)
9972dc611deSChristoph Hellwig  *
998e1c23468SBoaz Harrosh  * This function is used to save a scsi command information before re-execution
99955db6c1bSBoaz Harrosh  * as part of the error recovery process.  If @sense_bytes is 0 the command
100055db6c1bSBoaz Harrosh  * sent must be one that does not transfer any data.  If @sense_bytes != 0
100155db6c1bSBoaz Harrosh  * @cmnd is ignored and this functions sets up a REQUEST_SENSE command
100255db6c1bSBoaz Harrosh  * and cmnd buffers to read @sense_bytes into @scmd->sense_buffer.
1003dc8875e1SRandy Dunlap  */
1004e1c23468SBoaz Harrosh void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
1005e1c23468SBoaz Harrosh 			unsigned char *cmnd, int cmnd_size, unsigned sense_bytes)
10061da177e4SLinus Torvalds {
1007f59114b7S 	struct scsi_device *sdev = scmd->device;
10081da177e4SLinus Torvalds 
1009631c228cSChristoph Hellwig 	/*
1010631c228cSChristoph Hellwig 	 * We need saved copies of a number of fields - this is because
1011631c228cSChristoph Hellwig 	 * error handling may need to overwrite these with different values
1012631c228cSChristoph Hellwig 	 * to run different commands, and once error handling is complete,
1013631c228cSChristoph Hellwig 	 * we will need to restore these values prior to running the actual
1014631c228cSChristoph Hellwig 	 * command.
1015631c228cSChristoph Hellwig 	 */
1016e1c23468SBoaz Harrosh 	ses->cmd_len = scmd->cmd_len;
1017e1c23468SBoaz Harrosh 	ses->data_direction = scmd->sc_data_direction;
101830b0c37bSBoaz Harrosh 	ses->sdb = scmd->sdb;
1019e1c23468SBoaz Harrosh 	ses->result = scmd->result;
1020a9a4ea11SChristoph Hellwig 	ses->resid_len = scmd->resid_len;
102112265709SAlan Stern 	ses->underflow = scmd->underflow;
1022db007fc5SMartin K. Petersen 	ses->prot_op = scmd->prot_op;
10238e8c9d01SHannes Reinecke 	ses->eh_eflags = scmd->eh_eflags;
1024631c228cSChristoph Hellwig 
1025db007fc5SMartin K. Petersen 	scmd->prot_op = SCSI_PROT_NORMAL;
1026c69e6f81SJames Bottomley 	scmd->eh_eflags = 0;
1027ce70fd9aSChristoph Hellwig 	memcpy(ses->cmnd, scmd->cmnd, sizeof(ses->cmnd));
1028ce70fd9aSChristoph Hellwig 	memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
102930b0c37bSBoaz Harrosh 	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
1030644373a4SAlan Stern 	scmd->result = 0;
1031a9a4ea11SChristoph Hellwig 	scmd->resid_len = 0;
103230b0c37bSBoaz Harrosh 
103355db6c1bSBoaz Harrosh 	if (sense_bytes) {
103430b0c37bSBoaz Harrosh 		scmd->sdb.length = min_t(unsigned, SCSI_SENSE_BUFFERSIZE,
103530b0c37bSBoaz Harrosh 					 sense_bytes);
1036e1c23468SBoaz Harrosh 		sg_init_one(&ses->sense_sgl, scmd->sense_buffer,
103730b0c37bSBoaz Harrosh 			    scmd->sdb.length);
103830b0c37bSBoaz Harrosh 		scmd->sdb.table.sgl = &ses->sense_sgl;
103955db6c1bSBoaz Harrosh 		scmd->sc_data_direction = DMA_FROM_DEVICE;
10400c958eccSTony Battersby 		scmd->sdb.table.nents = scmd->sdb.table.orig_nents = 1;
104155db6c1bSBoaz Harrosh 		scmd->cmnd[0] = REQUEST_SENSE;
104230b0c37bSBoaz Harrosh 		scmd->cmnd[4] = scmd->sdb.length;
104355db6c1bSBoaz Harrosh 		scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
1044631c228cSChristoph Hellwig 	} else {
1045631c228cSChristoph Hellwig 		scmd->sc_data_direction = DMA_NONE;
104655db6c1bSBoaz Harrosh 		if (cmnd) {
1047ce70fd9aSChristoph Hellwig 			BUG_ON(cmnd_size > sizeof(scmd->cmnd));
104855db6c1bSBoaz Harrosh 			memcpy(scmd->cmnd, cmnd, cmnd_size);
104955db6c1bSBoaz Harrosh 			scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
105055db6c1bSBoaz Harrosh 		}
1051631c228cSChristoph Hellwig 	}
1052631c228cSChristoph Hellwig 
1053631c228cSChristoph Hellwig 	scmd->underflow = 0;
1054631c228cSChristoph Hellwig 
105555db6c1bSBoaz Harrosh 	if (sdev->scsi_level <= SCSI_2 && sdev->scsi_level != SCSI_UNKNOWN)
10561da177e4SLinus Torvalds 		scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) |
1057f59114b7S 			(sdev->lun << 5 & 0xe0);
10581da177e4SLinus Torvalds 
1059631c228cSChristoph Hellwig 	/*
1060631c228cSChristoph Hellwig 	 * Zero the sense buffer.  The scsi spec mandates that any
1061631c228cSChristoph Hellwig 	 * untransferred sense data should be interpreted as being zero.
1062631c228cSChristoph Hellwig 	 */
1063b80ca4f7SFUJITA Tomonori 	memset(scmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
1064e1c23468SBoaz Harrosh }
1065e1c23468SBoaz Harrosh EXPORT_SYMBOL(scsi_eh_prep_cmnd);
1066631c228cSChristoph Hellwig 
1067e1c23468SBoaz Harrosh /**
10683b729f76SSantosh Y  * scsi_eh_restore_cmnd  - Restore a scsi command info as part of error recovery
1069e1c23468SBoaz Harrosh  * @scmd:       SCSI command structure to restore
1070477e608cSBartlomiej Zolnierkiewicz  * @ses:        saved information from a coresponding call to scsi_eh_prep_cmnd
1071e1c23468SBoaz Harrosh  *
1072477e608cSBartlomiej Zolnierkiewicz  * Undo any damage done by above scsi_eh_prep_cmnd().
1073dc8875e1SRandy Dunlap  */
1074e1c23468SBoaz Harrosh void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
1075e1c23468SBoaz Harrosh {
1076e1c23468SBoaz Harrosh 	/*
1077e1c23468SBoaz Harrosh 	 * Restore original data
1078e1c23468SBoaz Harrosh 	 */
1079e1c23468SBoaz Harrosh 	scmd->cmd_len = ses->cmd_len;
1080ce70fd9aSChristoph Hellwig 	memcpy(scmd->cmnd, ses->cmnd, sizeof(ses->cmnd));
1081e1c23468SBoaz Harrosh 	scmd->sc_data_direction = ses->data_direction;
108230b0c37bSBoaz Harrosh 	scmd->sdb = ses->sdb;
1083e1c23468SBoaz Harrosh 	scmd->result = ses->result;
1084a9a4ea11SChristoph Hellwig 	scmd->resid_len = ses->resid_len;
108512265709SAlan Stern 	scmd->underflow = ses->underflow;
1086db007fc5SMartin K. Petersen 	scmd->prot_op = ses->prot_op;
10878e8c9d01SHannes Reinecke 	scmd->eh_eflags = ses->eh_eflags;
1088e1c23468SBoaz Harrosh }
1089e1c23468SBoaz Harrosh EXPORT_SYMBOL(scsi_eh_restore_cmnd);
1090e1c23468SBoaz Harrosh 
1091e1c23468SBoaz Harrosh /**
10923b729f76SSantosh Y  * scsi_send_eh_cmnd  - submit a scsi command as part of error recovery
1093e1c23468SBoaz Harrosh  * @scmd:       SCSI command structure to hijack
1094e1c23468SBoaz Harrosh  * @cmnd:       CDB to send
1095e1c23468SBoaz Harrosh  * @cmnd_size:  size in bytes of @cmnd
1096e1c23468SBoaz Harrosh  * @timeout:    timeout for this request
1097e1c23468SBoaz Harrosh  * @sense_bytes: size of sense data to copy or 0
1098e1c23468SBoaz Harrosh  *
1099e1c23468SBoaz Harrosh  * This function is used to send a scsi command down to a target device
1100e1c23468SBoaz Harrosh  * as part of the error recovery process. See also scsi_eh_prep_cmnd() above.
1101e1c23468SBoaz Harrosh  *
1102e1c23468SBoaz Harrosh  * Return value:
1103e1c23468SBoaz Harrosh  *    SUCCESS or FAILED or NEEDS_RETRY
1104dc8875e1SRandy Dunlap  */
1105b8e162f9SBart Van Assche static enum scsi_disposition scsi_send_eh_cmnd(struct scsi_cmnd *scmd,
1106b8e162f9SBart Van Assche 	unsigned char *cmnd, int cmnd_size, int timeout, unsigned sense_bytes)
1107e1c23468SBoaz Harrosh {
1108e1c23468SBoaz Harrosh 	struct scsi_device *sdev = scmd->device;
1109e1c23468SBoaz Harrosh 	struct Scsi_Host *shost = sdev->host;
1110e1c23468SBoaz Harrosh 	DECLARE_COMPLETION_ONSTACK(done);
1111bbe9fb0dSBart Van Assche 	unsigned long timeleft = timeout, delay;
1112e1c23468SBoaz Harrosh 	struct scsi_eh_save ses;
1113fc73648aSHannes Reinecke 	const unsigned long stall_for = msecs_to_jiffies(100);
1114e1c23468SBoaz Harrosh 	int rtn;
1115e1c23468SBoaz Harrosh 
1116fc73648aSHannes Reinecke retry:
1117e1c23468SBoaz Harrosh 	scsi_eh_prep_cmnd(scmd, &ses, cmnd, cmnd_size, sense_bytes);
11187dfdc9a5SChristoph Hellwig 	shost->eh_action = &done;
11191da177e4SLinus Torvalds 
11201da177e4SLinus Torvalds 	scsi_log_send(scmd);
1121bf23e619SBart Van Assche 	scmd->submitter = SUBMITTED_BY_SCSI_ERROR_HANDLER;
1122bbe9fb0dSBart Van Assche 
1123bbe9fb0dSBart Van Assche 	/*
1124bbe9fb0dSBart Van Assche 	 * Lock sdev->state_mutex to avoid that scsi_device_quiesce() can
1125bbe9fb0dSBart Van Assche 	 * change the SCSI device state after we have examined it and before
1126bbe9fb0dSBart Van Assche 	 * .queuecommand() is called.
1127bbe9fb0dSBart Van Assche 	 */
1128bbe9fb0dSBart Van Assche 	mutex_lock(&sdev->state_mutex);
1129bbe9fb0dSBart Van Assche 	while (sdev->sdev_state == SDEV_BLOCK && timeleft > 0) {
1130bbe9fb0dSBart Van Assche 		mutex_unlock(&sdev->state_mutex);
1131bbe9fb0dSBart Van Assche 		SCSI_LOG_ERROR_RECOVERY(5, sdev_printk(KERN_DEBUG, sdev,
1132bbe9fb0dSBart Van Assche 			"%s: state %d <> %d\n", __func__, sdev->sdev_state,
1133bbe9fb0dSBart Van Assche 			SDEV_BLOCK));
1134bbe9fb0dSBart Van Assche 		delay = min(timeleft, stall_for);
1135bbe9fb0dSBart Van Assche 		timeleft -= delay;
1136bbe9fb0dSBart Van Assche 		msleep(jiffies_to_msecs(delay));
1137bbe9fb0dSBart Van Assche 		mutex_lock(&sdev->state_mutex);
1138bbe9fb0dSBart Van Assche 	}
1139bbe9fb0dSBart Van Assche 	if (sdev->sdev_state != SDEV_BLOCK)
1140fc73648aSHannes Reinecke 		rtn = shost->hostt->queuecommand(shost, scmd);
1141bbe9fb0dSBart Van Assche 	else
1142280e91b0SBart Van Assche 		rtn = FAILED;
1143bbe9fb0dSBart Van Assche 	mutex_unlock(&sdev->state_mutex);
1144bbe9fb0dSBart Van Assche 
1145fc73648aSHannes Reinecke 	if (rtn) {
1146fc73648aSHannes Reinecke 		if (timeleft > stall_for) {
1147fc73648aSHannes Reinecke 			scsi_eh_restore_cmnd(scmd, &ses);
1148bf23e619SBart Van Assche 
1149fc73648aSHannes Reinecke 			timeleft -= stall_for;
1150fc73648aSHannes Reinecke 			msleep(jiffies_to_msecs(stall_for));
1151fc73648aSHannes Reinecke 			goto retry;
1152fc73648aSHannes Reinecke 		}
1153fc73648aSHannes Reinecke 		/* signal not to enter either branch of the if () below */
1154fc73648aSHannes Reinecke 		timeleft = 0;
1155511833acSAlan Stern 		rtn = FAILED;
1156fc73648aSHannes Reinecke 	} else {
11577dfdc9a5SChristoph Hellwig 		timeleft = wait_for_completion_timeout(&done, timeout);
1158ac61d195SHannes Reinecke 		rtn = SUCCESS;
1159fc73648aSHannes Reinecke 	}
11601da177e4SLinus Torvalds 
11617dfdc9a5SChristoph Hellwig 	shost->eh_action = NULL;
11621da177e4SLinus Torvalds 
1163fc73648aSHannes Reinecke 	scsi_log_completion(scmd, rtn);
11647dfdc9a5SChristoph Hellwig 
116591921e01SHannes Reinecke 	SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
1166470613b4SHannes Reinecke 			"%s timeleft: %ld\n",
1167470613b4SHannes Reinecke 			__func__, timeleft));
11681da177e4SLinus Torvalds 
11691da177e4SLinus Torvalds 	/*
1170fc73648aSHannes Reinecke 	 * If there is time left scsi_eh_done got called, and we will examine
1171fc73648aSHannes Reinecke 	 * the actual status codes to see whether the command actually did
1172fc73648aSHannes Reinecke 	 * complete normally, else if we have a zero return and no time left,
1173fc73648aSHannes Reinecke 	 * the command must still be pending, so abort it and return FAILED.
1174fc73648aSHannes Reinecke 	 * If we never actually managed to issue the command, because
1175fc73648aSHannes Reinecke 	 * ->queuecommand() kept returning non zero, use the rtn = FAILED
1176fc73648aSHannes Reinecke 	 * value above (so don't execute either branch of the if)
11771da177e4SLinus Torvalds 	 */
11787dfdc9a5SChristoph Hellwig 	if (timeleft) {
11791da177e4SLinus Torvalds 		rtn = scsi_eh_completed_normally(scmd);
118091921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
118191921e01SHannes Reinecke 			"%s: scsi_eh_completed_normally %x\n", __func__, rtn));
11827dfdc9a5SChristoph Hellwig 
11831da177e4SLinus Torvalds 		switch (rtn) {
11841da177e4SLinus Torvalds 		case SUCCESS:
11851da177e4SLinus Torvalds 		case NEEDS_RETRY:
11861da177e4SLinus Torvalds 		case FAILED:
11871da177e4SLinus Torvalds 			break;
11886e883b0eSHannes Reinecke 		case ADD_TO_MLQUEUE:
11896e883b0eSHannes Reinecke 			rtn = NEEDS_RETRY;
11906e883b0eSHannes Reinecke 			break;
11911da177e4SLinus Torvalds 		default:
11921da177e4SLinus Torvalds 			rtn = FAILED;
11931da177e4SLinus Torvalds 			break;
11941da177e4SLinus Torvalds 		}
1195511833acSAlan Stern 	} else if (rtn != FAILED) {
1196292148f8SBrian King 		scsi_abort_eh_cmnd(scmd);
11977dfdc9a5SChristoph Hellwig 		rtn = FAILED;
11981da177e4SLinus Torvalds 	}
11991da177e4SLinus Torvalds 
1200e1c23468SBoaz Harrosh 	scsi_eh_restore_cmnd(scmd, &ses);
120118a4d0a2SMartin K. Petersen 
12021da177e4SLinus Torvalds 	return rtn;
12031da177e4SLinus Torvalds }
12041da177e4SLinus Torvalds 
12051da177e4SLinus Torvalds /**
12061da177e4SLinus Torvalds  * scsi_request_sense - Request sense data from a particular target.
12071da177e4SLinus Torvalds  * @scmd:	SCSI cmd for request sense.
12081da177e4SLinus Torvalds  *
12091da177e4SLinus Torvalds  * Notes:
12101da177e4SLinus Torvalds  *    Some hosts automatically obtain this information, others require
12111da177e4SLinus Torvalds  *    that we obtain it on our own. This function will *not* return until
12121da177e4SLinus Torvalds  *    the command either times out, or it completes.
1213dc8875e1SRandy Dunlap  */
1214b8e162f9SBart Van Assche static enum scsi_disposition scsi_request_sense(struct scsi_cmnd *scmd)
12151da177e4SLinus Torvalds {
12160816c925SMartin K. Petersen 	return scsi_send_eh_cmnd(scmd, NULL, 0, scmd->device->eh_timeout, ~0);
12171da177e4SLinus Torvalds }
12181da177e4SLinus Torvalds 
1219b8e162f9SBart Van Assche static enum scsi_disposition
1220b8e162f9SBart Van Assche scsi_eh_action(struct scsi_cmnd *scmd, enum scsi_disposition rtn)
12212451079bSJames Bottomley {
1222aa8e25e5SBart Van Assche 	if (!blk_rq_is_passthrough(scsi_cmd_to_rq(scmd))) {
12232451079bSJames Bottomley 		struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd);
12242451079bSJames Bottomley 		if (sdrv->eh_action)
12252451079bSJames Bottomley 			rtn = sdrv->eh_action(scmd, rtn);
12262451079bSJames Bottomley 	}
12272451079bSJames Bottomley 	return rtn;
12282451079bSJames Bottomley }
12292451079bSJames Bottomley 
12301da177e4SLinus Torvalds /**
12311da177e4SLinus Torvalds  * scsi_eh_finish_cmd - Handle a cmd that eh is finished with.
12321da177e4SLinus Torvalds  * @scmd:	Original SCSI cmd that eh has finished.
12331da177e4SLinus Torvalds  * @done_q:	Queue for processed commands.
12341da177e4SLinus Torvalds  *
12351da177e4SLinus Torvalds  * Notes:
12361da177e4SLinus Torvalds  *    We don't want to use the normal command completion while we are are
12371da177e4SLinus Torvalds  *    still handling errors - it may cause other commands to be queued,
1238eb44820cSRob Landley  *    and that would disturb what we are doing.  Thus we really want to
12391da177e4SLinus Torvalds  *    keep a list of pending commands for final completion, and once we
12401da177e4SLinus Torvalds  *    are ready to leave error handling we handle completion for real.
1241dc8875e1SRandy Dunlap  */
1242041c5fc3STejun Heo void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
12431da177e4SLinus Torvalds {
12441da177e4SLinus Torvalds 	list_move_tail(&scmd->eh_entry, done_q);
12451da177e4SLinus Torvalds }
1246041c5fc3STejun Heo EXPORT_SYMBOL(scsi_eh_finish_cmd);
12471da177e4SLinus Torvalds 
12481da177e4SLinus Torvalds /**
12491da177e4SLinus Torvalds  * scsi_eh_get_sense - Get device sense data.
12501da177e4SLinus Torvalds  * @work_q:	Queue of commands to process.
1251eb44820cSRob Landley  * @done_q:	Queue of processed commands.
12521da177e4SLinus Torvalds  *
12531da177e4SLinus Torvalds  * Description:
12541da177e4SLinus Torvalds  *    See if we need to request sense information.  if so, then get it
12551da177e4SLinus Torvalds  *    now, so we have a better idea of what to do.
12561da177e4SLinus Torvalds  *
12571da177e4SLinus Torvalds  * Notes:
12581da177e4SLinus Torvalds  *    This has the unfortunate side effect that if a shost adapter does
1259eb44820cSRob Landley  *    not automatically request sense information, we end up shutting
12601da177e4SLinus Torvalds  *    it down before we request it.
12611da177e4SLinus Torvalds  *
12621da177e4SLinus Torvalds  *    All drivers should request sense information internally these days,
12631da177e4SLinus Torvalds  *    so for now all I have to say is tough noogies if you end up in here.
12641da177e4SLinus Torvalds  *
12651da177e4SLinus Torvalds  *    XXX: Long term this code should go away, but that needs an audit of
12661da177e4SLinus Torvalds  *         all LLDDs first.
1267dc8875e1SRandy Dunlap  */
1268dca84e46SDarrick J. Wong int scsi_eh_get_sense(struct list_head *work_q,
12691da177e4SLinus Torvalds 		      struct list_head *done_q)
12701da177e4SLinus Torvalds {
1271937abeaaSChristoph Hellwig 	struct scsi_cmnd *scmd, *next;
1272b4562022SHannes Reinecke 	struct Scsi_Host *shost;
1273b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
12741da177e4SLinus Torvalds 
1275709c75b5Sjiang.biao2@zte.com.cn 	/*
1276709c75b5Sjiang.biao2@zte.com.cn 	 * If SCSI_EH_ABORT_SCHEDULED has been set, it is timeout IO,
1277709c75b5Sjiang.biao2@zte.com.cn 	 * should not get sense.
1278709c75b5Sjiang.biao2@zte.com.cn 	 */
1279937abeaaSChristoph Hellwig 	list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
1280a0658632SHannes Reinecke 		if ((scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) ||
12811da177e4SLinus Torvalds 		    SCSI_SENSE_VALID(scmd))
12821da177e4SLinus Torvalds 			continue;
12831da177e4SLinus Torvalds 
1284b4562022SHannes Reinecke 		shost = scmd->device->host;
1285b4562022SHannes Reinecke 		if (scsi_host_eh_past_deadline(shost)) {
1286b4562022SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
1287a222b1e2SHannes Reinecke 				scmd_printk(KERN_INFO, scmd,
1288a222b1e2SHannes Reinecke 					    "%s: skip request sense, past eh deadline\n",
1289a222b1e2SHannes Reinecke 					     current->comm));
1290b4562022SHannes Reinecke 			break;
1291b4562022SHannes Reinecke 		}
1292d0672a03SHannes Reinecke 		if (!scsi_status_is_check_condition(scmd->result))
1293d555a2abSJames Bottomley 			/*
1294d555a2abSJames Bottomley 			 * don't request sense if there's no check condition
1295d555a2abSJames Bottomley 			 * status because the error we're processing isn't one
1296d555a2abSJames Bottomley 			 * that has a sense code (and some devices get
1297d555a2abSJames Bottomley 			 * confused by sense requests out of the blue)
1298d555a2abSJames Bottomley 			 */
1299d555a2abSJames Bottomley 			continue;
1300d555a2abSJames Bottomley 
13013bf743e7SJeff Garzik 		SCSI_LOG_ERROR_RECOVERY(2, scmd_printk(KERN_INFO, scmd,
13023bf743e7SJeff Garzik 						  "%s: requesting sense\n",
13033bf743e7SJeff Garzik 						  current->comm));
13041da177e4SLinus Torvalds 		rtn = scsi_request_sense(scmd);
13051da177e4SLinus Torvalds 		if (rtn != SUCCESS)
13061da177e4SLinus Torvalds 			continue;
13071da177e4SLinus Torvalds 
130891921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
1309470613b4SHannes Reinecke 			"sense requested, result %x\n", scmd->result));
1310d811b848SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3, scsi_print_sense(scmd));
13111da177e4SLinus Torvalds 
13121da177e4SLinus Torvalds 		rtn = scsi_decide_disposition(scmd);
13131da177e4SLinus Torvalds 
13141da177e4SLinus Torvalds 		/*
13151da177e4SLinus Torvalds 		 * if the result was normal, then just pass it along to the
13161da177e4SLinus Torvalds 		 * upper level.
13171da177e4SLinus Torvalds 		 */
13181da177e4SLinus Torvalds 		if (rtn == SUCCESS)
13192a242d59SMike Christie 			/*
13202a242d59SMike Christie 			 * We don't want this command reissued, just finished
13212a242d59SMike Christie 			 * with the sense data, so set retries to the max
13222a242d59SMike Christie 			 * allowed to ensure it won't get reissued. If the user
13232a242d59SMike Christie 			 * has requested infinite retries, we also want to
13242a242d59SMike Christie 			 * finish this command, so force completion by setting
13252a242d59SMike Christie 			 * retries and allowed to the same value.
13262a242d59SMike Christie 			 */
13272a242d59SMike Christie 			if (scmd->allowed == SCSI_CMD_RETRIES_NO_LIMIT)
13282a242d59SMike Christie 				scmd->retries = scmd->allowed = 1;
13292a242d59SMike Christie 			else
13301da177e4SLinus Torvalds 				scmd->retries = scmd->allowed;
13311da177e4SLinus Torvalds 		else if (rtn != NEEDS_RETRY)
13321da177e4SLinus Torvalds 			continue;
13331da177e4SLinus Torvalds 
13341da177e4SLinus Torvalds 		scsi_eh_finish_cmd(scmd, done_q);
13351da177e4SLinus Torvalds 	}
13361da177e4SLinus Torvalds 
13371da177e4SLinus Torvalds 	return list_empty(work_q);
13381da177e4SLinus Torvalds }
1339dca84e46SDarrick J. Wong EXPORT_SYMBOL_GPL(scsi_eh_get_sense);
13401da177e4SLinus Torvalds 
13411da177e4SLinus Torvalds /**
13421da177e4SLinus Torvalds  * scsi_eh_tur - Send TUR to device.
1343eb44820cSRob Landley  * @scmd:	&scsi_cmnd to send TUR
13441da177e4SLinus Torvalds  *
13451da177e4SLinus Torvalds  * Return value:
13461da177e4SLinus Torvalds  *    0 - Device is ready. 1 - Device NOT ready.
1347dc8875e1SRandy Dunlap  */
13481da177e4SLinus Torvalds static int scsi_eh_tur(struct scsi_cmnd *scmd)
13491da177e4SLinus Torvalds {
13501da177e4SLinus Torvalds 	static unsigned char tur_command[6] = {TEST_UNIT_READY, 0, 0, 0, 0, 0};
1351b8e162f9SBart Van Assche 	int retry_cnt = 1;
1352b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
13531da177e4SLinus Torvalds 
13541da177e4SLinus Torvalds retry_tur:
13550816c925SMartin K. Petersen 	rtn = scsi_send_eh_cmnd(scmd, tur_command, 6,
13560816c925SMartin K. Petersen 				scmd->device->eh_timeout, 0);
13571da177e4SLinus Torvalds 
135891921e01SHannes Reinecke 	SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
1359470613b4SHannes Reinecke 		"%s return: %x\n", __func__, rtn));
1360631c228cSChristoph Hellwig 
1361631c228cSChristoph Hellwig 	switch (rtn) {
1362631c228cSChristoph Hellwig 	case NEEDS_RETRY:
13631da177e4SLinus Torvalds 		if (retry_cnt--)
13641da177e4SLinus Torvalds 			goto retry_tur;
1365df561f66SGustavo A. R. Silva 		fallthrough;
1366631c228cSChristoph Hellwig 	case SUCCESS:
1367e47373ecSAlan Stern 		return 0;
1368631c228cSChristoph Hellwig 	default:
13691da177e4SLinus Torvalds 		return 1;
13701da177e4SLinus Torvalds 	}
1371631c228cSChristoph Hellwig }
13721da177e4SLinus Torvalds 
13731da177e4SLinus Torvalds /**
13743eef6257SDavid Jeffery  * scsi_eh_test_devices - check if devices are responding from error recovery.
13753eef6257SDavid Jeffery  * @cmd_list:	scsi commands in error recovery.
13763eef6257SDavid Jeffery  * @work_q:	queue for commands which still need more error recovery
13773eef6257SDavid Jeffery  * @done_q:	queue for commands which are finished
13783eef6257SDavid Jeffery  * @try_stu:	boolean on if a STU command should be tried in addition to TUR.
13793eef6257SDavid Jeffery  *
13803eef6257SDavid Jeffery  * Decription:
13813eef6257SDavid Jeffery  *    Tests if devices are in a working state.  Commands to devices now in
13823eef6257SDavid Jeffery  *    a working state are sent to the done_q while commands to devices which
13833eef6257SDavid Jeffery  *    are still failing to respond are returned to the work_q for more
13843eef6257SDavid Jeffery  *    processing.
13853eef6257SDavid Jeffery  **/
13863eef6257SDavid Jeffery static int scsi_eh_test_devices(struct list_head *cmd_list,
13873eef6257SDavid Jeffery 				struct list_head *work_q,
13883eef6257SDavid Jeffery 				struct list_head *done_q, int try_stu)
13893eef6257SDavid Jeffery {
13903eef6257SDavid Jeffery 	struct scsi_cmnd *scmd, *next;
13913eef6257SDavid Jeffery 	struct scsi_device *sdev;
13923eef6257SDavid Jeffery 	int finish_cmds;
13933eef6257SDavid Jeffery 
13943eef6257SDavid Jeffery 	while (!list_empty(cmd_list)) {
13953eef6257SDavid Jeffery 		scmd = list_entry(cmd_list->next, struct scsi_cmnd, eh_entry);
13963eef6257SDavid Jeffery 		sdev = scmd->device;
13973eef6257SDavid Jeffery 
1398b4562022SHannes Reinecke 		if (!try_stu) {
1399b4562022SHannes Reinecke 			if (scsi_host_eh_past_deadline(sdev->host)) {
1400b4562022SHannes Reinecke 				/* Push items back onto work_q */
1401b4562022SHannes Reinecke 				list_splice_init(cmd_list, work_q);
1402b4562022SHannes Reinecke 				SCSI_LOG_ERROR_RECOVERY(3,
1403a222b1e2SHannes Reinecke 					sdev_printk(KERN_INFO, sdev,
1404a222b1e2SHannes Reinecke 						    "%s: skip test device, past eh deadline",
1405a222b1e2SHannes Reinecke 						    current->comm));
1406b4562022SHannes Reinecke 				break;
1407b4562022SHannes Reinecke 			}
1408b4562022SHannes Reinecke 		}
1409b4562022SHannes Reinecke 
14103eef6257SDavid Jeffery 		finish_cmds = !scsi_device_online(scmd->device) ||
14113eef6257SDavid Jeffery 			(try_stu && !scsi_eh_try_stu(scmd) &&
14123eef6257SDavid Jeffery 			 !scsi_eh_tur(scmd)) ||
14133eef6257SDavid Jeffery 			!scsi_eh_tur(scmd);
14143eef6257SDavid Jeffery 
14153eef6257SDavid Jeffery 		list_for_each_entry_safe(scmd, next, cmd_list, eh_entry)
14163eef6257SDavid Jeffery 			if (scmd->device == sdev) {
14172451079bSJames Bottomley 				if (finish_cmds &&
14182451079bSJames Bottomley 				    (try_stu ||
14192451079bSJames Bottomley 				     scsi_eh_action(scmd, SUCCESS) == SUCCESS))
14203eef6257SDavid Jeffery 					scsi_eh_finish_cmd(scmd, done_q);
14213eef6257SDavid Jeffery 				else
14223eef6257SDavid Jeffery 					list_move_tail(&scmd->eh_entry, work_q);
14233eef6257SDavid Jeffery 			}
14243eef6257SDavid Jeffery 	}
14253eef6257SDavid Jeffery 	return list_empty(work_q);
14263eef6257SDavid Jeffery }
14273eef6257SDavid Jeffery 
14281da177e4SLinus Torvalds /**
14291da177e4SLinus Torvalds  * scsi_eh_try_stu - Send START_UNIT to device.
1430eb44820cSRob Landley  * @scmd:	&scsi_cmnd to send START_UNIT
14311da177e4SLinus Torvalds  *
14321da177e4SLinus Torvalds  * Return value:
14331da177e4SLinus Torvalds  *    0 - Device is ready. 1 - Device NOT ready.
1434dc8875e1SRandy Dunlap  */
14351da177e4SLinus Torvalds static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
14361da177e4SLinus Torvalds {
14371da177e4SLinus Torvalds 	static unsigned char stu_command[6] = {START_STOP, 0, 0, 0, 1, 0};
14381da177e4SLinus Torvalds 
1439631c228cSChristoph Hellwig 	if (scmd->device->allow_restart) {
1440b8e162f9SBart Van Assche 		int i;
1441b8e162f9SBart Van Assche 		enum scsi_disposition rtn = NEEDS_RETRY;
14421da177e4SLinus Torvalds 
1443ed773e66SBrian King 		for (i = 0; rtn == NEEDS_RETRY && i < 2; i++)
1444adcc796bSChunguang Xu 			rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
1445adcc796bSChunguang Xu 						scmd->device->eh_timeout, 0);
1446ed773e66SBrian King 
14471da177e4SLinus Torvalds 		if (rtn == SUCCESS)
14481da177e4SLinus Torvalds 			return 0;
1449631c228cSChristoph Hellwig 	}
1450631c228cSChristoph Hellwig 
14511da177e4SLinus Torvalds 	return 1;
14521da177e4SLinus Torvalds }
14531da177e4SLinus Torvalds 
14541da177e4SLinus Torvalds  /**
14551da177e4SLinus Torvalds  * scsi_eh_stu - send START_UNIT if needed
1456eb44820cSRob Landley  * @shost:	&scsi host being recovered.
1457eb44820cSRob Landley  * @work_q:	&list_head for pending commands.
1458eb44820cSRob Landley  * @done_q:	&list_head for processed commands.
14591da177e4SLinus Torvalds  *
14601da177e4SLinus Torvalds  * Notes:
14611da177e4SLinus Torvalds  *    If commands are failing due to not ready, initializing command required,
14621da177e4SLinus Torvalds  *	try revalidating the device, which will end up sending a start unit.
1463dc8875e1SRandy Dunlap  */
14641da177e4SLinus Torvalds static int scsi_eh_stu(struct Scsi_Host *shost,
14651da177e4SLinus Torvalds 			      struct list_head *work_q,
14661da177e4SLinus Torvalds 			      struct list_head *done_q)
14671da177e4SLinus Torvalds {
1468937abeaaSChristoph Hellwig 	struct scsi_cmnd *scmd, *stu_scmd, *next;
14691da177e4SLinus Torvalds 	struct scsi_device *sdev;
14701da177e4SLinus Torvalds 
14711da177e4SLinus Torvalds 	shost_for_each_device(sdev, shost) {
1472b4562022SHannes Reinecke 		if (scsi_host_eh_past_deadline(shost)) {
1473b4562022SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
1474a222b1e2SHannes Reinecke 				sdev_printk(KERN_INFO, sdev,
1475a222b1e2SHannes Reinecke 					    "%s: skip START_UNIT, past eh deadline\n",
1476a222b1e2SHannes Reinecke 					    current->comm));
14774dea170fSYe Bin 			scsi_device_put(sdev);
1478b4562022SHannes Reinecke 			break;
1479b4562022SHannes Reinecke 		}
14801da177e4SLinus Torvalds 		stu_scmd = NULL;
14811da177e4SLinus Torvalds 		list_for_each_entry(scmd, work_q, eh_entry)
14821da177e4SLinus Torvalds 			if (scmd->device == sdev && SCSI_SENSE_VALID(scmd) &&
14831da177e4SLinus Torvalds 			    scsi_check_sense(scmd) == FAILED ) {
14841da177e4SLinus Torvalds 				stu_scmd = scmd;
14851da177e4SLinus Torvalds 				break;
14861da177e4SLinus Torvalds 			}
14871da177e4SLinus Torvalds 
14881da177e4SLinus Torvalds 		if (!stu_scmd)
14891da177e4SLinus Torvalds 			continue;
14901da177e4SLinus Torvalds 
149191921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3,
1492a222b1e2SHannes Reinecke 			sdev_printk(KERN_INFO, sdev,
1493a222b1e2SHannes Reinecke 				     "%s: Sending START_UNIT\n",
1494a222b1e2SHannes Reinecke 				    current->comm));
14951da177e4SLinus Torvalds 
14961da177e4SLinus Torvalds 		if (!scsi_eh_try_stu(stu_scmd)) {
14971da177e4SLinus Torvalds 			if (!scsi_device_online(sdev) ||
14981da177e4SLinus Torvalds 			    !scsi_eh_tur(stu_scmd)) {
1499937abeaaSChristoph Hellwig 				list_for_each_entry_safe(scmd, next,
1500937abeaaSChristoph Hellwig 							  work_q, eh_entry) {
15012451079bSJames Bottomley 					if (scmd->device == sdev &&
15022451079bSJames Bottomley 					    scsi_eh_action(scmd, SUCCESS) == SUCCESS)
15031da177e4SLinus Torvalds 						scsi_eh_finish_cmd(scmd, done_q);
15041da177e4SLinus Torvalds 				}
15051da177e4SLinus Torvalds 			}
15061da177e4SLinus Torvalds 		} else {
15071da177e4SLinus Torvalds 			SCSI_LOG_ERROR_RECOVERY(3,
1508a222b1e2SHannes Reinecke 				sdev_printk(KERN_INFO, sdev,
1509a222b1e2SHannes Reinecke 					    "%s: START_UNIT failed\n",
1510a222b1e2SHannes Reinecke 					    current->comm));
15111da177e4SLinus Torvalds 		}
15121da177e4SLinus Torvalds 	}
15131da177e4SLinus Torvalds 
15141da177e4SLinus Torvalds 	return list_empty(work_q);
15151da177e4SLinus Torvalds }
15161da177e4SLinus Torvalds 
15171da177e4SLinus Torvalds 
15181da177e4SLinus Torvalds /**
15191da177e4SLinus Torvalds  * scsi_eh_bus_device_reset - send bdr if needed
15201da177e4SLinus Torvalds  * @shost:	scsi host being recovered.
1521eb44820cSRob Landley  * @work_q:	&list_head for pending commands.
1522eb44820cSRob Landley  * @done_q:	&list_head for processed commands.
15231da177e4SLinus Torvalds  *
15241da177e4SLinus Torvalds  * Notes:
1525eb44820cSRob Landley  *    Try a bus device reset.  Still, look to see whether we have multiple
15261da177e4SLinus Torvalds  *    devices that are jammed or not - if we have multiple devices, it
15271da177e4SLinus Torvalds  *    makes no sense to try bus_device_reset - we really would need to try
15281da177e4SLinus Torvalds  *    a bus_reset instead.
1529dc8875e1SRandy Dunlap  */
15301da177e4SLinus Torvalds static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
15311da177e4SLinus Torvalds 				    struct list_head *work_q,
15321da177e4SLinus Torvalds 				    struct list_head *done_q)
15331da177e4SLinus Torvalds {
1534937abeaaSChristoph Hellwig 	struct scsi_cmnd *scmd, *bdr_scmd, *next;
15351da177e4SLinus Torvalds 	struct scsi_device *sdev;
1536b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
15371da177e4SLinus Torvalds 
15381da177e4SLinus Torvalds 	shost_for_each_device(sdev, shost) {
1539b4562022SHannes Reinecke 		if (scsi_host_eh_past_deadline(shost)) {
1540b4562022SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
1541a222b1e2SHannes Reinecke 				sdev_printk(KERN_INFO, sdev,
1542a222b1e2SHannes Reinecke 					    "%s: skip BDR, past eh deadline\n",
1543a222b1e2SHannes Reinecke 					     current->comm));
15444dea170fSYe Bin 			scsi_device_put(sdev);
1545b4562022SHannes Reinecke 			break;
1546b4562022SHannes Reinecke 		}
15471da177e4SLinus Torvalds 		bdr_scmd = NULL;
15481da177e4SLinus Torvalds 		list_for_each_entry(scmd, work_q, eh_entry)
15491da177e4SLinus Torvalds 			if (scmd->device == sdev) {
15501da177e4SLinus Torvalds 				bdr_scmd = scmd;
15511da177e4SLinus Torvalds 				break;
15521da177e4SLinus Torvalds 			}
15531da177e4SLinus Torvalds 
15541da177e4SLinus Torvalds 		if (!bdr_scmd)
15551da177e4SLinus Torvalds 			continue;
15561da177e4SLinus Torvalds 
155791921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3,
1558a222b1e2SHannes Reinecke 			sdev_printk(KERN_INFO, sdev,
1559a222b1e2SHannes Reinecke 				     "%s: Sending BDR\n", current->comm));
15601da177e4SLinus Torvalds 		rtn = scsi_try_bus_device_reset(bdr_scmd);
15612f2eb587SChristof Schmitt 		if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
15621da177e4SLinus Torvalds 			if (!scsi_device_online(sdev) ||
15632f2eb587SChristof Schmitt 			    rtn == FAST_IO_FAIL ||
15641da177e4SLinus Torvalds 			    !scsi_eh_tur(bdr_scmd)) {
1565937abeaaSChristoph Hellwig 				list_for_each_entry_safe(scmd, next,
1566937abeaaSChristoph Hellwig 							 work_q, eh_entry) {
15672451079bSJames Bottomley 					if (scmd->device == sdev &&
15682451079bSJames Bottomley 					    scsi_eh_action(scmd, rtn) != FAILED)
15691da177e4SLinus Torvalds 						scsi_eh_finish_cmd(scmd,
15701da177e4SLinus Torvalds 								   done_q);
15711da177e4SLinus Torvalds 				}
15721da177e4SLinus Torvalds 			}
15731da177e4SLinus Torvalds 		} else {
157491921e01SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
1575a222b1e2SHannes Reinecke 				sdev_printk(KERN_INFO, sdev,
1576a222b1e2SHannes Reinecke 					    "%s: BDR failed\n", current->comm));
15771da177e4SLinus Torvalds 		}
15781da177e4SLinus Torvalds 	}
15791da177e4SLinus Torvalds 
15801da177e4SLinus Torvalds 	return list_empty(work_q);
15811da177e4SLinus Torvalds }
15821da177e4SLinus Torvalds 
15831da177e4SLinus Torvalds /**
158430bd7df8SMike Christie  * scsi_eh_target_reset - send target reset if needed
158530bd7df8SMike Christie  * @shost:	scsi host being recovered.
158630bd7df8SMike Christie  * @work_q:	&list_head for pending commands.
158730bd7df8SMike Christie  * @done_q:	&list_head for processed commands.
158830bd7df8SMike Christie  *
158930bd7df8SMike Christie  * Notes:
159030bd7df8SMike Christie  *    Try a target reset.
159130bd7df8SMike Christie  */
159230bd7df8SMike Christie static int scsi_eh_target_reset(struct Scsi_Host *shost,
159330bd7df8SMike Christie 				struct list_head *work_q,
159430bd7df8SMike Christie 				struct list_head *done_q)
159530bd7df8SMike Christie {
159698db5195SJames Bottomley 	LIST_HEAD(tmp_list);
15973eef6257SDavid Jeffery 	LIST_HEAD(check_list);
159830bd7df8SMike Christie 
159998db5195SJames Bottomley 	list_splice_init(work_q, &tmp_list);
160098db5195SJames Bottomley 
160198db5195SJames Bottomley 	while (!list_empty(&tmp_list)) {
160298db5195SJames Bottomley 		struct scsi_cmnd *next, *scmd;
1603b8e162f9SBart Van Assche 		enum scsi_disposition rtn;
160498db5195SJames Bottomley 		unsigned int id;
1605b4562022SHannes Reinecke 
1606b4562022SHannes Reinecke 		if (scsi_host_eh_past_deadline(shost)) {
1607b4562022SHannes Reinecke 			/* push back on work queue for further processing */
1608b4562022SHannes Reinecke 			list_splice_init(&check_list, work_q);
1609b4562022SHannes Reinecke 			list_splice_init(&tmp_list, work_q);
1610b4562022SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
1611b4562022SHannes Reinecke 				shost_printk(KERN_INFO, shost,
1612a222b1e2SHannes Reinecke 					    "%s: Skip target reset, past eh deadline\n",
1613a222b1e2SHannes Reinecke 					     current->comm));
1614b4562022SHannes Reinecke 			return list_empty(work_q);
1615b4562022SHannes Reinecke 		}
161698db5195SJames Bottomley 
161798db5195SJames Bottomley 		scmd = list_entry(tmp_list.next, struct scsi_cmnd, eh_entry);
161898db5195SJames Bottomley 		id = scmd_id(scmd);
161930bd7df8SMike Christie 
162091921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3,
162191921e01SHannes Reinecke 			shost_printk(KERN_INFO, shost,
162291921e01SHannes Reinecke 				     "%s: Sending target reset to target %d\n",
162330bd7df8SMike Christie 				     current->comm, id));
162498db5195SJames Bottomley 		rtn = scsi_try_target_reset(scmd);
162598db5195SJames Bottomley 		if (rtn != SUCCESS && rtn != FAST_IO_FAIL)
162691921e01SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
162791921e01SHannes Reinecke 				shost_printk(KERN_INFO, shost,
162891921e01SHannes Reinecke 					     "%s: Target reset failed"
162991921e01SHannes Reinecke 					     " target: %d\n",
163030bd7df8SMike Christie 					     current->comm, id));
163198db5195SJames Bottomley 		list_for_each_entry_safe(scmd, next, &tmp_list, eh_entry) {
163298db5195SJames Bottomley 			if (scmd_id(scmd) != id)
163398db5195SJames Bottomley 				continue;
163498db5195SJames Bottomley 
16353eef6257SDavid Jeffery 			if (rtn == SUCCESS)
16363eef6257SDavid Jeffery 				list_move_tail(&scmd->eh_entry, &check_list);
16373eef6257SDavid Jeffery 			else if (rtn == FAST_IO_FAIL)
163898db5195SJames Bottomley 				scsi_eh_finish_cmd(scmd, done_q);
163998db5195SJames Bottomley 			else
164098db5195SJames Bottomley 				/* push back on work queue for further processing */
164198db5195SJames Bottomley 				list_move(&scmd->eh_entry, work_q);
164298db5195SJames Bottomley 		}
164398db5195SJames Bottomley 	}
164430bd7df8SMike Christie 
16453eef6257SDavid Jeffery 	return scsi_eh_test_devices(&check_list, work_q, done_q, 0);
164630bd7df8SMike Christie }
164730bd7df8SMike Christie 
164830bd7df8SMike Christie /**
16491da177e4SLinus Torvalds  * scsi_eh_bus_reset - send a bus reset
1650eb44820cSRob Landley  * @shost:	&scsi host being recovered.
1651eb44820cSRob Landley  * @work_q:	&list_head for pending commands.
1652eb44820cSRob Landley  * @done_q:	&list_head for processed commands.
1653dc8875e1SRandy Dunlap  */
16541da177e4SLinus Torvalds static int scsi_eh_bus_reset(struct Scsi_Host *shost,
16551da177e4SLinus Torvalds 			     struct list_head *work_q,
16561da177e4SLinus Torvalds 			     struct list_head *done_q)
16571da177e4SLinus Torvalds {
1658937abeaaSChristoph Hellwig 	struct scsi_cmnd *scmd, *chan_scmd, *next;
16593eef6257SDavid Jeffery 	LIST_HEAD(check_list);
16601da177e4SLinus Torvalds 	unsigned int channel;
1661b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
16621da177e4SLinus Torvalds 
16631da177e4SLinus Torvalds 	/*
16641da177e4SLinus Torvalds 	 * we really want to loop over the various channels, and do this on
16651da177e4SLinus Torvalds 	 * a channel by channel basis.  we should also check to see if any
16661da177e4SLinus Torvalds 	 * of the failed commands are on soft_reset devices, and if so, skip
16671da177e4SLinus Torvalds 	 * the reset.
16681da177e4SLinus Torvalds 	 */
16691da177e4SLinus Torvalds 
16701da177e4SLinus Torvalds 	for (channel = 0; channel <= shost->max_channel; channel++) {
1671b4562022SHannes Reinecke 		if (scsi_host_eh_past_deadline(shost)) {
1672b4562022SHannes Reinecke 			list_splice_init(&check_list, work_q);
1673b4562022SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
1674b4562022SHannes Reinecke 				shost_printk(KERN_INFO, shost,
1675a222b1e2SHannes Reinecke 					    "%s: skip BRST, past eh deadline\n",
1676a222b1e2SHannes Reinecke 					     current->comm));
1677b4562022SHannes Reinecke 			return list_empty(work_q);
1678b4562022SHannes Reinecke 		}
1679b4562022SHannes Reinecke 
16801da177e4SLinus Torvalds 		chan_scmd = NULL;
16811da177e4SLinus Torvalds 		list_for_each_entry(scmd, work_q, eh_entry) {
1682422c0d61SJeff Garzik 			if (channel == scmd_channel(scmd)) {
16831da177e4SLinus Torvalds 				chan_scmd = scmd;
16841da177e4SLinus Torvalds 				break;
16851da177e4SLinus Torvalds 				/*
16861da177e4SLinus Torvalds 				 * FIXME add back in some support for
16871da177e4SLinus Torvalds 				 * soft_reset devices.
16881da177e4SLinus Torvalds 				 */
16891da177e4SLinus Torvalds 			}
16901da177e4SLinus Torvalds 		}
16911da177e4SLinus Torvalds 
16921da177e4SLinus Torvalds 		if (!chan_scmd)
16931da177e4SLinus Torvalds 			continue;
169491921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3,
169591921e01SHannes Reinecke 			shost_printk(KERN_INFO, shost,
169691921e01SHannes Reinecke 				     "%s: Sending BRST chan: %d\n",
169791921e01SHannes Reinecke 				     current->comm, channel));
16981da177e4SLinus Torvalds 		rtn = scsi_try_bus_reset(chan_scmd);
16992f2eb587SChristof Schmitt 		if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
1700937abeaaSChristoph Hellwig 			list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
17013eef6257SDavid Jeffery 				if (channel == scmd_channel(scmd)) {
17023eef6257SDavid Jeffery 					if (rtn == FAST_IO_FAIL)
17031da177e4SLinus Torvalds 						scsi_eh_finish_cmd(scmd,
17041da177e4SLinus Torvalds 								   done_q);
17053eef6257SDavid Jeffery 					else
17063eef6257SDavid Jeffery 						list_move_tail(&scmd->eh_entry,
17073eef6257SDavid Jeffery 							       &check_list);
17083eef6257SDavid Jeffery 				}
17091da177e4SLinus Torvalds 			}
17101da177e4SLinus Torvalds 		} else {
171191921e01SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
171291921e01SHannes Reinecke 				shost_printk(KERN_INFO, shost,
171391921e01SHannes Reinecke 					     "%s: BRST failed chan: %d\n",
171491921e01SHannes Reinecke 					     current->comm, channel));
17151da177e4SLinus Torvalds 		}
17161da177e4SLinus Torvalds 	}
17173eef6257SDavid Jeffery 	return scsi_eh_test_devices(&check_list, work_q, done_q, 0);
17181da177e4SLinus Torvalds }
17191da177e4SLinus Torvalds 
17201da177e4SLinus Torvalds /**
17211da177e4SLinus Torvalds  * scsi_eh_host_reset - send a host reset
172274cf298fSRandy Dunlap  * @shost:	host to be reset.
172374cf298fSRandy Dunlap  * @work_q:	&list_head for pending commands.
172474cf298fSRandy Dunlap  * @done_q:	&list_head for processed commands.
1725dc8875e1SRandy Dunlap  */
172691921e01SHannes Reinecke static int scsi_eh_host_reset(struct Scsi_Host *shost,
172791921e01SHannes Reinecke 			      struct list_head *work_q,
17281da177e4SLinus Torvalds 			      struct list_head *done_q)
17291da177e4SLinus Torvalds {
1730937abeaaSChristoph Hellwig 	struct scsi_cmnd *scmd, *next;
17313eef6257SDavid Jeffery 	LIST_HEAD(check_list);
1732b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
17331da177e4SLinus Torvalds 
17341da177e4SLinus Torvalds 	if (!list_empty(work_q)) {
17351da177e4SLinus Torvalds 		scmd = list_entry(work_q->next,
17361da177e4SLinus Torvalds 				  struct scsi_cmnd, eh_entry);
17371da177e4SLinus Torvalds 
173891921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(3,
173991921e01SHannes Reinecke 			shost_printk(KERN_INFO, shost,
174091921e01SHannes Reinecke 				     "%s: Sending HRST\n",
174191921e01SHannes Reinecke 				     current->comm));
17421da177e4SLinus Torvalds 
17431da177e4SLinus Torvalds 		rtn = scsi_try_host_reset(scmd);
17443eef6257SDavid Jeffery 		if (rtn == SUCCESS) {
17453eef6257SDavid Jeffery 			list_splice_init(work_q, &check_list);
17463eef6257SDavid Jeffery 		} else if (rtn == FAST_IO_FAIL) {
1747937abeaaSChristoph Hellwig 			list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
17481da177e4SLinus Torvalds 					scsi_eh_finish_cmd(scmd, done_q);
17491da177e4SLinus Torvalds 			}
17501da177e4SLinus Torvalds 		} else {
175191921e01SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
175291921e01SHannes Reinecke 				shost_printk(KERN_INFO, shost,
175391921e01SHannes Reinecke 					     "%s: HRST failed\n",
17541da177e4SLinus Torvalds 					     current->comm));
17551da177e4SLinus Torvalds 		}
17561da177e4SLinus Torvalds 	}
17573eef6257SDavid Jeffery 	return scsi_eh_test_devices(&check_list, work_q, done_q, 1);
17581da177e4SLinus Torvalds }
17591da177e4SLinus Torvalds 
17601da177e4SLinus Torvalds /**
17611da177e4SLinus Torvalds  * scsi_eh_offline_sdevs - offline scsi devices that fail to recover
176274cf298fSRandy Dunlap  * @work_q:	&list_head for pending commands.
176374cf298fSRandy Dunlap  * @done_q:	&list_head for processed commands.
1764dc8875e1SRandy Dunlap  */
17651da177e4SLinus Torvalds static void scsi_eh_offline_sdevs(struct list_head *work_q,
17661da177e4SLinus Torvalds 				  struct list_head *done_q)
17671da177e4SLinus Torvalds {
1768937abeaaSChristoph Hellwig 	struct scsi_cmnd *scmd, *next;
17690db6ca8aSBart Van Assche 	struct scsi_device *sdev;
17701da177e4SLinus Torvalds 
1771937abeaaSChristoph Hellwig 	list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
177231765d7dSMatthew Wilcox 		sdev_printk(KERN_INFO, scmd->device, "Device offlined - "
177331765d7dSMatthew Wilcox 			    "not ready after error recovery\n");
17740db6ca8aSBart Van Assche 		sdev = scmd->device;
17750db6ca8aSBart Van Assche 
17760db6ca8aSBart Van Assche 		mutex_lock(&sdev->state_mutex);
17770db6ca8aSBart Van Assche 		scsi_device_set_state(sdev, SDEV_OFFLINE);
17780db6ca8aSBart Van Assche 		mutex_unlock(&sdev->state_mutex);
17790db6ca8aSBart Van Assche 
17801da177e4SLinus Torvalds 		scsi_eh_finish_cmd(scmd, done_q);
17811da177e4SLinus Torvalds 	}
17821da177e4SLinus Torvalds 	return;
17831da177e4SLinus Torvalds }
17841da177e4SLinus Torvalds 
17851da177e4SLinus Torvalds /**
1786e494f6a7SHannes Reinecke  * scsi_noretry_cmd - determine if command should be failed fast
17874a27446fSMike Christie  * @scmd:	SCSI cmd to examine.
17884a27446fSMike Christie  */
178988b32c3cSBart Van Assche bool scsi_noretry_cmd(struct scsi_cmnd *scmd)
17904a27446fSMike Christie {
1791aa8e25e5SBart Van Assche 	struct request *req = scsi_cmd_to_rq(scmd);
1792aa8e25e5SBart Van Assche 
17934a27446fSMike Christie 	switch (host_byte(scmd->result)) {
17944a27446fSMike Christie 	case DID_OK:
17954a27446fSMike Christie 		break;
1796e494f6a7SHannes Reinecke 	case DID_TIME_OUT:
1797e494f6a7SHannes Reinecke 		goto check_type;
17984a27446fSMike Christie 	case DID_BUS_BUSY:
179988b32c3cSBart Van Assche 		return !!(req->cmd_flags & REQ_FAILFAST_TRANSPORT);
18004a27446fSMike Christie 	case DID_PARITY:
180188b32c3cSBart Van Assche 		return !!(req->cmd_flags & REQ_FAILFAST_DEV);
18024a27446fSMike Christie 	case DID_ERROR:
18033d45cefcSHannes Reinecke 		if (get_status_byte(scmd) == SAM_STAT_RESERVATION_CONFLICT)
180488b32c3cSBart Van Assche 			return false;
1805df561f66SGustavo A. R. Silva 		fallthrough;
18064a27446fSMike Christie 	case DID_SOFT_ERROR:
180788b32c3cSBart Van Assche 		return !!(req->cmd_flags & REQ_FAILFAST_DRIVER);
18084a27446fSMike Christie 	}
18094a27446fSMike Christie 
1810d0672a03SHannes Reinecke 	if (!scsi_status_is_check_condition(scmd->result))
181188b32c3cSBart Van Assche 		return false;
1812e494f6a7SHannes Reinecke 
1813e494f6a7SHannes Reinecke check_type:
18144a27446fSMike Christie 	/*
1815e494f6a7SHannes Reinecke 	 * assume caller has checked sense and determined
18164a27446fSMike Christie 	 * the check condition was retryable.
18174a27446fSMike Christie 	 */
1818aa8e25e5SBart Van Assche 	if (req->cmd_flags & REQ_FAILFAST_DEV || blk_rq_is_passthrough(req))
181988b32c3cSBart Van Assche 		return true;
1820342c81eeSDamien Le Moal 
182188b32c3cSBart Van Assche 	return false;
18224a27446fSMike Christie }
18234a27446fSMike Christie 
18244a27446fSMike Christie /**
18251da177e4SLinus Torvalds  * scsi_decide_disposition - Disposition a cmd on return from LLD.
18261da177e4SLinus Torvalds  * @scmd:	SCSI cmd to examine.
18271da177e4SLinus Torvalds  *
18281da177e4SLinus Torvalds  * Notes:
18291da177e4SLinus Torvalds  *    This is *only* called when we are examining the status after sending
18301da177e4SLinus Torvalds  *    out the actual data command.  any commands that are queued for error
18311da177e4SLinus Torvalds  *    recovery (e.g. test_unit_ready) do *not* come through here.
18321da177e4SLinus Torvalds  *
18331da177e4SLinus Torvalds  *    When this routine returns failed, it means the error handler thread
18341da177e4SLinus Torvalds  *    is woken.  In cases where the error code indicates an error that
18351da177e4SLinus Torvalds  *    doesn't require the error handler read (i.e. we don't need to
18361da177e4SLinus Torvalds  *    abort/reset), this function should return SUCCESS.
1837dc8875e1SRandy Dunlap  */
1838b8e162f9SBart Van Assche enum scsi_disposition scsi_decide_disposition(struct scsi_cmnd *scmd)
18391da177e4SLinus Torvalds {
1840b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
18411da177e4SLinus Torvalds 
18421da177e4SLinus Torvalds 	/*
18431da177e4SLinus Torvalds 	 * if the device is offline, then we clearly just pass the result back
18441da177e4SLinus Torvalds 	 * up to the top level.
18451da177e4SLinus Torvalds 	 */
18461da177e4SLinus Torvalds 	if (!scsi_device_online(scmd->device)) {
184791921e01SHannes Reinecke 		SCSI_LOG_ERROR_RECOVERY(5, scmd_printk(KERN_INFO, scmd,
184891921e01SHannes Reinecke 			"%s: device offline - report as SUCCESS\n", __func__));
18491da177e4SLinus Torvalds 		return SUCCESS;
18501da177e4SLinus Torvalds 	}
18511da177e4SLinus Torvalds 
18521da177e4SLinus Torvalds 	/*
18531da177e4SLinus Torvalds 	 * first check the host byte, to see if there is anything in there
18541da177e4SLinus Torvalds 	 * that would indicate what we need to do.
18551da177e4SLinus Torvalds 	 */
18561da177e4SLinus Torvalds 	switch (host_byte(scmd->result)) {
18571da177e4SLinus Torvalds 	case DID_PASSTHROUGH:
18581da177e4SLinus Torvalds 		/*
18591da177e4SLinus Torvalds 		 * no matter what, pass this through to the upper layer.
18601da177e4SLinus Torvalds 		 * nuke this special code so that it looks like we are saying
18611da177e4SLinus Torvalds 		 * did_ok.
18621da177e4SLinus Torvalds 		 */
18631da177e4SLinus Torvalds 		scmd->result &= 0xff00ffff;
18641da177e4SLinus Torvalds 		return SUCCESS;
18651da177e4SLinus Torvalds 	case DID_OK:
18661da177e4SLinus Torvalds 		/*
18671da177e4SLinus Torvalds 		 * looks good.  drop through, and check the next byte.
18681da177e4SLinus Torvalds 		 */
18691da177e4SLinus Torvalds 		break;
1870e494f6a7SHannes Reinecke 	case DID_ABORT:
1871e494f6a7SHannes Reinecke 		if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) {
18728922a908SUlrich Obergfell 			set_host_byte(scmd, DID_TIME_OUT);
1873e494f6a7SHannes Reinecke 			return SUCCESS;
1874e494f6a7SHannes Reinecke 		}
1875df561f66SGustavo A. R. Silva 		fallthrough;
18761da177e4SLinus Torvalds 	case DID_NO_CONNECT:
18771da177e4SLinus Torvalds 	case DID_BAD_TARGET:
18781da177e4SLinus Torvalds 		/*
18791da177e4SLinus Torvalds 		 * note - this means that we just report the status back
18801da177e4SLinus Torvalds 		 * to the top level driver, not that we actually think
18811da177e4SLinus Torvalds 		 * that it indicates SUCCESS.
18821da177e4SLinus Torvalds 		 */
18831da177e4SLinus Torvalds 		return SUCCESS;
1884ad95028aSPetros Koutoupis 	case DID_SOFT_ERROR:
18851da177e4SLinus Torvalds 		/*
18861da177e4SLinus Torvalds 		 * when the low level driver returns did_soft_error,
18871da177e4SLinus Torvalds 		 * it is responsible for keeping an internal retry counter
18881da177e4SLinus Torvalds 		 * in order to avoid endless loops (db)
18891da177e4SLinus Torvalds 		 */
18901da177e4SLinus Torvalds 		goto maybe_retry;
18911da177e4SLinus Torvalds 	case DID_IMM_RETRY:
18921da177e4SLinus Torvalds 		return NEEDS_RETRY;
18931da177e4SLinus Torvalds 
1894bf341919S 	case DID_REQUEUE:
1895bf341919S 		return ADD_TO_MLQUEUE;
1896a4dfaa6fSMike Christie 	case DID_TRANSPORT_DISRUPTED:
1897a4dfaa6fSMike Christie 		/*
1898a4dfaa6fSMike Christie 		 * LLD/transport was disrupted during processing of the IO.
1899a4dfaa6fSMike Christie 		 * The transport class is now blocked/blocking,
1900a4dfaa6fSMike Christie 		 * and the transport will decide what to do with the IO
1901939c2288SMike Christie 		 * based on its timers and recovery capablilities if
1902939c2288SMike Christie 		 * there are enough retries.
1903a4dfaa6fSMike Christie 		 */
1904939c2288SMike Christie 		goto maybe_retry;
1905a4dfaa6fSMike Christie 	case DID_TRANSPORT_FAILFAST:
1906a4dfaa6fSMike Christie 		/*
1907a4dfaa6fSMike Christie 		 * The transport decided to failfast the IO (most likely
1908a4dfaa6fSMike Christie 		 * the fast io fail tmo fired), so send IO directly upwards.
1909a4dfaa6fSMike Christie 		 */
1910a4dfaa6fSMike Christie 		return SUCCESS;
1911962c8dcdSMuneendra Kumar 	case DID_TRANSPORT_MARGINAL:
1912962c8dcdSMuneendra Kumar 		/*
1913962c8dcdSMuneendra Kumar 		 * caller has decided not to do retries on
1914962c8dcdSMuneendra Kumar 		 * abort success, so send IO directly upwards
1915962c8dcdSMuneendra Kumar 		 */
1916962c8dcdSMuneendra Kumar 		return SUCCESS;
19171da177e4SLinus Torvalds 	case DID_ERROR:
19183d45cefcSHannes Reinecke 		if (get_status_byte(scmd) == SAM_STAT_RESERVATION_CONFLICT)
19191da177e4SLinus Torvalds 			/*
19201da177e4SLinus Torvalds 			 * execute reservation conflict processing code
19211da177e4SLinus Torvalds 			 * lower down
19221da177e4SLinus Torvalds 			 */
19231da177e4SLinus Torvalds 			break;
1924df561f66SGustavo A. R. Silva 		fallthrough;
19251da177e4SLinus Torvalds 	case DID_BUS_BUSY:
19261da177e4SLinus Torvalds 	case DID_PARITY:
19271da177e4SLinus Torvalds 		goto maybe_retry;
19281da177e4SLinus Torvalds 	case DID_TIME_OUT:
19291da177e4SLinus Torvalds 		/*
19301da177e4SLinus Torvalds 		 * when we scan the bus, we get timeout messages for
19311da177e4SLinus Torvalds 		 * these commands if there is no device available.
19321da177e4SLinus Torvalds 		 * other hosts report did_no_connect for the same thing.
19331da177e4SLinus Torvalds 		 */
19341da177e4SLinus Torvalds 		if ((scmd->cmnd[0] == TEST_UNIT_READY ||
19351da177e4SLinus Torvalds 		     scmd->cmnd[0] == INQUIRY)) {
19361da177e4SLinus Torvalds 			return SUCCESS;
19371da177e4SLinus Torvalds 		} else {
19381da177e4SLinus Torvalds 			return FAILED;
19391da177e4SLinus Torvalds 		}
19401da177e4SLinus Torvalds 	case DID_RESET:
19411da177e4SLinus Torvalds 		return SUCCESS;
19421da177e4SLinus Torvalds 	default:
19431da177e4SLinus Torvalds 		return FAILED;
19441da177e4SLinus Torvalds 	}
19451da177e4SLinus Torvalds 
19461da177e4SLinus Torvalds 	/*
19471da177e4SLinus Torvalds 	 * check the status byte to see if this indicates anything special.
19481da177e4SLinus Torvalds 	 */
19493d45cefcSHannes Reinecke 	switch (get_status_byte(scmd)) {
19503d45cefcSHannes Reinecke 	case SAM_STAT_TASK_SET_FULL:
195142a6a918SMike Christie 		scsi_handle_queue_full(scmd->device);
19521da177e4SLinus Torvalds 		/*
19531da177e4SLinus Torvalds 		 * the case of trying to send too many commands to a
19541da177e4SLinus Torvalds 		 * tagged queueing device.
19551da177e4SLinus Torvalds 		 */
1956df561f66SGustavo A. R. Silva 		fallthrough;
19573d45cefcSHannes Reinecke 	case SAM_STAT_BUSY:
19581da177e4SLinus Torvalds 		/*
19591da177e4SLinus Torvalds 		 * device can't talk to us at the moment.  Should only
19601da177e4SLinus Torvalds 		 * occur (SAM-3) when the task queue is empty, so will cause
19611da177e4SLinus Torvalds 		 * the empty queue handling to trigger a stall in the
19621da177e4SLinus Torvalds 		 * device.
19631da177e4SLinus Torvalds 		 */
19641da177e4SLinus Torvalds 		return ADD_TO_MLQUEUE;
19653d45cefcSHannes Reinecke 	case SAM_STAT_GOOD:
1966279afdfeSEwan D. Milne 		if (scmd->cmnd[0] == REPORT_LUNS)
1967279afdfeSEwan D. Milne 			scmd->device->sdev_target->expecting_lun_change = 0;
19684a84067dSVasu Dev 		scsi_handle_queue_ramp_up(scmd->device);
1969df561f66SGustavo A. R. Silva 		fallthrough;
19703d45cefcSHannes Reinecke 	case SAM_STAT_COMMAND_TERMINATED:
19711da177e4SLinus Torvalds 		return SUCCESS;
19723d45cefcSHannes Reinecke 	case SAM_STAT_TASK_ABORTED:
1973a9b589d9SVladislav Bolkhovitin 		goto maybe_retry;
19743d45cefcSHannes Reinecke 	case SAM_STAT_CHECK_CONDITION:
19751da177e4SLinus Torvalds 		rtn = scsi_check_sense(scmd);
19761da177e4SLinus Torvalds 		if (rtn == NEEDS_RETRY)
19771da177e4SLinus Torvalds 			goto maybe_retry;
19781da177e4SLinus Torvalds 		/* if rtn == FAILED, we have no sense information;
19791da177e4SLinus Torvalds 		 * returning FAILED will wake the error handler thread
19801da177e4SLinus Torvalds 		 * to collect the sense and redo the decide
19811da177e4SLinus Torvalds 		 * disposition */
19821da177e4SLinus Torvalds 		return rtn;
19833d45cefcSHannes Reinecke 	case SAM_STAT_CONDITION_MET:
19843d45cefcSHannes Reinecke 	case SAM_STAT_INTERMEDIATE:
19853d45cefcSHannes Reinecke 	case SAM_STAT_INTERMEDIATE_CONDITION_MET:
19863d45cefcSHannes Reinecke 	case SAM_STAT_ACA_ACTIVE:
19871da177e4SLinus Torvalds 		/*
19881da177e4SLinus Torvalds 		 * who knows?  FIXME(eric)
19891da177e4SLinus Torvalds 		 */
19901da177e4SLinus Torvalds 		return SUCCESS;
19911da177e4SLinus Torvalds 
19923d45cefcSHannes Reinecke 	case SAM_STAT_RESERVATION_CONFLICT:
19939ccfc756SJames Bottomley 		sdev_printk(KERN_INFO, scmd->device,
19949ccfc756SJames Bottomley 			    "reservation conflict\n");
19957dfaae6aSMike Christie 		set_scsi_ml_byte(scmd, SCSIML_STAT_RESV_CONFLICT);
19961da177e4SLinus Torvalds 		return SUCCESS; /* causes immediate i/o error */
19971da177e4SLinus Torvalds 	}
19981da177e4SLinus Torvalds 	return FAILED;
19991da177e4SLinus Torvalds 
20001da177e4SLinus Torvalds maybe_retry:
20011da177e4SLinus Torvalds 
20021da177e4SLinus Torvalds 	/* we requeue for retry because the error was retryable, and
20031da177e4SLinus Torvalds 	 * the request was not marked fast fail.  Note that above,
20041da177e4SLinus Torvalds 	 * even if the request is marked fast fail, we still requeue
20051da177e4SLinus Torvalds 	 * for queue congestion conditions (QUEUE_FULL or BUSY) */
20062a242d59SMike Christie 	if (scsi_cmd_retry_allowed(scmd) && !scsi_noretry_cmd(scmd)) {
20071da177e4SLinus Torvalds 		return NEEDS_RETRY;
20081da177e4SLinus Torvalds 	} else {
20091da177e4SLinus Torvalds 		/*
20101da177e4SLinus Torvalds 		 * no more retries - report this one back to upper level.
20111da177e4SLinus Torvalds 		 */
20121da177e4SLinus Torvalds 		return SUCCESS;
20131da177e4SLinus Torvalds 	}
20141da177e4SLinus Torvalds }
20151da177e4SLinus Torvalds 
2016de671d61SJens Axboe static enum rq_end_io_ret eh_lock_door_done(struct request *req,
2017de671d61SJens Axboe 					    blk_status_t status)
2018f078727bSFUJITA Tomonori {
20190bf6d96cSChristoph Hellwig 	blk_mq_free_request(req);
2020de671d61SJens Axboe 	return RQ_END_IO_NONE;
2021f078727bSFUJITA Tomonori }
2022f078727bSFUJITA Tomonori 
20231da177e4SLinus Torvalds /**
20241da177e4SLinus Torvalds  * scsi_eh_lock_door - Prevent medium removal for the specified device
20251da177e4SLinus Torvalds  * @sdev:	SCSI device to prevent medium removal
20261da177e4SLinus Torvalds  *
20271da177e4SLinus Torvalds  * Locking:
202891bc31fbSJames Bottomley  * 	We must be called from process context.
20291da177e4SLinus Torvalds  *
20301da177e4SLinus Torvalds  * Notes:
20311da177e4SLinus Torvalds  * 	We queue up an asynchronous "ALLOW MEDIUM REMOVAL" request on the
20321da177e4SLinus Torvalds  * 	head of the devices request queue, and continue.
2033dc8875e1SRandy Dunlap  */
20341da177e4SLinus Torvalds static void scsi_eh_lock_door(struct scsi_device *sdev)
20351da177e4SLinus Torvalds {
2036ce70fd9aSChristoph Hellwig 	struct scsi_cmnd *scmd;
2037f078727bSFUJITA Tomonori 	struct request *req;
20381da177e4SLinus Torvalds 
203968ec3b81SChristoph Hellwig 	req = scsi_alloc_request(sdev->request_queue, REQ_OP_DRV_IN, 0);
2040a492f075SJoe Lawrence 	if (IS_ERR(req))
2041eb571eeaSJoe Lawrence 		return;
2042ce70fd9aSChristoph Hellwig 	scmd = blk_mq_rq_to_pdu(req);
20431da177e4SLinus Torvalds 
2044ce70fd9aSChristoph Hellwig 	scmd->cmnd[0] = ALLOW_MEDIUM_REMOVAL;
2045ce70fd9aSChristoph Hellwig 	scmd->cmnd[1] = 0;
2046ce70fd9aSChristoph Hellwig 	scmd->cmnd[2] = 0;
2047ce70fd9aSChristoph Hellwig 	scmd->cmnd[3] = 0;
2048ce70fd9aSChristoph Hellwig 	scmd->cmnd[4] = SCSI_REMOVAL_PREVENT;
2049ce70fd9aSChristoph Hellwig 	scmd->cmnd[5] = 0;
2050ce70fd9aSChristoph Hellwig 	scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
2051e2e53086SChristoph Hellwig 	scmd->allowed = 5;
2052f078727bSFUJITA Tomonori 
2053e8064021SChristoph Hellwig 	req->rq_flags |= RQF_QUIET;
2054f078727bSFUJITA Tomonori 	req->timeout = 10 * HZ;
2055e2e53086SChristoph Hellwig 	req->end_io = eh_lock_door_done;
2056f078727bSFUJITA Tomonori 
2057e2e53086SChristoph Hellwig 	blk_execute_rq_nowait(req, true);
20581da177e4SLinus Torvalds }
20591da177e4SLinus Torvalds 
20601da177e4SLinus Torvalds /**
20611da177e4SLinus Torvalds  * scsi_restart_operations - restart io operations to the specified host.
20621da177e4SLinus Torvalds  * @shost:	Host we are restarting.
20631da177e4SLinus Torvalds  *
20641da177e4SLinus Torvalds  * Notes:
20651da177e4SLinus Torvalds  *    When we entered the error handler, we blocked all further i/o to
20661da177e4SLinus Torvalds  *    this device.  we need to 'reverse' this process.
2067dc8875e1SRandy Dunlap  */
20681da177e4SLinus Torvalds static void scsi_restart_operations(struct Scsi_Host *shost)
20691da177e4SLinus Torvalds {
20701da177e4SLinus Torvalds 	struct scsi_device *sdev;
2071939647eeSJames Bottomley 	unsigned long flags;
20721da177e4SLinus Torvalds 
20731da177e4SLinus Torvalds 	/*
20741da177e4SLinus Torvalds 	 * If the door was locked, we need to insert a door lock request
20751da177e4SLinus Torvalds 	 * onto the head of the SCSI request queue for the device.  There
20761da177e4SLinus Torvalds 	 * is no point trying to lock the door of an off-line device.
20771da177e4SLinus Torvalds 	 */
20781da177e4SLinus Torvalds 	shost_for_each_device(sdev, shost) {
207948379270SChristoph Hellwig 		if (scsi_device_online(sdev) && sdev->was_reset && sdev->locked) {
20801da177e4SLinus Torvalds 			scsi_eh_lock_door(sdev);
208148379270SChristoph Hellwig 			sdev->was_reset = 0;
208248379270SChristoph Hellwig 		}
20831da177e4SLinus Torvalds 	}
20841da177e4SLinus Torvalds 
20851da177e4SLinus Torvalds 	/*
20861da177e4SLinus Torvalds 	 * next free up anything directly waiting upon the host.  this
20871da177e4SLinus Torvalds 	 * will be requests for character device operations, and also for
20881da177e4SLinus Torvalds 	 * ioctls to queued block devices.
20891da177e4SLinus Torvalds 	 */
2090b4562022SHannes Reinecke 	SCSI_LOG_ERROR_RECOVERY(3,
209191921e01SHannes Reinecke 		shost_printk(KERN_INFO, shost, "waking up host to restart\n"));
20921da177e4SLinus Torvalds 
2093939647eeSJames Bottomley 	spin_lock_irqsave(shost->host_lock, flags);
2094939647eeSJames Bottomley 	if (scsi_host_set_state(shost, SHOST_RUNNING))
2095939647eeSJames Bottomley 		if (scsi_host_set_state(shost, SHOST_CANCEL))
2096939647eeSJames Bottomley 			BUG_ON(scsi_host_set_state(shost, SHOST_DEL));
2097939647eeSJames Bottomley 	spin_unlock_irqrestore(shost->host_lock, flags);
20981da177e4SLinus Torvalds 
20991da177e4SLinus Torvalds 	wake_up(&shost->host_wait);
21001da177e4SLinus Torvalds 
21011da177e4SLinus Torvalds 	/*
21021da177e4SLinus Torvalds 	 * finally we need to re-initiate requests that may be pending.  we will
21031da177e4SLinus Torvalds 	 * have had everything blocked while error handling is taking place, and
21041da177e4SLinus Torvalds 	 * now that error recovery is done, we will need to ensure that these
21051da177e4SLinus Torvalds 	 * requests are started.
21061da177e4SLinus Torvalds 	 */
21071da177e4SLinus Torvalds 	scsi_run_host_queues(shost);
210857fc2e33SDan Williams 
210957fc2e33SDan Williams 	/*
211057fc2e33SDan Williams 	 * if eh is active and host_eh_scheduled is pending we need to re-run
211157fc2e33SDan Williams 	 * recovery.  we do this check after scsi_run_host_queues() to allow
211257fc2e33SDan Williams 	 * everything pent up since the last eh run a chance to make forward
211357fc2e33SDan Williams 	 * progress before we sync again.  Either we'll immediately re-run
211457fc2e33SDan Williams 	 * recovery or scsi_device_unbusy() will wake us again when these
211557fc2e33SDan Williams 	 * pending commands complete.
211657fc2e33SDan Williams 	 */
211757fc2e33SDan Williams 	spin_lock_irqsave(shost->host_lock, flags);
211857fc2e33SDan Williams 	if (shost->host_eh_scheduled)
211957fc2e33SDan Williams 		if (scsi_host_set_state(shost, SHOST_RECOVERY))
212057fc2e33SDan Williams 			WARN_ON(scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY));
212157fc2e33SDan Williams 	spin_unlock_irqrestore(shost->host_lock, flags);
21221da177e4SLinus Torvalds }
21231da177e4SLinus Torvalds 
21241da177e4SLinus Torvalds /**
21251da177e4SLinus Torvalds  * scsi_eh_ready_devs - check device ready state and recover if not.
21261da177e4SLinus Torvalds  * @shost:	host to be recovered.
2127eb44820cSRob Landley  * @work_q:	&list_head for pending commands.
2128eb44820cSRob Landley  * @done_q:	&list_head for processed commands.
2129dc8875e1SRandy Dunlap  */
2130dca84e46SDarrick J. Wong void scsi_eh_ready_devs(struct Scsi_Host *shost,
21311da177e4SLinus Torvalds 			struct list_head *work_q,
21321da177e4SLinus Torvalds 			struct list_head *done_q)
21331da177e4SLinus Torvalds {
21341da177e4SLinus Torvalds 	if (!scsi_eh_stu(shost, work_q, done_q))
21351da177e4SLinus Torvalds 		if (!scsi_eh_bus_device_reset(shost, work_q, done_q))
213630bd7df8SMike Christie 			if (!scsi_eh_target_reset(shost, work_q, done_q))
21371da177e4SLinus Torvalds 				if (!scsi_eh_bus_reset(shost, work_q, done_q))
213891921e01SHannes Reinecke 					if (!scsi_eh_host_reset(shost, work_q, done_q))
213930bd7df8SMike Christie 						scsi_eh_offline_sdevs(work_q,
214030bd7df8SMike Christie 								      done_q);
21411da177e4SLinus Torvalds }
2142dca84e46SDarrick J. Wong EXPORT_SYMBOL_GPL(scsi_eh_ready_devs);
21431da177e4SLinus Torvalds 
21441da177e4SLinus Torvalds /**
21451da177e4SLinus Torvalds  * scsi_eh_flush_done_q - finish processed commands or retry them.
21461da177e4SLinus Torvalds  * @done_q:	list_head of processed commands.
2147dc8875e1SRandy Dunlap  */
2148041c5fc3STejun Heo void scsi_eh_flush_done_q(struct list_head *done_q)
21491da177e4SLinus Torvalds {
2150937abeaaSChristoph Hellwig 	struct scsi_cmnd *scmd, *next;
21511da177e4SLinus Torvalds 
2152937abeaaSChristoph Hellwig 	list_for_each_entry_safe(scmd, next, done_q, eh_entry) {
2153937abeaaSChristoph Hellwig 		list_del_init(&scmd->eh_entry);
21541da177e4SLinus Torvalds 		if (scsi_device_online(scmd->device) &&
215560bee27bSMuneendra Kumar 		    !scsi_noretry_cmd(scmd) && scsi_cmd_retry_allowed(scmd) &&
215660bee27bSMuneendra Kumar 			scsi_eh_should_retry_cmd(scmd)) {
215791921e01SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
215891921e01SHannes Reinecke 				scmd_printk(KERN_INFO, scmd,
2159470613b4SHannes Reinecke 					     "%s: flush retry cmd\n",
2160470613b4SHannes Reinecke 					     current->comm));
21611da177e4SLinus Torvalds 				scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY);
21621da177e4SLinus Torvalds 		} else {
2163793698ceSPatrick Mansfield  			/*
2164793698ceSPatrick Mansfield  			 * If just we got sense for the device (called
2165793698ceSPatrick Mansfield  			 * scsi_eh_get_sense), scmd->result is already
21664bd51e54SHannes Reinecke 			 * set, do not set DID_TIME_OUT.
2167793698ceSPatrick Mansfield  			 */
21681da177e4SLinus Torvalds 			if (!scmd->result)
21694bd51e54SHannes Reinecke 				scmd->result |= (DID_TIME_OUT << 16);
217091921e01SHannes Reinecke 			SCSI_LOG_ERROR_RECOVERY(3,
217191921e01SHannes Reinecke 				scmd_printk(KERN_INFO, scmd,
2172470613b4SHannes Reinecke 					     "%s: flush finish cmd\n",
2173470613b4SHannes Reinecke 					     current->comm));
21741da177e4SLinus Torvalds 			scsi_finish_command(scmd);
21751da177e4SLinus Torvalds 		}
21761da177e4SLinus Torvalds 	}
21771da177e4SLinus Torvalds }
2178041c5fc3STejun Heo EXPORT_SYMBOL(scsi_eh_flush_done_q);
21791da177e4SLinus Torvalds 
21801da177e4SLinus Torvalds /**
21811da177e4SLinus Torvalds  * scsi_unjam_host - Attempt to fix a host which has a cmd that failed.
21821da177e4SLinus Torvalds  * @shost:	Host to unjam.
21831da177e4SLinus Torvalds  *
21841da177e4SLinus Torvalds  * Notes:
21851da177e4SLinus Torvalds  *    When we come in here, we *know* that all commands on the bus have
21861da177e4SLinus Torvalds  *    either completed, failed or timed out.  we also know that no further
21871da177e4SLinus Torvalds  *    commands are being sent to the host, so things are relatively quiet
21881da177e4SLinus Torvalds  *    and we have freedom to fiddle with things as we wish.
21891da177e4SLinus Torvalds  *
21901da177e4SLinus Torvalds  *    This is only the *default* implementation.  it is possible for
21911da177e4SLinus Torvalds  *    individual drivers to supply their own version of this function, and
21921da177e4SLinus Torvalds  *    if the maintainer wishes to do this, it is strongly suggested that
21931da177e4SLinus Torvalds  *    this function be taken as a template and modified.  this function
21941da177e4SLinus Torvalds  *    was designed to correctly handle problems for about 95% of the
21951da177e4SLinus Torvalds  *    different cases out there, and it should always provide at least a
21961da177e4SLinus Torvalds  *    reasonable amount of error recovery.
21971da177e4SLinus Torvalds  *
21981da177e4SLinus Torvalds  *    Any command marked 'failed' or 'timeout' must eventually have
21991da177e4SLinus Torvalds  *    scsi_finish_cmd() called for it.  we do all of the retry stuff
22001da177e4SLinus Torvalds  *    here, so when we restart the host after we return it should have an
22011da177e4SLinus Torvalds  *    empty queue.
2202dc8875e1SRandy Dunlap  */
22031da177e4SLinus Torvalds static void scsi_unjam_host(struct Scsi_Host *shost)
22041da177e4SLinus Torvalds {
22051da177e4SLinus Torvalds 	unsigned long flags;
22061da177e4SLinus Torvalds 	LIST_HEAD(eh_work_q);
22071da177e4SLinus Torvalds 	LIST_HEAD(eh_done_q);
22081da177e4SLinus Torvalds 
22091da177e4SLinus Torvalds 	spin_lock_irqsave(shost->host_lock, flags);
22101da177e4SLinus Torvalds 	list_splice_init(&shost->eh_cmd_q, &eh_work_q);
22111da177e4SLinus Torvalds 	spin_unlock_irqrestore(shost->host_lock, flags);
22121da177e4SLinus Torvalds 
22131da177e4SLinus Torvalds 	SCSI_LOG_ERROR_RECOVERY(1, scsi_eh_prt_fail_stats(shost, &eh_work_q));
22141da177e4SLinus Torvalds 
22151da177e4SLinus Torvalds 	if (!scsi_eh_get_sense(&eh_work_q, &eh_done_q))
22161da177e4SLinus Torvalds 		scsi_eh_ready_devs(shost, &eh_work_q, &eh_done_q);
22171da177e4SLinus Torvalds 
2218b4562022SHannes Reinecke 	spin_lock_irqsave(shost->host_lock, flags);
2219bb3b621aSRen Mingxin 	if (shost->eh_deadline != -1)
2220b4562022SHannes Reinecke 		shost->last_reset = 0;
2221b4562022SHannes Reinecke 	spin_unlock_irqrestore(shost->host_lock, flags);
22221da177e4SLinus Torvalds 	scsi_eh_flush_done_q(&eh_done_q);
22231da177e4SLinus Torvalds }
22241da177e4SLinus Torvalds 
22251da177e4SLinus Torvalds /**
2226ad42eb1bSChristoph Hellwig  * scsi_error_handler - SCSI error handler thread
22271da177e4SLinus Torvalds  * @data:	Host for which we are running.
22281da177e4SLinus Torvalds  *
22291da177e4SLinus Torvalds  * Notes:
2230ad42eb1bSChristoph Hellwig  *    This is the main error handling loop.  This is run as a kernel thread
2231ad42eb1bSChristoph Hellwig  *    for every SCSI host and handles all error handling activity.
2232dc8875e1SRandy Dunlap  */
22331da177e4SLinus Torvalds int scsi_error_handler(void *data)
22341da177e4SLinus Torvalds {
2235ad42eb1bSChristoph Hellwig 	struct Scsi_Host *shost = data;
22361da177e4SLinus Torvalds 
22371da177e4SLinus Torvalds 	/*
2238ad42eb1bSChristoph Hellwig 	 * We use TASK_INTERRUPTIBLE so that the thread is not
2239ad42eb1bSChristoph Hellwig 	 * counted against the load average as a running process.
2240ad42eb1bSChristoph Hellwig 	 * We never actually get interrupted because kthread_run
2241c03264a7SFrederik Schwarzer 	 * disables signal delivery for the created thread.
22421da177e4SLinus Torvalds 	 */
2243537b604cSMichal Hocko 	while (true) {
2244537b604cSMichal Hocko 		/*
2245537b604cSMichal Hocko 		 * The sequence in kthread_stop() sets the stop flag first
2246537b604cSMichal Hocko 		 * then wakes the process.  To avoid missed wakeups, the task
2247537b604cSMichal Hocko 		 * should always be in a non running state before the stop
2248537b604cSMichal Hocko 		 * flag is checked
2249537b604cSMichal Hocko 		 */
2250b9d5c6b7SDan Williams 		set_current_state(TASK_INTERRUPTIBLE);
2251537b604cSMichal Hocko 		if (kthread_should_stop())
2252537b604cSMichal Hocko 			break;
2253537b604cSMichal Hocko 
2254ee7863bcSTejun Heo 		if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) ||
2255c84b023aSMing Lei 		    shost->host_failed != scsi_host_busy(shost)) {
2256ad42eb1bSChristoph Hellwig 			SCSI_LOG_ERROR_RECOVERY(1,
225791921e01SHannes Reinecke 				shost_printk(KERN_INFO, shost,
225891921e01SHannes Reinecke 					     "scsi_eh_%d: sleeping\n",
22593ed7a470SJames Bottomley 					     shost->host_no));
22603ed7a470SJames Bottomley 			schedule();
22613ed7a470SJames Bottomley 			continue;
22623ed7a470SJames Bottomley 		}
22631da177e4SLinus Torvalds 
22643ed7a470SJames Bottomley 		__set_current_state(TASK_RUNNING);
2265ad42eb1bSChristoph Hellwig 		SCSI_LOG_ERROR_RECOVERY(1,
226691921e01SHannes Reinecke 			shost_printk(KERN_INFO, shost,
226791921e01SHannes Reinecke 				     "scsi_eh_%d: waking up %d/%d/%d\n",
2268b4562022SHannes Reinecke 				     shost->host_no, shost->host_eh_scheduled,
226974665016SChristoph Hellwig 				     shost->host_failed,
2270c84b023aSMing Lei 				     scsi_host_busy(shost)));
22711da177e4SLinus Torvalds 
22721da177e4SLinus Torvalds 		/*
22731da177e4SLinus Torvalds 		 * We have a host that is failing for some reason.  Figure out
22741da177e4SLinus Torvalds 		 * what we need to do to get it up and online again (if we can).
22751da177e4SLinus Torvalds 		 * If we fail, we end up taking the thing offline.
22761da177e4SLinus Torvalds 		 */
2277ae0751ffSLin Ming 		if (!shost->eh_noresume && scsi_autopm_get_host(shost) != 0) {
2278bc4f2401SAlan Stern 			SCSI_LOG_ERROR_RECOVERY(1,
2279a222b1e2SHannes Reinecke 				shost_printk(KERN_ERR, shost,
2280a222b1e2SHannes Reinecke 					     "scsi_eh_%d: unable to autoresume\n",
2281bc4f2401SAlan Stern 					     shost->host_no));
2282bc4f2401SAlan Stern 			continue;
2283bc4f2401SAlan Stern 		}
2284bc4f2401SAlan Stern 
22859227c33dSChristoph Hellwig 		if (shost->transportt->eh_strategy_handler)
22869227c33dSChristoph Hellwig 			shost->transportt->eh_strategy_handler(shost);
22871da177e4SLinus Torvalds 		else
22881da177e4SLinus Torvalds 			scsi_unjam_host(shost);
22891da177e4SLinus Torvalds 
229072d8c36eSWei Fang 		/* All scmds have been handled */
229172d8c36eSWei Fang 		shost->host_failed = 0;
229272d8c36eSWei Fang 
22931da177e4SLinus Torvalds 		/*
22941da177e4SLinus Torvalds 		 * Note - if the above fails completely, the action is to take
22951da177e4SLinus Torvalds 		 * individual devices offline and flush the queue of any
22961da177e4SLinus Torvalds 		 * outstanding requests that may have been pending.  When we
22971da177e4SLinus Torvalds 		 * restart, we restart any I/O to any other devices on the bus
22981da177e4SLinus Torvalds 		 * which are still online.
22991da177e4SLinus Torvalds 		 */
23001da177e4SLinus Torvalds 		scsi_restart_operations(shost);
2301ae0751ffSLin Ming 		if (!shost->eh_noresume)
2302bc4f2401SAlan Stern 			scsi_autopm_put_host(shost);
23031da177e4SLinus Torvalds 	}
2304461a0ffbSSteven Rostedt 	__set_current_state(TASK_RUNNING);
2305461a0ffbSSteven Rostedt 
2306ad42eb1bSChristoph Hellwig 	SCSI_LOG_ERROR_RECOVERY(1,
230791921e01SHannes Reinecke 		shost_printk(KERN_INFO, shost,
230891921e01SHannes Reinecke 			     "Error handler scsi_eh_%d exiting\n",
230991921e01SHannes Reinecke 			     shost->host_no));
23103ed7a470SJames Bottomley 	shost->ehandler = NULL;
23111da177e4SLinus Torvalds 	return 0;
23121da177e4SLinus Torvalds }
23131da177e4SLinus Torvalds 
23141da177e4SLinus Torvalds /*
23151da177e4SLinus Torvalds  * Function:    scsi_report_bus_reset()
23161da177e4SLinus Torvalds  *
23171da177e4SLinus Torvalds  * Purpose:     Utility function used by low-level drivers to report that
23181da177e4SLinus Torvalds  *		they have observed a bus reset on the bus being handled.
23191da177e4SLinus Torvalds  *
23201da177e4SLinus Torvalds  * Arguments:   shost       - Host in question
23211da177e4SLinus Torvalds  *		channel     - channel on which reset was observed.
23221da177e4SLinus Torvalds  *
23231da177e4SLinus Torvalds  * Returns:     Nothing
23241da177e4SLinus Torvalds  *
23251da177e4SLinus Torvalds  * Lock status: Host lock must be held.
23261da177e4SLinus Torvalds  *
23271da177e4SLinus Torvalds  * Notes:       This only needs to be called if the reset is one which
23281da177e4SLinus Torvalds  *		originates from an unknown location.  Resets originated
23291da177e4SLinus Torvalds  *		by the mid-level itself don't need to call this, but there
23301da177e4SLinus Torvalds  *		should be no harm.
23311da177e4SLinus Torvalds  *
23321da177e4SLinus Torvalds  *		The main purpose of this is to make sure that a CHECK_CONDITION
23331da177e4SLinus Torvalds  *		is properly treated.
23341da177e4SLinus Torvalds  */
23351da177e4SLinus Torvalds void scsi_report_bus_reset(struct Scsi_Host *shost, int channel)
23361da177e4SLinus Torvalds {
23371da177e4SLinus Torvalds 	struct scsi_device *sdev;
23381da177e4SLinus Torvalds 
23391da177e4SLinus Torvalds 	__shost_for_each_device(sdev, shost) {
234030bd7df8SMike Christie 		if (channel == sdev_channel(sdev))
234130bd7df8SMike Christie 			__scsi_report_device_reset(sdev, NULL);
23421da177e4SLinus Torvalds 	}
23431da177e4SLinus Torvalds }
23441da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_report_bus_reset);
23451da177e4SLinus Torvalds 
23461da177e4SLinus Torvalds /*
23471da177e4SLinus Torvalds  * Function:    scsi_report_device_reset()
23481da177e4SLinus Torvalds  *
23491da177e4SLinus Torvalds  * Purpose:     Utility function used by low-level drivers to report that
23501da177e4SLinus Torvalds  *		they have observed a device reset on the device being handled.
23511da177e4SLinus Torvalds  *
23521da177e4SLinus Torvalds  * Arguments:   shost       - Host in question
23531da177e4SLinus Torvalds  *		channel     - channel on which reset was observed
23541da177e4SLinus Torvalds  *		target	    - target on which reset was observed
23551da177e4SLinus Torvalds  *
23561da177e4SLinus Torvalds  * Returns:     Nothing
23571da177e4SLinus Torvalds  *
23581da177e4SLinus Torvalds  * Lock status: Host lock must be held
23591da177e4SLinus Torvalds  *
23601da177e4SLinus Torvalds  * Notes:       This only needs to be called if the reset is one which
23611da177e4SLinus Torvalds  *		originates from an unknown location.  Resets originated
23621da177e4SLinus Torvalds  *		by the mid-level itself don't need to call this, but there
23631da177e4SLinus Torvalds  *		should be no harm.
23641da177e4SLinus Torvalds  *
23651da177e4SLinus Torvalds  *		The main purpose of this is to make sure that a CHECK_CONDITION
23661da177e4SLinus Torvalds  *		is properly treated.
23671da177e4SLinus Torvalds  */
23681da177e4SLinus Torvalds void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target)
23691da177e4SLinus Torvalds {
23701da177e4SLinus Torvalds 	struct scsi_device *sdev;
23711da177e4SLinus Torvalds 
23721da177e4SLinus Torvalds 	__shost_for_each_device(sdev, shost) {
2373422c0d61SJeff Garzik 		if (channel == sdev_channel(sdev) &&
237430bd7df8SMike Christie 		    target == sdev_id(sdev))
237530bd7df8SMike Christie 			__scsi_report_device_reset(sdev, NULL);
23761da177e4SLinus Torvalds 	}
23771da177e4SLinus Torvalds }
23781da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_report_device_reset);
23791da177e4SLinus Torvalds 
2380176aa9d6SChristoph Hellwig /**
2381176aa9d6SChristoph Hellwig  * scsi_ioctl_reset: explicitly reset a host/bus/target/device
2382176aa9d6SChristoph Hellwig  * @dev:	scsi_device to operate on
2383176aa9d6SChristoph Hellwig  * @arg:	reset type (see sg.h)
23841da177e4SLinus Torvalds  */
23851da177e4SLinus Torvalds int
2386176aa9d6SChristoph Hellwig scsi_ioctl_reset(struct scsi_device *dev, int __user *arg)
23871da177e4SLinus Torvalds {
2388bc4f2401SAlan Stern 	struct scsi_cmnd *scmd;
2389d7a1bb0aSJames Smart 	struct Scsi_Host *shost = dev->host;
2390e9c787e6SChristoph Hellwig 	struct request *rq;
2391d7a1bb0aSJames Smart 	unsigned long flags;
2392b8e162f9SBart Van Assche 	int error = 0, val;
2393b8e162f9SBart Van Assche 	enum scsi_disposition rtn;
2394176aa9d6SChristoph Hellwig 
2395176aa9d6SChristoph Hellwig 	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
2396176aa9d6SChristoph Hellwig 		return -EACCES;
2397176aa9d6SChristoph Hellwig 
2398176aa9d6SChristoph Hellwig 	error = get_user(val, arg);
2399176aa9d6SChristoph Hellwig 	if (error)
2400176aa9d6SChristoph Hellwig 		return error;
24011da177e4SLinus Torvalds 
2402bc4f2401SAlan Stern 	if (scsi_autopm_get_host(shost) < 0)
2403176aa9d6SChristoph Hellwig 		return -EIO;
2404bc4f2401SAlan Stern 
2405176aa9d6SChristoph Hellwig 	error = -EIO;
2406e9c787e6SChristoph Hellwig 	rq = kzalloc(sizeof(struct request) + sizeof(struct scsi_cmnd) +
2407e9c787e6SChristoph Hellwig 			shost->hostt->cmd_size, GFP_KERNEL);
2408e9c787e6SChristoph Hellwig 	if (!rq)
240995eeb5f5SChristoph Hellwig 		goto out_put_autopm_host;
2410e9c787e6SChristoph Hellwig 	blk_rq_init(NULL, rq);
241195eeb5f5SChristoph Hellwig 
2412e9c787e6SChristoph Hellwig 	scmd = (struct scsi_cmnd *)(rq + 1);
2413e9c787e6SChristoph Hellwig 	scsi_init_command(dev, scmd);
24141da177e4SLinus Torvalds 
2415bf23e619SBart Van Assche 	scmd->submitter = SUBMITTED_BY_SCSI_RESET_IOCTL;
241630b0c37bSBoaz Harrosh 	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
24171da177e4SLinus Torvalds 
24181da177e4SLinus Torvalds 	scmd->cmd_len			= 0;
24191da177e4SLinus Torvalds 
24201da177e4SLinus Torvalds 	scmd->sc_data_direction		= DMA_BIDIRECTIONAL;
24211da177e4SLinus Torvalds 
2422d7a1bb0aSJames Smart 	spin_lock_irqsave(shost->host_lock, flags);
2423d7a1bb0aSJames Smart 	shost->tmf_in_progress = 1;
2424d7a1bb0aSJames Smart 	spin_unlock_irqrestore(shost->host_lock, flags);
2425d7a1bb0aSJames Smart 
2426176aa9d6SChristoph Hellwig 	switch (val & ~SG_SCSI_RESET_NO_ESCALATE) {
2427176aa9d6SChristoph Hellwig 	case SG_SCSI_RESET_NOTHING:
2428176aa9d6SChristoph Hellwig 		rtn = SUCCESS;
2429176aa9d6SChristoph Hellwig 		break;
2430176aa9d6SChristoph Hellwig 	case SG_SCSI_RESET_DEVICE:
24311da177e4SLinus Torvalds 		rtn = scsi_try_bus_device_reset(scmd);
2432176aa9d6SChristoph Hellwig 		if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE))
24331da177e4SLinus Torvalds 			break;
2434df561f66SGustavo A. R. Silva 		fallthrough;
2435176aa9d6SChristoph Hellwig 	case SG_SCSI_RESET_TARGET:
243630bd7df8SMike Christie 		rtn = scsi_try_target_reset(scmd);
2437176aa9d6SChristoph Hellwig 		if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE))
243830bd7df8SMike Christie 			break;
2439df561f66SGustavo A. R. Silva 		fallthrough;
2440176aa9d6SChristoph Hellwig 	case SG_SCSI_RESET_BUS:
24411da177e4SLinus Torvalds 		rtn = scsi_try_bus_reset(scmd);
2442176aa9d6SChristoph Hellwig 		if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE))
24431da177e4SLinus Torvalds 			break;
2444df561f66SGustavo A. R. Silva 		fallthrough;
2445176aa9d6SChristoph Hellwig 	case SG_SCSI_RESET_HOST:
24461da177e4SLinus Torvalds 		rtn = scsi_try_host_reset(scmd);
2447176aa9d6SChristoph Hellwig 		if (rtn == SUCCESS)
244826cf591eSDouglas Gilbert 			break;
2449df561f66SGustavo A. R. Silva 		fallthrough;
24503bf2ff67SBart Van Assche 	default:
24511da177e4SLinus Torvalds 		rtn = FAILED;
2452176aa9d6SChristoph Hellwig 		break;
24531da177e4SLinus Torvalds 	}
24541da177e4SLinus Torvalds 
2455176aa9d6SChristoph Hellwig 	error = (rtn == SUCCESS) ? 0 : -EIO;
2456176aa9d6SChristoph Hellwig 
2457d7a1bb0aSJames Smart 	spin_lock_irqsave(shost->host_lock, flags);
2458d7a1bb0aSJames Smart 	shost->tmf_in_progress = 0;
2459d7a1bb0aSJames Smart 	spin_unlock_irqrestore(shost->host_lock, flags);
2460d7a1bb0aSJames Smart 
2461d7a1bb0aSJames Smart 	/*
2462d7a1bb0aSJames Smart 	 * be sure to wake up anyone who was sleeping or had their queue
2463d7a1bb0aSJames Smart 	 * suspended while we performed the TMF.
2464d7a1bb0aSJames Smart 	 */
2465d7a1bb0aSJames Smart 	SCSI_LOG_ERROR_RECOVERY(3,
246691921e01SHannes Reinecke 		shost_printk(KERN_INFO, shost,
246791921e01SHannes Reinecke 			     "waking up host to restart after TMF\n"));
2468d7a1bb0aSJames Smart 
2469d7a1bb0aSJames Smart 	wake_up(&shost->host_wait);
2470d7a1bb0aSJames Smart 	scsi_run_host_queues(shost);
2471d7a1bb0aSJames Smart 
2472e9c787e6SChristoph Hellwig 	kfree(rq);
24730f121dd8SChristoph Hellwig 
247404796336SChristoph Hellwig out_put_autopm_host:
2475bc4f2401SAlan Stern 	scsi_autopm_put_host(shost);
2476176aa9d6SChristoph Hellwig 	return error;
24771da177e4SLinus Torvalds }
24781da177e4SLinus Torvalds 
24794753cbc0SHannes Reinecke bool scsi_command_normalize_sense(const struct scsi_cmnd *cmd,
24801da177e4SLinus Torvalds 				  struct scsi_sense_hdr *sshdr)
24811da177e4SLinus Torvalds {
24821da177e4SLinus Torvalds 	return scsi_normalize_sense(cmd->sense_buffer,
2483b80ca4f7SFUJITA Tomonori 			SCSI_SENSE_BUFFERSIZE, sshdr);
24841da177e4SLinus Torvalds }
24851da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_command_normalize_sense);
24861da177e4SLinus Torvalds 
24871da177e4SLinus Torvalds /**
2488eb44820cSRob Landley  * scsi_get_sense_info_fld - get information field from sense data (either fixed or descriptor format)
24891da177e4SLinus Torvalds  * @sense_buffer:	byte array of sense data
24901da177e4SLinus Torvalds  * @sb_len:		number of valid bytes in sense_buffer
24911da177e4SLinus Torvalds  * @info_out:		pointer to 64 integer where 8 or 4 byte information
24921da177e4SLinus Torvalds  *			field will be placed if found.
24931da177e4SLinus Torvalds  *
24941da177e4SLinus Torvalds  * Return value:
24952908769cSDamien Le Moal  *	true if information field found, false if not found.
2496dc8875e1SRandy Dunlap  */
24972908769cSDamien Le Moal bool scsi_get_sense_info_fld(const u8 *sense_buffer, int sb_len,
24981da177e4SLinus Torvalds 			     u64 *info_out)
24991da177e4SLinus Torvalds {
25001da177e4SLinus Torvalds 	const u8 * ucp;
25011da177e4SLinus Torvalds 
25021da177e4SLinus Torvalds 	if (sb_len < 7)
25032908769cSDamien Le Moal 		return false;
25041da177e4SLinus Torvalds 	switch (sense_buffer[0] & 0x7f) {
25051da177e4SLinus Torvalds 	case 0x70:
25061da177e4SLinus Torvalds 	case 0x71:
25071da177e4SLinus Torvalds 		if (sense_buffer[0] & 0x80) {
25082908769cSDamien Le Moal 			*info_out = get_unaligned_be32(&sense_buffer[3]);
25092908769cSDamien Le Moal 			return true;
25102908769cSDamien Le Moal 		}
25112908769cSDamien Le Moal 		return false;
25121da177e4SLinus Torvalds 	case 0x72:
25131da177e4SLinus Torvalds 	case 0x73:
25141da177e4SLinus Torvalds 		ucp = scsi_sense_desc_find(sense_buffer, sb_len,
25151da177e4SLinus Torvalds 					   0 /* info desc */);
25161da177e4SLinus Torvalds 		if (ucp && (0xa == ucp[1])) {
25172908769cSDamien Le Moal 			*info_out = get_unaligned_be64(&ucp[4]);
25182908769cSDamien Le Moal 			return true;
25191da177e4SLinus Torvalds 		}
25202908769cSDamien Le Moal 		return false;
25211da177e4SLinus Torvalds 	default:
25222908769cSDamien Le Moal 		return false;
25231da177e4SLinus Torvalds 	}
25241da177e4SLinus Torvalds }
25251da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_get_sense_info_fld);
2526