Blame view

drivers/scsi/scsi_error.c 70.5 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
  /*
   *  scsi_error.c Copyright (C) 1997 Eric Youngdale
   *
   *  SCSI error/timeout handling
   *      Initial versions: Eric Youngdale.  Based upon conversations with
0bf8c8697   Jesper Juhl   Reduce sequential...
6
   *                        Leonard Zubkoff and David Miller at Linux Expo,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
10
11
12
   *                        ideas originating from all over the place.
   *
   *	Restructured scsi_unjam_host and associated functions.
   *	September 04, 2002 Mike Anderson (andmike@us.ibm.com)
   *
   *	Forward port of Russell King's (rmk@arm.linux.org.uk) changes and
0bf8c8697   Jesper Juhl   Reduce sequential...
13
   *	minor cleanups.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
16
17
18
   *	September 30, 2002 Mike Anderson (andmike@us.ibm.com)
   */
  
  #include <linux/module.h>
  #include <linux/sched.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
19
  #include <linux/gfp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
  #include <linux/timer.h>
  #include <linux/string.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  #include <linux/kernel.h>
831441862   Rafael J. Wysocki   Freezer: make ker...
23
  #include <linux/freezer.h>
c5478def7   Christoph Hellwig   [SCSI] switch EH ...
24
  #include <linux/kthread.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
  #include <linux/interrupt.h>
  #include <linux/blkdev.h>
  #include <linux/delay.h>
fc73648a5   Hannes Reinecke   [SCSI] Handle MLQ...
28
  #include <linux/jiffies.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
  
  #include <scsi/scsi.h>
beb404875   Christoph Hellwig   [SCSI] remove scs...
31
  #include <scsi/scsi_cmnd.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
  #include <scsi/scsi_dbg.h>
  #include <scsi/scsi_device.h>
18a4d0a22   Martin K. Petersen   [SCSI] Handle dis...
34
  #include <scsi/scsi_driver.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  #include <scsi/scsi_eh.h>
c829c3941   James Smart   [SCSI] FC transpo...
36
  #include <scsi/scsi_transport.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
  #include <scsi/scsi_host.h>
  #include <scsi/scsi_ioctl.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
41
  
  #include "scsi_priv.h"
  #include "scsi_logging.h"
79ee83044   Adrian Bunk   [SCSI] scsi_error...
42
  #include "scsi_transport_api.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43

bf8162354   Kei Tokunaga   [SCSI] add scsi t...
44
  #include <trace/events/scsi.h>
14216561e   James Bottomley   [SCSI] Fix 'Devic...
45
  static void scsi_eh_done(struct scsi_cmnd *scmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
49
50
51
  /*
   * These should *probably* be handled by the host itself.
   * Since it is allowed to sleep, it probably should.
   */
  #define BUS_RESET_SETTLE_TIME   (10)
  #define HOST_RESET_SETTLE_TIME  (10)
3eef6257d   David Jeffery   [SCSI] Reduce err...
52
  static int scsi_eh_try_stu(struct scsi_cmnd *scmd);
e494f6a72   Hannes Reinecke   [SCSI] improved e...
53
54
  static int scsi_try_to_abort_cmd(struct scsi_host_template *,
  				 struct scsi_cmnd *);
3eef6257d   David Jeffery   [SCSI] Reduce err...
55

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
  /* called with shost->host_lock held */
  void scsi_eh_wakeup(struct Scsi_Host *shost)
  {
746650160   Christoph Hellwig   scsi: convert hos...
59
  	if (atomic_read(&shost->host_busy) == shost->host_failed) {
bf8162354   Kei Tokunaga   [SCSI] add scsi t...
60
  		trace_scsi_eh_wakeup(shost);
3ed7a4704   James Bottomley   [SCSI] Fix thread...
61
  		wake_up_process(shost->ehandler);
91921e016   Hannes Reinecke   scsi: use dev_pri...
62
63
64
  		SCSI_LOG_ERROR_RECOVERY(5, shost_printk(KERN_INFO, shost,
  			"Waking error handler thread
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
66
  	}
  }
f8bbfc247   Tejun Heo   [PATCH] SCSI: mak...
67
68
69
70
71
72
  
  /**
   * scsi_schedule_eh - schedule EH for SCSI host
   * @shost:	SCSI host to invoke error handling on.
   *
   * Schedule SCSI EH without scmd.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
73
   */
f8bbfc247   Tejun Heo   [PATCH] SCSI: mak...
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  void scsi_schedule_eh(struct Scsi_Host *shost)
  {
  	unsigned long flags;
  
  	spin_lock_irqsave(shost->host_lock, flags);
  
  	if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 ||
  	    scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) {
  		shost->host_eh_scheduled++;
  		scsi_eh_wakeup(shost);
  	}
  
  	spin_unlock_irqrestore(shost->host_lock, flags);
  }
  EXPORT_SYMBOL_GPL(scsi_schedule_eh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89

b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
90
91
  static int scsi_host_eh_past_deadline(struct Scsi_Host *shost)
  {
bb3b621a3   Ren Mingxin   [SCSI] Set the mi...
92
  	if (!shost->last_reset || shost->eh_deadline == -1)
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
93
  		return 0;
76ad3e595   Hannes Reinecke   [SCSI] Unlock acc...
94
95
96
97
  	/*
  	 * 32bit accesses are guaranteed to be atomic
  	 * (on all supported architectures), so instead
  	 * of using a spinlock we can as well double check
bb3b621a3   Ren Mingxin   [SCSI] Set the mi...
98
  	 * if eh_deadline has been set to 'off' during the
76ad3e595   Hannes Reinecke   [SCSI] Unlock acc...
99
100
101
  	 * time_before call.
  	 */
  	if (time_before(jiffies, shost->last_reset + shost->eh_deadline) &&
bb3b621a3   Ren Mingxin   [SCSI] Set the mi...
102
  	    shost->eh_deadline > -1)
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
103
104
105
106
  		return 0;
  
  	return 1;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
  /**
e494f6a72   Hannes Reinecke   [SCSI] improved e...
108
109
110
111
112
113
114
115
116
   * scmd_eh_abort_handler - Handle command aborts
   * @work:	command to be aborted.
   */
  void
  scmd_eh_abort_handler(struct work_struct *work)
  {
  	struct scsi_cmnd *scmd =
  		container_of(work, struct scsi_cmnd, abort_work.work);
  	struct scsi_device *sdev = scmd->device;
e494f6a72   Hannes Reinecke   [SCSI] improved e...
117
  	int rtn;
e494f6a72   Hannes Reinecke   [SCSI] improved e...
118
  	if (scsi_host_eh_past_deadline(sdev->host)) {
e494f6a72   Hannes Reinecke   [SCSI] improved e...
119
120
121
122
123
124
  		SCSI_LOG_ERROR_RECOVERY(3,
  			scmd_printk(KERN_INFO, scmd,
  				    "scmd %p eh timeout, not aborting
  ",
  				    scmd));
  	} else {
e494f6a72   Hannes Reinecke   [SCSI] improved e...
125
126
127
128
129
130
  		SCSI_LOG_ERROR_RECOVERY(3,
  			scmd_printk(KERN_INFO, scmd,
  				    "aborting command %p
  ", scmd));
  		rtn = scsi_try_to_abort_cmd(sdev->host->hostt, scmd);
  		if (rtn == SUCCESS) {
8922a9089   Ulrich Obergfell   scsi_error: fix i...
131
  			set_host_byte(scmd, DID_TIME_OUT);
bb3b621a3   Ren Mingxin   [SCSI] Set the mi...
132
133
134
135
136
137
138
139
  			if (scsi_host_eh_past_deadline(sdev->host)) {
  				SCSI_LOG_ERROR_RECOVERY(3,
  					scmd_printk(KERN_INFO, scmd,
  						    "scmd %p eh timeout, "
  						    "not retrying aborted "
  						    "command
  ", scmd));
  			} else if (!scsi_noretry_cmd(scmd) &&
e494f6a72   Hannes Reinecke   [SCSI] improved e...
140
141
142
143
144
145
146
  			    (++scmd->retries <= scmd->allowed)) {
  				SCSI_LOG_ERROR_RECOVERY(3,
  					scmd_printk(KERN_WARNING, scmd,
  						    "scmd %p retry "
  						    "aborted command
  ", scmd));
  				scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY);
bb3b621a3   Ren Mingxin   [SCSI] Set the mi...
147
  				return;
e494f6a72   Hannes Reinecke   [SCSI] improved e...
148
149
150
151
152
153
154
  			} else {
  				SCSI_LOG_ERROR_RECOVERY(3,
  					scmd_printk(KERN_WARNING, scmd,
  						    "scmd %p finish "
  						    "aborted command
  ", scmd));
  				scsi_finish_command(scmd);
bb3b621a3   Ren Mingxin   [SCSI] Set the mi...
155
  				return;
e494f6a72   Hannes Reinecke   [SCSI] improved e...
156
  			}
bb3b621a3   Ren Mingxin   [SCSI] Set the mi...
157
158
159
160
161
162
  		} else {
  			SCSI_LOG_ERROR_RECOVERY(3,
  				scmd_printk(KERN_INFO, scmd,
  					    "scmd %p abort failed, rtn %d
  ",
  					    scmd, rtn));
e494f6a72   Hannes Reinecke   [SCSI] improved e...
163
  		}
e494f6a72   Hannes Reinecke   [SCSI] improved e...
164
165
166
167
168
169
170
171
  	}
  
  	if (!scsi_eh_scmd_add(scmd, 0)) {
  		SCSI_LOG_ERROR_RECOVERY(3,
  			scmd_printk(KERN_WARNING, scmd,
  				    "scmd %p terminate "
  				    "aborted command
  ", scmd));
8922a9089   Ulrich Obergfell   scsi_error: fix i...
172
  		set_host_byte(scmd, DID_TIME_OUT);
e494f6a72   Hannes Reinecke   [SCSI] improved e...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  		scsi_finish_command(scmd);
  	}
  }
  
  /**
   * scsi_abort_command - schedule a command abort
   * @scmd:	scmd to abort.
   *
   * We only need to abort commands after a command timeout
   */
  static int
  scsi_abort_command(struct scsi_cmnd *scmd)
  {
  	struct scsi_device *sdev = scmd->device;
  	struct Scsi_Host *shost = sdev->host;
  	unsigned long flags;
  
  	if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) {
  		/*
  		 * Retry after abort failed, escalate to next level.
  		 */
7daf48048   Hannes Reinecke   [SCSI] Fix USB de...
194
  		scmd->eh_eflags &= ~SCSI_EH_ABORT_SCHEDULED;
e494f6a72   Hannes Reinecke   [SCSI] improved e...
195
196
197
198
  		SCSI_LOG_ERROR_RECOVERY(3,
  			scmd_printk(KERN_INFO, scmd,
  				    "scmd %p previous abort failed
  ", scmd));
fcc95a763   Bart Van Assche   scsi: remove two ...
199
  		BUG_ON(delayed_work_pending(&scmd->abort_work));
e494f6a72   Hannes Reinecke   [SCSI] improved e...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
  		return FAILED;
  	}
  
  	/*
  	 * Do not try a command abort if
  	 * SCSI EH has already started.
  	 */
  	spin_lock_irqsave(shost->host_lock, flags);
  	if (scsi_host_in_recovery(shost)) {
  		spin_unlock_irqrestore(shost->host_lock, flags);
  		SCSI_LOG_ERROR_RECOVERY(3,
  			scmd_printk(KERN_INFO, scmd,
  				    "scmd %p not aborting, host in recovery
  ",
  				    scmd));
  		return FAILED;
  	}
bb3b621a3   Ren Mingxin   [SCSI] Set the mi...
217
  	if (shost->eh_deadline != -1 && !shost->last_reset)
e494f6a72   Hannes Reinecke   [SCSI] improved e...
218
219
220
221
222
223
224
225
226
227
228
229
230
  		shost->last_reset = jiffies;
  	spin_unlock_irqrestore(shost->host_lock, flags);
  
  	scmd->eh_eflags |= SCSI_EH_ABORT_SCHEDULED;
  	SCSI_LOG_ERROR_RECOVERY(3,
  		scmd_printk(KERN_INFO, scmd,
  			    "scmd %p abort scheduled
  ", scmd));
  	queue_delayed_work(shost->tmf_work_q, &scmd->abort_work, HZ / 100);
  	return SUCCESS;
  }
  
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
232
233
234
235
236
   * scsi_eh_scmd_add - add scsi cmd to error handling.
   * @scmd:	scmd to run eh on.
   * @eh_flag:	optional SCSI_EH flag.
   *
   * Return value:
   *	0 on failure.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
237
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
240
241
  int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag)
  {
  	struct Scsi_Host *shost = scmd->device->host;
  	unsigned long flags;
939647ee3   James Bottomley   [SCSI] fix oops o...
242
  	int ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243

3ed7a4704   James Bottomley   [SCSI] Fix thread...
244
  	if (!shost->ehandler)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
247
  		return 0;
  
  	spin_lock_irqsave(shost->host_lock, flags);
939647ee3   James Bottomley   [SCSI] fix oops o...
248
249
250
  	if (scsi_host_set_state(shost, SHOST_RECOVERY))
  		if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY))
  			goto out_unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251

bb3b621a3   Ren Mingxin   [SCSI] Set the mi...
252
  	if (shost->eh_deadline != -1 && !shost->last_reset)
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
253
  		shost->last_reset = jiffies;
939647ee3   James Bottomley   [SCSI] fix oops o...
254
  	ret = 1;
e494f6a72   Hannes Reinecke   [SCSI] improved e...
255
256
  	if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED)
  		eh_flag &= ~SCSI_EH_CANCEL_CMD;
3111b0d16   Christoph Hellwig   [SCSI] remove scs...
257
  	scmd->eh_eflags |= eh_flag;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
  	list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
260
  	shost->host_failed++;
  	scsi_eh_wakeup(shost);
939647ee3   James Bottomley   [SCSI] fix oops o...
261
   out_unlock:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
  	spin_unlock_irqrestore(shost->host_lock, flags);
939647ee3   James Bottomley   [SCSI] fix oops o...
263
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
265
266
  }
  
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
   * scsi_times_out - Timeout function for normal scsi commands.
242f9dcb8   Jens Axboe   block: unify requ...
268
   * @req:	request that is timing out.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
271
272
273
274
   *
   * Notes:
   *     We do not need to lock this.  There is the potential for a race
   *     only in that the normal completion handling might run, but if the
   *     normal completion function determines that the timer has already
   *     fired, then it mustn't do anything.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
275
   */
242f9dcb8   Jens Axboe   block: unify requ...
276
  enum blk_eh_timer_return scsi_times_out(struct request *req)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
  {
242f9dcb8   Jens Axboe   block: unify requ...
278
  	struct scsi_cmnd *scmd = req->special;
242f9dcb8   Jens Axboe   block: unify requ...
279
  	enum blk_eh_timer_return rtn = BLK_EH_NOT_HANDLED;
0bf8c8697   Jesper Juhl   Reduce sequential...
280
  	struct Scsi_Host *host = scmd->device->host;
6c5f8ce1f   James Bottomley   [SCSI] expose eh_...
281

bf8162354   Kei Tokunaga   [SCSI] add scsi t...
282
  	trace_scsi_dispatch_cmd_timeout(scmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
  	scsi_log_completion(scmd, TIMEOUT_ERROR);
bb3b621a3   Ren Mingxin   [SCSI] Set the mi...
284
  	if (host->eh_deadline != -1 && !host->last_reset)
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
285
  		host->last_reset = jiffies;
0bf8c8697   Jesper Juhl   Reduce sequential...
286
287
288
289
  	if (host->transportt->eh_timed_out)
  		rtn = host->transportt->eh_timed_out(scmd);
  	else if (host->hostt->eh_timed_out)
  		rtn = host->hostt->eh_timed_out(scmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290

a33c070bc   Hannes Reinecke   scsi_error: set D...
291
292
293
  	if (rtn == BLK_EH_NOT_HANDLED) {
  		if (!host->hostt->no_async_abort &&
  		    scsi_abort_command(scmd) == SUCCESS)
e494f6a72   Hannes Reinecke   [SCSI] improved e...
294
  			return BLK_EH_NOT_HANDLED;
a33c070bc   Hannes Reinecke   scsi_error: set D...
295
296
297
298
  		set_host_byte(scmd, DID_TIME_OUT);
  		if (!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))
  			rtn = BLK_EH_HANDLED;
  	}
242f9dcb8   Jens Axboe   block: unify requ...
299

fa9907810   Christoph Hellwig   [SCSI] clean up s...
300
  	return rtn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
302
303
304
305
306
307
308
309
310
311
312
  }
  
  /**
   * scsi_block_when_processing_errors - Prevent cmds from being queued.
   * @sdev:	Device on which we are performing recovery.
   *
   * Description:
   *     We block until the host is out of error recovery, and then check to
   *     see whether the host or the device is offline.
   *
   * Return value:
   *     0 when dev was taken offline by error recovery. 1 OK to proceed.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
313
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
315
316
  int scsi_block_when_processing_errors(struct scsi_device *sdev)
  {
  	int online;
939647ee3   James Bottomley   [SCSI] fix oops o...
317
  	wait_event(sdev->host->host_wait, !scsi_host_in_recovery(sdev->host));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
319
  
  	online = scsi_device_online(sdev);
91921e016   Hannes Reinecke   scsi: use dev_pri...
320
321
322
  	SCSI_LOG_ERROR_RECOVERY(5, sdev_printk(KERN_INFO, sdev,
  		"%s: rtn: %d
  ", __func__, online));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
325
326
327
328
329
330
331
332
  
  	return online;
  }
  EXPORT_SYMBOL(scsi_block_when_processing_errors);
  
  #ifdef CONFIG_SCSI_LOGGING
  /**
   * scsi_eh_prt_fail_stats - Log info on failures.
   * @shost:	scsi host being recovered.
   * @work_q:	Queue of scsi cmds to process.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
333
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
336
337
338
339
340
341
342
343
344
345
346
347
  static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
  					  struct list_head *work_q)
  {
  	struct scsi_cmnd *scmd;
  	struct scsi_device *sdev;
  	int total_failures = 0;
  	int cmd_failed = 0;
  	int cmd_cancel = 0;
  	int devices_failed = 0;
  
  	shost_for_each_device(sdev, shost) {
  		list_for_each_entry(scmd, work_q, eh_entry) {
  			if (scmd->device == sdev) {
  				++total_failures;
3111b0d16   Christoph Hellwig   [SCSI] remove scs...
348
  				if (scmd->eh_eflags & SCSI_EH_CANCEL_CMD)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
  					++cmd_cancel;
0bf8c8697   Jesper Juhl   Reduce sequential...
350
  				else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
353
354
355
356
  					++cmd_failed;
  			}
  		}
  
  		if (cmd_cancel || cmd_failed) {
  			SCSI_LOG_ERROR_RECOVERY(3,
9ccfc756a   James Bottomley   [SCSI] move the m...
357
358
359
  				sdev_printk(KERN_INFO, sdev,
  					    "%s: cmds failed: %d, cancel: %d
  ",
cadbd4a5e   Harvey Harrison   [SCSI] replace __...
360
  					    __func__, cmd_failed,
9ccfc756a   James Bottomley   [SCSI] move the m...
361
  					    cmd_cancel));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
364
365
366
  			cmd_cancel = 0;
  			cmd_failed = 0;
  			++devices_failed;
  		}
  	}
91921e016   Hannes Reinecke   scsi: use dev_pri...
367
368
369
370
  	SCSI_LOG_ERROR_RECOVERY(2, shost_printk(KERN_INFO, shost,
  				   "Total of %d commands on %d"
  				   " devices require eh work
  ",
0bf8c8697   Jesper Juhl   Reduce sequential...
371
  				   total_failures, devices_failed));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372
373
  }
  #endif
279afdfe7   Ewan D. Milne   [SCSI] Generate u...
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
   /**
   * scsi_report_lun_change - Set flag on all *other* devices on the same target
   *                          to indicate that a UNIT ATTENTION is expected.
   * @sdev:	Device reporting the UNIT ATTENTION
   */
  static void scsi_report_lun_change(struct scsi_device *sdev)
  {
  	sdev->sdev_target->expecting_lun_change = 1;
  }
  
  /**
   * scsi_report_sense - Examine scsi sense information and log messages for
   *		       certain conditions, also issue uevents for some of them.
   * @sdev:	Device reporting the sense code
   * @sshdr:	sshdr to be examined
   */
  static void scsi_report_sense(struct scsi_device *sdev,
  			      struct scsi_sense_hdr *sshdr)
  {
  	enum scsi_device_event evt_type = SDEV_EVT_MAXBITS;	/* i.e. none */
  
  	if (sshdr->sense_key == UNIT_ATTENTION) {
  		if (sshdr->asc == 0x3f && sshdr->ascq == 0x03) {
  			evt_type = SDEV_EVT_INQUIRY_CHANGE_REPORTED;
  			sdev_printk(KERN_WARNING, sdev,
  				    "Inquiry data has changed");
  		} else if (sshdr->asc == 0x3f && sshdr->ascq == 0x0e) {
  			evt_type = SDEV_EVT_LUN_CHANGE_REPORTED;
  			scsi_report_lun_change(sdev);
  			sdev_printk(KERN_WARNING, sdev,
  				    "Warning! Received an indication that the "
  				    "LUN assignments on this target have "
  				    "changed. The Linux SCSI layer does not "
  				    "automatically remap LUN assignments.
  ");
  		} else if (sshdr->asc == 0x3f)
  			sdev_printk(KERN_WARNING, sdev,
  				    "Warning! Received an indication that the "
  				    "operating parameters on this target have "
  				    "changed. The Linux SCSI layer does not "
  				    "automatically adjust these parameters.
  ");
  
  		if (sshdr->asc == 0x38 && sshdr->ascq == 0x07) {
  			evt_type = SDEV_EVT_SOFT_THRESHOLD_REACHED_REPORTED;
  			sdev_printk(KERN_WARNING, sdev,
  				    "Warning! Received an indication that the "
  				    "LUN reached a thin provisioning soft "
  				    "threshold.
  ");
  		}
  
  		if (sshdr->asc == 0x2a && sshdr->ascq == 0x01) {
  			evt_type = SDEV_EVT_MODE_PARAMETER_CHANGE_REPORTED;
  			sdev_printk(KERN_WARNING, sdev,
  				    "Mode parameters changed");
  		} else if (sshdr->asc == 0x2a && sshdr->ascq == 0x09) {
  			evt_type = SDEV_EVT_CAPACITY_CHANGE_REPORTED;
  			sdev_printk(KERN_WARNING, sdev,
  				    "Capacity data has changed");
  		} else if (sshdr->asc == 0x2a)
  			sdev_printk(KERN_WARNING, sdev,
  				    "Parameters changed");
  	}
  
  	if (evt_type != SDEV_EVT_MAXBITS) {
  		set_bit(evt_type, sdev->pending_events);
  		schedule_work(&sdev->event_work);
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
445
446
447
448
  /**
   * scsi_check_sense - Examine scsi cmd sense
   * @scmd:	Cmd to have sense checked.
   *
   * Return value:
87f14e658   Hannes Reinecke   [SCSI] Set hostby...
449
   *	SUCCESS or FAILED or NEEDS_RETRY or ADD_TO_MLQUEUE
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
451
452
453
   *
   * Notes:
   *	When a deferred error is detected the current command has
   *	not been executed and needs retrying.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
454
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
456
  static int scsi_check_sense(struct scsi_cmnd *scmd)
  {
a6a8d9f87   Chandra Seetharaman   [SCSI] scsi_dh: a...
457
  	struct scsi_device *sdev = scmd->device;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
460
461
  	struct scsi_sense_hdr sshdr;
  
  	if (! scsi_command_normalize_sense(scmd, &sshdr))
  		return FAILED;	/* no valid sense data */
279afdfe7   Ewan D. Milne   [SCSI] Generate u...
462
  	scsi_report_sense(sdev, &sshdr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
464
  	if (scsi_sense_is_deferred(&sshdr))
  		return NEEDS_RETRY;
a6a8d9f87   Chandra Seetharaman   [SCSI] scsi_dh: a...
465
466
467
468
469
470
471
472
473
  	if (sdev->scsi_dh_data && sdev->scsi_dh_data->scsi_dh &&
  			sdev->scsi_dh_data->scsi_dh->check_sense) {
  		int rc;
  
  		rc = sdev->scsi_dh_data->scsi_dh->check_sense(sdev, &sshdr);
  		if (rc != SCSI_RETURN_NOT_HANDLED)
  			return rc;
  		/* handler does not care. Drop down to default handling */
  	}
e925cc431   Christoph Hellwig   scsi: call device...
474
475
476
477
478
479
480
  	if (scmd->cmnd[0] == TEST_UNIT_READY && scmd->scsi_done != scsi_eh_done)
  		/*
  		 * nasty: for mid-layer issued TURs, we need to return the
  		 * actual sense data without any recovery attempt.  For eh
  		 * issued ones, we need to try to recover and interpret
  		 */
  		return SUCCESS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
  	/*
  	 * Previous logic looked for FILEMARK, EOM or ILI which are
  	 * mainly associated with tapes and returned SUCCESS.
  	 */
  	if (sshdr.response_code == 0x70) {
  		/* fixed format */
  		if (scmd->sense_buffer[2] & 0xe0)
  			return SUCCESS;
  	} else {
  		/*
  		 * descriptor format: look for "stream commands sense data
  		 * descriptor" (see SSC-3). Assume single sense data
  		 * descriptor. Ignore ILI from SBC-2 READ LONG and WRITE LONG.
  		 */
  		if ((sshdr.additional_length > 3) &&
  		    (scmd->sense_buffer[8] == 0x4) &&
  		    (scmd->sense_buffer[11] & 0xe0))
  			return SUCCESS;
  	}
  
  	switch (sshdr.sense_key) {
  	case NO_SENSE:
  		return SUCCESS;
  	case RECOVERED_ERROR:
  		return /* soft_error */ SUCCESS;
  
  	case ABORTED_COMMAND:
511e44f42   Martin K. Petersen   [SCSI] Do not ret...
508
509
  		if (sshdr.asc == 0x10) /* DIF */
  			return SUCCESS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510
511
512
513
514
515
516
517
518
519
  		return NEEDS_RETRY;
  	case NOT_READY:
  	case UNIT_ATTENTION:
  		/*
  		 * if we are expecting a cc/ua because of a bus reset that we
  		 * performed, treat this just as a retry.  otherwise this is
  		 * information that we should pass up to the upper-level driver
  		 * so that we can deal with it there.
  		 */
  		if (scmd->device->expecting_cc_ua) {
dfcf77758   TARUISI Hiroaki   [SCSI] Fix out of...
520
521
522
523
524
525
526
527
528
529
  			/*
  			 * Because some device does not queue unit
  			 * attentions correctly, we carefully check
  			 * additional sense code and qualifier so as
  			 * not to squash media change unit attention.
  			 */
  			if (sshdr.asc != 0x28 || sshdr.ascq != 0x00) {
  				scmd->device->expecting_cc_ua = 0;
  				return NEEDS_RETRY;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
531
  		}
  		/*
279afdfe7   Ewan D. Milne   [SCSI] Generate u...
532
533
534
535
536
537
538
539
  		 * we might also expect a cc/ua if another LUN on the target
  		 * reported a UA with an ASC/ASCQ of 3F 0E -
  		 * REPORTED LUNS DATA HAS CHANGED.
  		 */
  		if (scmd->device->sdev_target->expecting_lun_change &&
  		    sshdr.asc == 0x3f && sshdr.ascq == 0x0e)
  			return NEEDS_RETRY;
  		/*
0bf8c8697   Jesper Juhl   Reduce sequential...
540
  		 * if the device is in the process of becoming ready, we
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
543
544
545
546
547
548
549
550
551
  		 * should retry.
  		 */
  		if ((sshdr.asc == 0x04) && (sshdr.ascq == 0x01))
  			return NEEDS_RETRY;
  		/*
  		 * if the device is not started, we need to wake
  		 * the error handler to start the motor
  		 */
  		if (scmd->device->allow_restart &&
  		    (sshdr.asc == 0x04) && (sshdr.ascq == 0x02))
  			return FAILED;
02e031cbc   Christoph Hellwig   block: remove REQ...
552
553
554
555
556
  		/*
  		 * Pass the UA upwards for a determination in the completion
  		 * functions.
  		 */
  		return SUCCESS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557

63583cca7   Hannes Reinecke   [SCSI] Add detail...
558
  		/* these are not supported */
a9d6ceb83   Hannes Reinecke   [SCSI] return ENO...
559
560
561
562
563
564
  	case DATA_PROTECT:
  		if (sshdr.asc == 0x27 && sshdr.ascq == 0x07) {
  			/* Thin provisioning hard threshold reached */
  			set_host_byte(scmd, DID_ALLOC_FAILURE);
  			return SUCCESS;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
565
566
567
  	case COPY_ABORTED:
  	case VOLUME_OVERFLOW:
  	case MISCOMPARE:
63583cca7   Hannes Reinecke   [SCSI] Add detail...
568
  	case BLANK_CHECK:
87f14e658   Hannes Reinecke   [SCSI] Set hostby...
569
570
  		set_host_byte(scmd, DID_TARGET_FAILURE);
  		return SUCCESS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
572
  
  	case MEDIUM_ERROR:
fd1b494d4   Luben Tuikov   [SCSI] Fix sense ...
573
574
575
  		if (sshdr.asc == 0x11 || /* UNRECOVERED READ ERR */
  		    sshdr.asc == 0x13 || /* AMNF DATA FIELD */
  		    sshdr.asc == 0x14) { /* RECORD NOT FOUND */
7e782af57   Hannes Reinecke   [SCSI] Return ENO...
576
  			set_host_byte(scmd, DID_MEDIUM_ERROR);
87f14e658   Hannes Reinecke   [SCSI] Set hostby...
577
  			return SUCCESS;
fd1b494d4   Luben Tuikov   [SCSI] Fix sense ...
578
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
580
581
582
  		return NEEDS_RETRY;
  
  	case HARDWARE_ERROR:
  		if (scmd->device->retry_hwerror)
bb0003c1e   Mike Anderson   [SCSI] make scsi_...
583
  			return ADD_TO_MLQUEUE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
  		else
87f14e658   Hannes Reinecke   [SCSI] Set hostby...
585
  			set_host_byte(scmd, DID_TARGET_FAILURE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
587
  
  	case ILLEGAL_REQUEST:
47ac56db1   Mike Snitzer   [SCSI] scsi_error...
588
589
590
591
  		if (sshdr.asc == 0x20 || /* Invalid command operation code */
  		    sshdr.asc == 0x21 || /* Logical block address out of range */
  		    sshdr.asc == 0x24 || /* Invalid field in cdb */
  		    sshdr.asc == 0x26) { /* Parameter value invalid */
87f14e658   Hannes Reinecke   [SCSI] Set hostby...
592
  			set_host_byte(scmd, DID_TARGET_FAILURE);
47ac56db1   Mike Snitzer   [SCSI] scsi_error...
593
594
  		}
  		return SUCCESS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
596
597
598
  	default:
  		return SUCCESS;
  	}
  }
4a84067db   Vasu Dev   [SCSI] add queue_...
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
  static void scsi_handle_queue_ramp_up(struct scsi_device *sdev)
  {
  	struct scsi_host_template *sht = sdev->host->hostt;
  	struct scsi_device *tmp_sdev;
  
  	if (!sht->change_queue_depth ||
  	    sdev->queue_depth >= sdev->max_queue_depth)
  		return;
  
  	if (time_before(jiffies,
  	    sdev->last_queue_ramp_up + sdev->queue_ramp_up_period))
  		return;
  
  	if (time_before(jiffies,
  	    sdev->last_queue_full_time + sdev->queue_ramp_up_period))
  		return;
  
  	/*
  	 * Walk all devices of a target and do
  	 * ramp up on them.
  	 */
  	shost_for_each_device(tmp_sdev, sdev->host) {
  		if (tmp_sdev->channel != sdev->channel ||
  		    tmp_sdev->id != sdev->id ||
  		    tmp_sdev->queue_depth == sdev->max_queue_depth)
  			continue;
  		/*
  		 * call back into LLD to increase queue_depth by one
  		 * with ramp up reason code.
  		 */
  		sht->change_queue_depth(tmp_sdev, tmp_sdev->queue_depth + 1,
  					SCSI_QDEPTH_RAMP_UP);
  		sdev->last_queue_ramp_up = jiffies;
  	}
  }
42a6a9183   Mike Christie   [SCSI] scsi error...
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
  static void scsi_handle_queue_full(struct scsi_device *sdev)
  {
  	struct scsi_host_template *sht = sdev->host->hostt;
  	struct scsi_device *tmp_sdev;
  
  	if (!sht->change_queue_depth)
  		return;
  
  	shost_for_each_device(tmp_sdev, sdev->host) {
  		if (tmp_sdev->channel != sdev->channel ||
  		    tmp_sdev->id != sdev->id)
  			continue;
  		/*
  		 * We do not know the number of commands that were at
  		 * the device when we got the queue full so we start
  		 * from the highest possible value and work our way down.
  		 */
  		sht->change_queue_depth(tmp_sdev, tmp_sdev->queue_depth - 1,
  					SCSI_QDEPTH_QFULL);
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
656
657
658
659
660
661
662
663
  /**
   * scsi_eh_completed_normally - Disposition a eh cmd on return from LLD.
   * @scmd:	SCSI cmd to examine.
   *
   * Notes:
   *    This is *only* called when we are examining the status of commands
   *    queued during error recovery.  the main difference here is that we
   *    don't allow for the possibility of retries here, and we are a lot
   *    more restrictive about what we consider acceptable.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
664
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
  static int scsi_eh_completed_normally(struct scsi_cmnd *scmd)
  {
  	/*
  	 * first check the host byte, to see if there is anything in there
  	 * that would indicate what we need to do.
  	 */
  	if (host_byte(scmd->result) == DID_RESET) {
  		/*
  		 * rats.  we are already in the error handler, so we now
  		 * get to try and figure out what to do next.  if the sense
  		 * is valid, we have a pretty good idea of what to do.
  		 * if not, we mark it as FAILED.
  		 */
  		return scsi_check_sense(scmd);
  	}
  	if (host_byte(scmd->result) != DID_OK)
  		return FAILED;
  
  	/*
  	 * next, check the message byte.
  	 */
  	if (msg_byte(scmd->result) != COMMAND_COMPLETE)
  		return FAILED;
  
  	/*
  	 * now, check the status byte to see if this indicates
  	 * anything special.
  	 */
  	switch (status_byte(scmd->result)) {
  	case GOOD:
4a84067db   Vasu Dev   [SCSI] add queue_...
695
  		scsi_handle_queue_ramp_up(scmd->device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
697
698
699
700
701
702
703
704
705
706
  	case COMMAND_TERMINATED:
  		return SUCCESS;
  	case CHECK_CONDITION:
  		return scsi_check_sense(scmd);
  	case CONDITION_GOOD:
  	case INTERMEDIATE_GOOD:
  	case INTERMEDIATE_C_GOOD:
  		/*
  		 * who knows?  FIXME(eric)
  		 */
  		return SUCCESS;
5f91bb050   Michael Reed   [SCSI] reservatio...
707
  	case RESERVATION_CONFLICT:
67110dfd4   James Bottomley   [SCSI] make error...
708
709
710
711
712
713
  		if (scmd->cmnd[0] == TEST_UNIT_READY)
  			/* it is a success, we probed the device and
  			 * found it */
  			return SUCCESS;
  		/* otherwise, we failed to send the command */
  		return FAILED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
  	case QUEUE_FULL:
42a6a9183   Mike Christie   [SCSI] scsi error...
715
716
717
  		scsi_handle_queue_full(scmd->device);
  		/* fall through */
  	case BUSY:
3eb3a9285   Hannes Reinecke   [SCSI] Return NEE...
718
  		return NEEDS_RETRY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
720
721
722
723
724
725
  	default:
  		return FAILED;
  	}
  	return FAILED;
  }
  
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
727
   * scsi_eh_done - Completion function for error handling.
   * @scmd:	Cmd that is done.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
728
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
729
730
  static void scsi_eh_done(struct scsi_cmnd *scmd)
  {
0bf8c8697   Jesper Juhl   Reduce sequential...
731
  	struct completion *eh_action;
85631672e   Michael Reed   [SCSI] fix OOPS d...
732

91921e016   Hannes Reinecke   scsi: use dev_pri...
733
734
735
  	SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
  			"%s scmd: %p result: %x
  ",
cadbd4a5e   Harvey Harrison   [SCSI] replace __...
736
  			__func__, scmd, scmd->result));
85631672e   Michael Reed   [SCSI] fix OOPS d...
737
738
739
740
  
  	eh_action = scmd->device->host->eh_action;
  	if (eh_action)
  		complete(eh_action);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
742
743
  }
  
  /**
292148f8b   Brian King   [SCSI] scsi_error...
744
   * scsi_try_host_reset - ask host adapter to reset itself
c2b3ebd0d   Geert Uytterhoeven   scsi: Spelling hs...
745
   * @scmd:	SCSI cmd to send host reset.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
746
   */
292148f8b   Brian King   [SCSI] scsi_error...
747
748
749
750
  static int scsi_try_host_reset(struct scsi_cmnd *scmd)
  {
  	unsigned long flags;
  	int rtn;
0bf8c8697   Jesper Juhl   Reduce sequential...
751
752
  	struct Scsi_Host *host = scmd->device->host;
  	struct scsi_host_template *hostt = host->hostt;
292148f8b   Brian King   [SCSI] scsi_error...
753

91921e016   Hannes Reinecke   scsi: use dev_pri...
754
755
756
  	SCSI_LOG_ERROR_RECOVERY(3,
  		shost_printk(KERN_INFO, host, "Snd Host RST
  "));
292148f8b   Brian King   [SCSI] scsi_error...
757

0bf8c8697   Jesper Juhl   Reduce sequential...
758
  	if (!hostt->eh_host_reset_handler)
292148f8b   Brian King   [SCSI] scsi_error...
759
  		return FAILED;
0bf8c8697   Jesper Juhl   Reduce sequential...
760
  	rtn = hostt->eh_host_reset_handler(scmd);
292148f8b   Brian King   [SCSI] scsi_error...
761
762
  
  	if (rtn == SUCCESS) {
0bf8c8697   Jesper Juhl   Reduce sequential...
763
  		if (!hostt->skip_settle_delay)
292148f8b   Brian King   [SCSI] scsi_error...
764
  			ssleep(HOST_RESET_SETTLE_TIME);
0bf8c8697   Jesper Juhl   Reduce sequential...
765
766
767
  		spin_lock_irqsave(host->host_lock, flags);
  		scsi_report_bus_reset(host, scmd_channel(scmd));
  		spin_unlock_irqrestore(host->host_lock, flags);
292148f8b   Brian King   [SCSI] scsi_error...
768
769
770
771
772
773
774
775
  	}
  
  	return rtn;
  }
  
  /**
   * scsi_try_bus_reset - ask host to perform a bus reset
   * @scmd:	SCSI cmd to send bus reset.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
776
   */
292148f8b   Brian King   [SCSI] scsi_error...
777
778
779
780
  static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
  {
  	unsigned long flags;
  	int rtn;
0bf8c8697   Jesper Juhl   Reduce sequential...
781
782
  	struct Scsi_Host *host = scmd->device->host;
  	struct scsi_host_template *hostt = host->hostt;
292148f8b   Brian King   [SCSI] scsi_error...
783

91921e016   Hannes Reinecke   scsi: use dev_pri...
784
785
786
  	SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
  		"%s: Snd Bus RST
  ", __func__));
292148f8b   Brian King   [SCSI] scsi_error...
787

0bf8c8697   Jesper Juhl   Reduce sequential...
788
  	if (!hostt->eh_bus_reset_handler)
292148f8b   Brian King   [SCSI] scsi_error...
789
  		return FAILED;
0bf8c8697   Jesper Juhl   Reduce sequential...
790
  	rtn = hostt->eh_bus_reset_handler(scmd);
292148f8b   Brian King   [SCSI] scsi_error...
791
792
  
  	if (rtn == SUCCESS) {
0bf8c8697   Jesper Juhl   Reduce sequential...
793
  		if (!hostt->skip_settle_delay)
292148f8b   Brian King   [SCSI] scsi_error...
794
  			ssleep(BUS_RESET_SETTLE_TIME);
0bf8c8697   Jesper Juhl   Reduce sequential...
795
796
797
  		spin_lock_irqsave(host->host_lock, flags);
  		scsi_report_bus_reset(host, scmd_channel(scmd));
  		spin_unlock_irqrestore(host->host_lock, flags);
292148f8b   Brian King   [SCSI] scsi_error...
798
799
800
801
  	}
  
  	return rtn;
  }
30bd7df8c   Mike Christie   [SCSI] scsi_error...
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
  static void __scsi_report_device_reset(struct scsi_device *sdev, void *data)
  {
  	sdev->was_reset = 1;
  	sdev->expecting_cc_ua = 1;
  }
  
  /**
   * scsi_try_target_reset - Ask host to perform a target reset
   * @scmd:	SCSI cmd used to send a target reset
   *
   * Notes:
   *    There is no timeout for this operation.  if this operation is
   *    unreliable for a given host, then the host itself needs to put a
   *    timer on it, and set the host back to a consistent state prior to
   *    returning.
   */
  static int scsi_try_target_reset(struct scsi_cmnd *scmd)
  {
  	unsigned long flags;
  	int rtn;
0bf8c8697   Jesper Juhl   Reduce sequential...
822
823
  	struct Scsi_Host *host = scmd->device->host;
  	struct scsi_host_template *hostt = host->hostt;
30bd7df8c   Mike Christie   [SCSI] scsi_error...
824

0bf8c8697   Jesper Juhl   Reduce sequential...
825
  	if (!hostt->eh_target_reset_handler)
30bd7df8c   Mike Christie   [SCSI] scsi_error...
826
  		return FAILED;
0bf8c8697   Jesper Juhl   Reduce sequential...
827
  	rtn = hostt->eh_target_reset_handler(scmd);
30bd7df8c   Mike Christie   [SCSI] scsi_error...
828
  	if (rtn == SUCCESS) {
0bf8c8697   Jesper Juhl   Reduce sequential...
829
  		spin_lock_irqsave(host->host_lock, flags);
30bd7df8c   Mike Christie   [SCSI] scsi_error...
830
831
  		__starget_for_each_device(scsi_target(scmd->device), NULL,
  					  __scsi_report_device_reset);
0bf8c8697   Jesper Juhl   Reduce sequential...
832
  		spin_unlock_irqrestore(host->host_lock, flags);
30bd7df8c   Mike Christie   [SCSI] scsi_error...
833
834
835
836
  	}
  
  	return rtn;
  }
292148f8b   Brian King   [SCSI] scsi_error...
837
838
839
840
841
842
843
844
845
  /**
   * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev
   * @scmd:	SCSI cmd used to send BDR
   *
   * Notes:
   *    There is no timeout for this operation.  if this operation is
   *    unreliable for a given host, then the host itself needs to put a
   *    timer on it, and set the host back to a consistent state prior to
   *    returning.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
846
   */
292148f8b   Brian King   [SCSI] scsi_error...
847
848
849
  static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
  {
  	int rtn;
0bf8c8697   Jesper Juhl   Reduce sequential...
850
  	struct scsi_host_template *hostt = scmd->device->host->hostt;
292148f8b   Brian King   [SCSI] scsi_error...
851

0bf8c8697   Jesper Juhl   Reduce sequential...
852
  	if (!hostt->eh_device_reset_handler)
292148f8b   Brian King   [SCSI] scsi_error...
853
  		return FAILED;
0bf8c8697   Jesper Juhl   Reduce sequential...
854
  	rtn = hostt->eh_device_reset_handler(scmd);
30bd7df8c   Mike Christie   [SCSI] scsi_error...
855
856
  	if (rtn == SUCCESS)
  		__scsi_report_device_reset(scmd->device, NULL);
292148f8b   Brian King   [SCSI] scsi_error...
857
858
  	return rtn;
  }
0bf8c8697   Jesper Juhl   Reduce sequential...
859
  static int scsi_try_to_abort_cmd(struct scsi_host_template *hostt, struct scsi_cmnd *scmd)
292148f8b   Brian King   [SCSI] scsi_error...
860
  {
0bf8c8697   Jesper Juhl   Reduce sequential...
861
  	if (!hostt->eh_abort_handler)
292148f8b   Brian King   [SCSI] scsi_error...
862
  		return FAILED;
0bf8c8697   Jesper Juhl   Reduce sequential...
863
  	return hostt->eh_abort_handler(scmd);
292148f8b   Brian King   [SCSI] scsi_error...
864
  }
292148f8b   Brian King   [SCSI] scsi_error...
865
866
  static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
  {
0bf8c8697   Jesper Juhl   Reduce sequential...
867
  	if (scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd) != SUCCESS)
292148f8b   Brian King   [SCSI] scsi_error...
868
  		if (scsi_try_bus_device_reset(scmd) != SUCCESS)
30bd7df8c   Mike Christie   [SCSI] scsi_error...
869
870
871
  			if (scsi_try_target_reset(scmd) != SUCCESS)
  				if (scsi_try_bus_reset(scmd) != SUCCESS)
  					scsi_try_host_reset(scmd);
292148f8b   Brian King   [SCSI] scsi_error...
872
873
874
  }
  
  /**
3b729f764   Santosh Y   scsi: fix comment...
875
   * scsi_eh_prep_cmnd  - Save a scsi command info as part of error recovery
2dc611de5   Christoph Hellwig   [SCSI] use one-el...
876
   * @scmd:       SCSI command structure to hijack
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
877
   * @ses:        structure to save restore information
55db6c1b8   Boaz Harrosh   [SCSI] scsi_error...
878
   * @cmnd:       CDB to send. Can be NULL if no new cmnd is needed
64a87b244   Boaz Harrosh   [SCSI] Let scsi_c...
879
   * @cmnd_size:  size in bytes of @cmnd (must be <= BLK_MAX_CDB)
55db6c1b8   Boaz Harrosh   [SCSI] scsi_error...
880
   * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored)
2dc611de5   Christoph Hellwig   [SCSI] use one-el...
881
   *
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
882
   * This function is used to save a scsi command information before re-execution
55db6c1b8   Boaz Harrosh   [SCSI] scsi_error...
883
884
885
886
   * as part of the error recovery process.  If @sense_bytes is 0 the command
   * sent must be one that does not transfer any data.  If @sense_bytes != 0
   * @cmnd is ignored and this functions sets up a REQUEST_SENSE command
   * and cmnd buffers to read @sense_bytes into @scmd->sense_buffer.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
887
   */
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
888
889
  void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
  			unsigned char *cmnd, int cmnd_size, unsigned sense_bytes)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
890
  {
f59114b7b   Tejun Heo   [PATCH] scsi: scs...
891
  	struct scsi_device *sdev = scmd->device;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
892

631c228cd   Christoph Hellwig   [SCSI] hide EH ba...
893
894
895
896
897
898
899
  	/*
  	 * We need saved copies of a number of fields - this is because
  	 * error handling may need to overwrite these with different values
  	 * to run different commands, and once error handling is complete,
  	 * we will need to restore these values prior to running the actual
  	 * command.
  	 */
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
900
  	ses->cmd_len = scmd->cmd_len;
64a87b244   Boaz Harrosh   [SCSI] Let scsi_c...
901
  	ses->cmnd = scmd->cmnd;
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
902
  	ses->data_direction = scmd->sc_data_direction;
30b0c37b2   Boaz Harrosh   [SCSI] implement ...
903
  	ses->sdb = scmd->sdb;
6f9a35e2d   Boaz Harrosh   [SCSI] bidirectio...
904
  	ses->next_rq = scmd->request->next_rq;
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
905
  	ses->result = scmd->result;
12265709a   Alan Stern   [SCSI] scsi_eh_pr...
906
  	ses->underflow = scmd->underflow;
db007fc5e   Martin K. Petersen   [SCSI] Command pr...
907
  	ses->prot_op = scmd->prot_op;
631c228cd   Christoph Hellwig   [SCSI] hide EH ba...
908

db007fc5e   Martin K. Petersen   [SCSI] Command pr...
909
  	scmd->prot_op = SCSI_PROT_NORMAL;
c69e6f812   James Bottomley   [SCSI] More USB d...
910
  	scmd->eh_eflags = 0;
64a87b244   Boaz Harrosh   [SCSI] Let scsi_c...
911
912
  	scmd->cmnd = ses->eh_cmnd;
  	memset(scmd->cmnd, 0, BLK_MAX_CDB);
30b0c37b2   Boaz Harrosh   [SCSI] implement ...
913
  	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
6f9a35e2d   Boaz Harrosh   [SCSI] bidirectio...
914
  	scmd->request->next_rq = NULL;
644373a42   Alan Stern   [SCSI] Fix comman...
915
  	scmd->result = 0;
30b0c37b2   Boaz Harrosh   [SCSI] implement ...
916

55db6c1b8   Boaz Harrosh   [SCSI] scsi_error...
917
  	if (sense_bytes) {
30b0c37b2   Boaz Harrosh   [SCSI] implement ...
918
919
  		scmd->sdb.length = min_t(unsigned, SCSI_SENSE_BUFFERSIZE,
  					 sense_bytes);
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
920
  		sg_init_one(&ses->sense_sgl, scmd->sense_buffer,
30b0c37b2   Boaz Harrosh   [SCSI] implement ...
921
922
  			    scmd->sdb.length);
  		scmd->sdb.table.sgl = &ses->sense_sgl;
55db6c1b8   Boaz Harrosh   [SCSI] scsi_error...
923
  		scmd->sc_data_direction = DMA_FROM_DEVICE;
30b0c37b2   Boaz Harrosh   [SCSI] implement ...
924
  		scmd->sdb.table.nents = 1;
55db6c1b8   Boaz Harrosh   [SCSI] scsi_error...
925
  		scmd->cmnd[0] = REQUEST_SENSE;
30b0c37b2   Boaz Harrosh   [SCSI] implement ...
926
  		scmd->cmnd[4] = scmd->sdb.length;
55db6c1b8   Boaz Harrosh   [SCSI] scsi_error...
927
  		scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
631c228cd   Christoph Hellwig   [SCSI] hide EH ba...
928
  	} else {
631c228cd   Christoph Hellwig   [SCSI] hide EH ba...
929
  		scmd->sc_data_direction = DMA_NONE;
55db6c1b8   Boaz Harrosh   [SCSI] scsi_error...
930
  		if (cmnd) {
64a87b244   Boaz Harrosh   [SCSI] Let scsi_c...
931
  			BUG_ON(cmnd_size > BLK_MAX_CDB);
55db6c1b8   Boaz Harrosh   [SCSI] scsi_error...
932
933
934
  			memcpy(scmd->cmnd, cmnd, cmnd_size);
  			scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
  		}
631c228cd   Christoph Hellwig   [SCSI] hide EH ba...
935
936
937
  	}
  
  	scmd->underflow = 0;
631c228cd   Christoph Hellwig   [SCSI] hide EH ba...
938

55db6c1b8   Boaz Harrosh   [SCSI] scsi_error...
939
  	if (sdev->scsi_level <= SCSI_2 && sdev->scsi_level != SCSI_UNKNOWN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
940
  		scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) |
f59114b7b   Tejun Heo   [PATCH] scsi: scs...
941
  			(sdev->lun << 5 & 0xe0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
942

631c228cd   Christoph Hellwig   [SCSI] hide EH ba...
943
944
945
946
  	/*
  	 * Zero the sense buffer.  The scsi spec mandates that any
  	 * untransferred sense data should be interpreted as being zero.
  	 */
b80ca4f7e   FUJITA Tomonori   [SCSI] replace si...
947
  	memset(scmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
948
949
950
951
  }
  EXPORT_SYMBOL(scsi_eh_prep_cmnd);
  
  /**
3b729f764   Santosh Y   scsi: fix comment...
952
   * scsi_eh_restore_cmnd  - Restore a scsi command info as part of error recovery
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
953
   * @scmd:       SCSI command structure to restore
477e608c0   Bartlomiej Zolnierkiewicz   [SCSI] fix docume...
954
   * @ses:        saved information from a coresponding call to scsi_eh_prep_cmnd
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
955
   *
477e608c0   Bartlomiej Zolnierkiewicz   [SCSI] fix docume...
956
   * Undo any damage done by above scsi_eh_prep_cmnd().
dc8875e10   Randy Dunlap   [SCSI] docbook an...
957
   */
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
958
959
960
961
962
963
  void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
  {
  	/*
  	 * Restore original data
  	 */
  	scmd->cmd_len = ses->cmd_len;
64a87b244   Boaz Harrosh   [SCSI] Let scsi_c...
964
  	scmd->cmnd = ses->cmnd;
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
965
  	scmd->sc_data_direction = ses->data_direction;
30b0c37b2   Boaz Harrosh   [SCSI] implement ...
966
  	scmd->sdb = ses->sdb;
6f9a35e2d   Boaz Harrosh   [SCSI] bidirectio...
967
  	scmd->request->next_rq = ses->next_rq;
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
968
  	scmd->result = ses->result;
12265709a   Alan Stern   [SCSI] scsi_eh_pr...
969
  	scmd->underflow = ses->underflow;
db007fc5e   Martin K. Petersen   [SCSI] Command pr...
970
  	scmd->prot_op = ses->prot_op;
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
971
972
  }
  EXPORT_SYMBOL(scsi_eh_restore_cmnd);
631c228cd   Christoph Hellwig   [SCSI] hide EH ba...
973

e1c234685   Boaz Harrosh   [SCSI] scsi_error...
974
  /**
3b729f764   Santosh Y   scsi: fix comment...
975
   * scsi_send_eh_cmnd  - submit a scsi command as part of error recovery
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
976
977
978
979
980
981
982
983
984
985
986
   * @scmd:       SCSI command structure to hijack
   * @cmnd:       CDB to send
   * @cmnd_size:  size in bytes of @cmnd
   * @timeout:    timeout for this request
   * @sense_bytes: size of sense data to copy or 0
   *
   * This function is used to send a scsi command down to a target device
   * as part of the error recovery process. See also scsi_eh_prep_cmnd() above.
   *
   * Return value:
   *    SUCCESS or FAILED or NEEDS_RETRY
dc8875e10   Randy Dunlap   [SCSI] docbook an...
987
   */
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
988
989
990
991
992
993
  static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
  			     int cmnd_size, int timeout, unsigned sense_bytes)
  {
  	struct scsi_device *sdev = scmd->device;
  	struct Scsi_Host *shost = sdev->host;
  	DECLARE_COMPLETION_ONSTACK(done);
fc73648a5   Hannes Reinecke   [SCSI] Handle MLQ...
994
  	unsigned long timeleft = timeout;
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
995
  	struct scsi_eh_save ses;
fc73648a5   Hannes Reinecke   [SCSI] Handle MLQ...
996
  	const unsigned long stall_for = msecs_to_jiffies(100);
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
997
  	int rtn;
fc73648a5   Hannes Reinecke   [SCSI] Handle MLQ...
998
  retry:
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
999
  	scsi_eh_prep_cmnd(scmd, &ses, cmnd, cmnd_size, sense_bytes);
7dfdc9a52   Christoph Hellwig   [SCSI] use a comp...
1000
  	shost->eh_action = &done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1001

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1002
  	scsi_log_send(scmd);
f281233d3   Jeff Garzik   SCSI host lock pu...
1003
  	scmd->scsi_done = scsi_eh_done;
fc73648a5   Hannes Reinecke   [SCSI] Handle MLQ...
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
  	rtn = shost->hostt->queuecommand(shost, scmd);
  	if (rtn) {
  		if (timeleft > stall_for) {
  			scsi_eh_restore_cmnd(scmd, &ses);
  			timeleft -= stall_for;
  			msleep(jiffies_to_msecs(stall_for));
  			goto retry;
  		}
  		/* signal not to enter either branch of the if () below */
  		timeleft = 0;
  		rtn = NEEDS_RETRY;
  	} else {
  		timeleft = wait_for_completion_timeout(&done, timeout);
ac61d1955   Hannes Reinecke   scsi: set correct...
1017
  		rtn = SUCCESS;
fc73648a5   Hannes Reinecke   [SCSI] Handle MLQ...
1018
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019

f59114b7b   Tejun Heo   [PATCH] scsi: scs...
1020
  	shost->eh_action = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1021

fc73648a5   Hannes Reinecke   [SCSI] Handle MLQ...
1022
  	scsi_log_completion(scmd, rtn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023

91921e016   Hannes Reinecke   scsi: use dev_pri...
1024
1025
1026
  	SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
  			"%s: scmd: %p, timeleft: %ld
  ",
cadbd4a5e   Harvey Harrison   [SCSI] replace __...
1027
  			__func__, scmd, timeleft));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028
1029
  
  	/*
fc73648a5   Hannes Reinecke   [SCSI] Handle MLQ...
1030
1031
1032
1033
1034
1035
1036
  	 * If there is time left scsi_eh_done got called, and we will examine
  	 * the actual status codes to see whether the command actually did
  	 * complete normally, else if we have a zero return and no time left,
  	 * the command must still be pending, so abort it and return FAILED.
  	 * If we never actually managed to issue the command, because
  	 * ->queuecommand() kept returning non zero, use the rtn = FAILED
  	 * value above (so don't execute either branch of the if)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1037
  	 */
7dfdc9a52   Christoph Hellwig   [SCSI] use a comp...
1038
  	if (timeleft) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1039
  		rtn = scsi_eh_completed_normally(scmd);
91921e016   Hannes Reinecke   scsi: use dev_pri...
1040
1041
1042
  		SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
  			"%s: scsi_eh_completed_normally %x
  ", __func__, rtn));
7dfdc9a52   Christoph Hellwig   [SCSI] use a comp...
1043

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1044
1045
1046
1047
1048
  		switch (rtn) {
  		case SUCCESS:
  		case NEEDS_RETRY:
  		case FAILED:
  			break;
6e883b0e4   Hannes Reinecke   [SCSI] Retry ADD_...
1049
1050
1051
  		case ADD_TO_MLQUEUE:
  			rtn = NEEDS_RETRY;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1052
1053
1054
1055
  		default:
  			rtn = FAILED;
  			break;
  		}
fc73648a5   Hannes Reinecke   [SCSI] Handle MLQ...
1056
  	} else if (!rtn) {
292148f8b   Brian King   [SCSI] scsi_error...
1057
  		scsi_abort_eh_cmnd(scmd);
7dfdc9a52   Christoph Hellwig   [SCSI] use a comp...
1058
  		rtn = FAILED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1059
  	}
e1c234685   Boaz Harrosh   [SCSI] scsi_error...
1060
  	scsi_eh_restore_cmnd(scmd, &ses);
18a4d0a22   Martin K. Petersen   [SCSI] Handle dis...
1061

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
  	return rtn;
  }
  
  /**
   * scsi_request_sense - Request sense data from a particular target.
   * @scmd:	SCSI cmd for request sense.
   *
   * Notes:
   *    Some hosts automatically obtain this information, others require
   *    that we obtain it on our own. This function will *not* return until
   *    the command either times out, or it completes.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
1073
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1074
1075
  static int scsi_request_sense(struct scsi_cmnd *scmd)
  {
0816c9251   Martin K. Petersen   [SCSI] Allow erro...
1076
  	return scsi_send_eh_cmnd(scmd, NULL, 0, scmd->device->eh_timeout, ~0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1077
  }
2451079bc   James Bottomley   [SCSI] Fix errati...
1078
1079
1080
1081
1082
1083
1084
1085
1086
  static int scsi_eh_action(struct scsi_cmnd *scmd, int rtn)
  {
  	if (scmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
  		struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd);
  		if (sdrv->eh_action)
  			rtn = sdrv->eh_action(scmd, rtn);
  	}
  	return rtn;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1087
1088
1089
1090
1091
1092
1093
1094
  /**
   * scsi_eh_finish_cmd - Handle a cmd that eh is finished with.
   * @scmd:	Original SCSI cmd that eh has finished.
   * @done_q:	Queue for processed commands.
   *
   * Notes:
   *    We don't want to use the normal command completion while we are are
   *    still handling errors - it may cause other commands to be queued,
eb44820c2   Rob Landley   [SCSI] Add Docume...
1095
   *    and that would disturb what we are doing.  Thus we really want to
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1096
1097
   *    keep a list of pending commands for final completion, and once we
   *    are ready to leave error handling we handle completion for real.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
1098
   */
041c5fc33   Tejun Heo   [PATCH] SCSI: exp...
1099
  void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1100
1101
  {
  	scmd->device->host->host_failed--;
3111b0d16   Christoph Hellwig   [SCSI] remove scs...
1102
  	scmd->eh_eflags = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1103
1104
  	list_move_tail(&scmd->eh_entry, done_q);
  }
041c5fc33   Tejun Heo   [PATCH] SCSI: exp...
1105
  EXPORT_SYMBOL(scsi_eh_finish_cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1106
1107
1108
1109
  
  /**
   * scsi_eh_get_sense - Get device sense data.
   * @work_q:	Queue of commands to process.
eb44820c2   Rob Landley   [SCSI] Add Docume...
1110
   * @done_q:	Queue of processed commands.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1111
1112
1113
   *
   * Description:
   *    See if we need to request sense information.  if so, then get it
0bf8c8697   Jesper Juhl   Reduce sequential...
1114
   *    now, so we have a better idea of what to do.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1115
1116
1117
   *
   * Notes:
   *    This has the unfortunate side effect that if a shost adapter does
eb44820c2   Rob Landley   [SCSI] Add Docume...
1118
   *    not automatically request sense information, we end up shutting
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1119
1120
1121
1122
1123
1124
1125
   *    it down before we request it.
   *
   *    All drivers should request sense information internally these days,
   *    so for now all I have to say is tough noogies if you end up in here.
   *
   *    XXX: Long term this code should go away, but that needs an audit of
   *         all LLDDs first.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
1126
   */
dca84e469   Darrick J. Wong   [SCSI] scsi_error...
1127
1128
  int scsi_eh_get_sense(struct list_head *work_q,
  		      struct list_head *done_q)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1129
  {
937abeaad   Christoph Hellwig   [SCSI] use list_f...
1130
  	struct scsi_cmnd *scmd, *next;
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1131
  	struct Scsi_Host *shost;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1132
  	int rtn;
937abeaad   Christoph Hellwig   [SCSI] use list_f...
1133
  	list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
3111b0d16   Christoph Hellwig   [SCSI] remove scs...
1134
  		if ((scmd->eh_eflags & SCSI_EH_CANCEL_CMD) ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1135
1136
  		    SCSI_SENSE_VALID(scmd))
  			continue;
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1137
  		shost = scmd->device->host;
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1138
  		if (scsi_host_eh_past_deadline(shost)) {
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1139
1140
1141
1142
1143
1144
1145
  			SCSI_LOG_ERROR_RECOVERY(3,
  				shost_printk(KERN_INFO, shost,
  					    "skip %s, past eh deadline
  ",
  					     __func__));
  			break;
  		}
d555a2abf   James Bottomley   [SCSI] Fix spurio...
1146
1147
1148
1149
1150
1151
1152
1153
  		if (status_byte(scmd->result) != CHECK_CONDITION)
  			/*
  			 * don't request sense if there's no check condition
  			 * status because the error we're processing isn't one
  			 * that has a sense code (and some devices get
  			 * confused by sense requests out of the blue)
  			 */
  			continue;
3bf743e7c   Jeff Garzik   [SCSI] use {sdev,...
1154
1155
1156
1157
  		SCSI_LOG_ERROR_RECOVERY(2, scmd_printk(KERN_INFO, scmd,
  						  "%s: requesting sense
  ",
  						  current->comm));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1158
1159
1160
  		rtn = scsi_request_sense(scmd);
  		if (rtn != SUCCESS)
  			continue;
91921e016   Hannes Reinecke   scsi: use dev_pri...
1161
1162
1163
1164
  		SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
  			"sense requested for %p result %x
  ",
  			scmd, scmd->result));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
  		SCSI_LOG_ERROR_RECOVERY(3, scsi_print_sense("bh", scmd));
  
  		rtn = scsi_decide_disposition(scmd);
  
  		/*
  		 * if the result was normal, then just pass it along to the
  		 * upper level.
  		 */
  		if (rtn == SUCCESS)
  			/* we don't want this command reissued, just
  			 * finished with the sense data, so set
  			 * retries to the max allowed to ensure it
  			 * won't get reissued */
  			scmd->retries = scmd->allowed;
  		else if (rtn != NEEDS_RETRY)
  			continue;
  
  		scsi_eh_finish_cmd(scmd, done_q);
  	}
  
  	return list_empty(work_q);
  }
dca84e469   Darrick J. Wong   [SCSI] scsi_error...
1187
  EXPORT_SYMBOL_GPL(scsi_eh_get_sense);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1188
1189
  
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1190
   * scsi_eh_tur - Send TUR to device.
eb44820c2   Rob Landley   [SCSI] Add Docume...
1191
   * @scmd:	&scsi_cmnd to send TUR
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1192
1193
1194
   *
   * Return value:
   *    0 - Device is ready. 1 - Device NOT ready.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
1195
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1196
1197
1198
1199
1200
1201
  static int scsi_eh_tur(struct scsi_cmnd *scmd)
  {
  	static unsigned char tur_command[6] = {TEST_UNIT_READY, 0, 0, 0, 0, 0};
  	int retry_cnt = 1, rtn;
  
  retry_tur:
0816c9251   Martin K. Petersen   [SCSI] Allow erro...
1202
1203
  	rtn = scsi_send_eh_cmnd(scmd, tur_command, 6,
  				scmd->device->eh_timeout, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1204

91921e016   Hannes Reinecke   scsi: use dev_pri...
1205
1206
1207
  	SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
  		"%s: scmd %p rtn %x
  ", __func__, scmd, rtn));
631c228cd   Christoph Hellwig   [SCSI] hide EH ba...
1208
1209
1210
  
  	switch (rtn) {
  	case NEEDS_RETRY:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1211
1212
  		if (retry_cnt--)
  			goto retry_tur;
631c228cd   Christoph Hellwig   [SCSI] hide EH ba...
1213
1214
  		/*FALLTHRU*/
  	case SUCCESS:
e47373ec1   Alan Stern   [SCSI] return suc...
1215
  		return 0;
631c228cd   Christoph Hellwig   [SCSI] hide EH ba...
1216
1217
  	default:
  		return 1;
e47373ec1   Alan Stern   [SCSI] return suc...
1218
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1219
1220
1221
  }
  
  /**
3eef6257d   David Jeffery   [SCSI] Reduce err...
1222
1223
   * scsi_eh_test_devices - check if devices are responding from error recovery.
   * @cmd_list:	scsi commands in error recovery.
74cf298fe   Randy Dunlap   scsi: fix various...
1224
1225
1226
   * @work_q:	queue for commands which still need more error recovery
   * @done_q:	queue for commands which are finished
   * @try_stu:	boolean on if a STU command should be tried in addition to TUR.
3eef6257d   David Jeffery   [SCSI] Reduce err...
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
   *
   * Decription:
   *    Tests if devices are in a working state.  Commands to devices now in
   *    a working state are sent to the done_q while commands to devices which
   *    are still failing to respond are returned to the work_q for more
   *    processing.
   **/
  static int scsi_eh_test_devices(struct list_head *cmd_list,
  				struct list_head *work_q,
  				struct list_head *done_q, int try_stu)
  {
  	struct scsi_cmnd *scmd, *next;
  	struct scsi_device *sdev;
  	int finish_cmds;
  
  	while (!list_empty(cmd_list)) {
  		scmd = list_entry(cmd_list->next, struct scsi_cmnd, eh_entry);
  		sdev = scmd->device;
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1245
  		if (!try_stu) {
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1246
1247
1248
  			if (scsi_host_eh_past_deadline(sdev->host)) {
  				/* Push items back onto work_q */
  				list_splice_init(cmd_list, work_q);
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1249
1250
1251
1252
1253
1254
  				SCSI_LOG_ERROR_RECOVERY(3,
  					shost_printk(KERN_INFO, sdev->host,
  						     "skip %s, past eh deadline",
  						     __func__));
  				break;
  			}
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1255
  		}
3eef6257d   David Jeffery   [SCSI] Reduce err...
1256
1257
1258
1259
1260
1261
1262
  		finish_cmds = !scsi_device_online(scmd->device) ||
  			(try_stu && !scsi_eh_try_stu(scmd) &&
  			 !scsi_eh_tur(scmd)) ||
  			!scsi_eh_tur(scmd);
  
  		list_for_each_entry_safe(scmd, next, cmd_list, eh_entry)
  			if (scmd->device == sdev) {
2451079bc   James Bottomley   [SCSI] Fix errati...
1263
1264
1265
  				if (finish_cmds &&
  				    (try_stu ||
  				     scsi_eh_action(scmd, SUCCESS) == SUCCESS))
3eef6257d   David Jeffery   [SCSI] Reduce err...
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
  					scsi_eh_finish_cmd(scmd, done_q);
  				else
  					list_move_tail(&scmd->eh_entry, work_q);
  			}
  	}
  	return list_empty(work_q);
  }
  
  
  /**
eb44820c2   Rob Landley   [SCSI] Add Docume...
1276
1277
1278
   * scsi_eh_abort_cmds - abort pending commands.
   * @work_q:	&list_head for pending commands.
   * @done_q:	&list_head for processed commands.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1279
1280
1281
   *
   * Decription:
   *    Try and see whether or not it makes sense to try and abort the
eb44820c2   Rob Landley   [SCSI] Add Docume...
1282
1283
   *    running command.  This only works out to be the case if we have one
   *    command that has timed out.  If the command simply failed, it makes
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1284
1285
   *    no sense to try and abort the command, since as far as the shost
   *    adapter is concerned, it isn't running.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
1286
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1287
1288
1289
  static int scsi_eh_abort_cmds(struct list_head *work_q,
  			      struct list_head *done_q)
  {
937abeaad   Christoph Hellwig   [SCSI] use list_f...
1290
  	struct scsi_cmnd *scmd, *next;
3eef6257d   David Jeffery   [SCSI] Reduce err...
1291
  	LIST_HEAD(check_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1292
  	int rtn;
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1293
  	struct Scsi_Host *shost;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1294

937abeaad   Christoph Hellwig   [SCSI] use list_f...
1295
  	list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
3111b0d16   Christoph Hellwig   [SCSI] remove scs...
1296
  		if (!(scmd->eh_eflags & SCSI_EH_CANCEL_CMD))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1297
  			continue;
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1298
  		shost = scmd->device->host;
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1299
  		if (scsi_host_eh_past_deadline(shost)) {
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1300
1301
1302
1303
1304
1305
1306
1307
  			list_splice_init(&check_list, work_q);
  			SCSI_LOG_ERROR_RECOVERY(3,
  				shost_printk(KERN_INFO, shost,
  					    "skip %s, past eh deadline
  ",
  					     __func__));
  			return list_empty(work_q);
  		}
91921e016   Hannes Reinecke   scsi: use dev_pri...
1308
1309
1310
1311
1312
  		SCSI_LOG_ERROR_RECOVERY(3,
  			shost_printk(KERN_INFO, shost,
  				     "%s: aborting cmd: 0x%p
  ",
  				     current->comm, scmd));
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1313
  		rtn = scsi_try_to_abort_cmd(shost->hostt, scmd);
6fd046f96   Hannes Reinecke   [SCSI] scsi_error...
1314
  		if (rtn == FAILED) {
91921e016   Hannes Reinecke   scsi: use dev_pri...
1315
1316
1317
1318
1319
  			SCSI_LOG_ERROR_RECOVERY(3,
  				shost_printk(KERN_INFO, shost,
  					     "%s: aborting cmd failed: 0x%p
  ",
  					     current->comm, scmd));
6fd046f96   Hannes Reinecke   [SCSI] scsi_error...
1320
1321
1322
1323
1324
1325
1326
1327
  			list_splice_init(&check_list, work_q);
  			return list_empty(work_q);
  		}
  		scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD;
  		if (rtn == FAST_IO_FAIL)
  			scsi_eh_finish_cmd(scmd, done_q);
  		else
  			list_move_tail(&scmd->eh_entry, &check_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1328
  	}
3eef6257d   David Jeffery   [SCSI] Reduce err...
1329
  	return scsi_eh_test_devices(&check_list, work_q, done_q, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1330
1331
1332
  }
  
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1333
   * scsi_eh_try_stu - Send START_UNIT to device.
eb44820c2   Rob Landley   [SCSI] Add Docume...
1334
   * @scmd:	&scsi_cmnd to send START_UNIT
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1335
1336
1337
   *
   * Return value:
   *    0 - Device is ready. 1 - Device NOT ready.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
1338
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1339
1340
1341
  static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
  {
  	static unsigned char stu_command[6] = {START_STOP, 0, 0, 0, 1, 0};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1342

631c228cd   Christoph Hellwig   [SCSI] hide EH ba...
1343
  	if (scmd->device->allow_restart) {
ed773e664   Brian King   [SCSI] scsi_error...
1344
1345
1346
  		int i, rtn = NEEDS_RETRY;
  
  		for (i = 0; rtn == NEEDS_RETRY && i < 2; i++)
9728c0814   James Bottomley   [SCSI] make scsi_...
1347
  			rtn = scsi_send_eh_cmnd(scmd, stu_command, 6, scmd->device->request_queue->rq_timeout, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1348

631c228cd   Christoph Hellwig   [SCSI] hide EH ba...
1349
1350
1351
  		if (rtn == SUCCESS)
  			return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1352

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353
1354
1355
1356
1357
  	return 1;
  }
  
   /**
   * scsi_eh_stu - send START_UNIT if needed
eb44820c2   Rob Landley   [SCSI] Add Docume...
1358
   * @shost:	&scsi host being recovered.
74cf298fe   Randy Dunlap   scsi: fix various...
1359
   * @work_q:	&list_head for pending commands.
eb44820c2   Rob Landley   [SCSI] Add Docume...
1360
   * @done_q:	&list_head for processed commands.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1361
1362
1363
   *
   * Notes:
   *    If commands are failing due to not ready, initializing command required,
0bf8c8697   Jesper Juhl   Reduce sequential...
1364
   *	try revalidating the device, which will end up sending a start unit.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
1365
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1366
1367
1368
1369
  static int scsi_eh_stu(struct Scsi_Host *shost,
  			      struct list_head *work_q,
  			      struct list_head *done_q)
  {
937abeaad   Christoph Hellwig   [SCSI] use list_f...
1370
  	struct scsi_cmnd *scmd, *stu_scmd, *next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1371
1372
1373
  	struct scsi_device *sdev;
  
  	shost_for_each_device(sdev, shost) {
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1374
  		if (scsi_host_eh_past_deadline(shost)) {
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1375
1376
1377
1378
1379
1380
1381
  			SCSI_LOG_ERROR_RECOVERY(3,
  				shost_printk(KERN_INFO, shost,
  					    "skip %s, past eh deadline
  ",
  					     __func__));
  			break;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
  		stu_scmd = NULL;
  		list_for_each_entry(scmd, work_q, eh_entry)
  			if (scmd->device == sdev && SCSI_SENSE_VALID(scmd) &&
  			    scsi_check_sense(scmd) == FAILED ) {
  				stu_scmd = scmd;
  				break;
  			}
  
  		if (!stu_scmd)
  			continue;
91921e016   Hannes Reinecke   scsi: use dev_pri...
1392
1393
1394
1395
1396
  		SCSI_LOG_ERROR_RECOVERY(3,
  			shost_printk(KERN_INFO, shost,
  				     "%s: Sending START_UNIT to sdev: 0x%p
  ",
  				     current->comm, sdev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1397
1398
1399
1400
  
  		if (!scsi_eh_try_stu(stu_scmd)) {
  			if (!scsi_device_online(sdev) ||
  			    !scsi_eh_tur(stu_scmd)) {
937abeaad   Christoph Hellwig   [SCSI] use list_f...
1401
1402
  				list_for_each_entry_safe(scmd, next,
  							  work_q, eh_entry) {
2451079bc   James Bottomley   [SCSI] Fix errati...
1403
1404
  					if (scmd->device == sdev &&
  					    scsi_eh_action(scmd, SUCCESS) == SUCCESS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1405
1406
1407
1408
1409
  						scsi_eh_finish_cmd(scmd, done_q);
  				}
  			}
  		} else {
  			SCSI_LOG_ERROR_RECOVERY(3,
91921e016   Hannes Reinecke   scsi: use dev_pri...
1410
1411
1412
1413
  				shost_printk(KERN_INFO, shost,
  					     "%s: START_UNIT failed to sdev:"
  					     " 0x%p
  ", current->comm, sdev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
  		}
  	}
  
  	return list_empty(work_q);
  }
  
  
  /**
   * scsi_eh_bus_device_reset - send bdr if needed
   * @shost:	scsi host being recovered.
74cf298fe   Randy Dunlap   scsi: fix various...
1424
   * @work_q:	&list_head for pending commands.
eb44820c2   Rob Landley   [SCSI] Add Docume...
1425
   * @done_q:	&list_head for processed commands.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1426
1427
   *
   * Notes:
eb44820c2   Rob Landley   [SCSI] Add Docume...
1428
   *    Try a bus device reset.  Still, look to see whether we have multiple
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1429
1430
   *    devices that are jammed or not - if we have multiple devices, it
   *    makes no sense to try bus_device_reset - we really would need to try
0bf8c8697   Jesper Juhl   Reduce sequential...
1431
   *    a bus_reset instead.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
1432
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1433
1434
1435
1436
  static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
  				    struct list_head *work_q,
  				    struct list_head *done_q)
  {
937abeaad   Christoph Hellwig   [SCSI] use list_f...
1437
  	struct scsi_cmnd *scmd, *bdr_scmd, *next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1438
1439
1440
1441
  	struct scsi_device *sdev;
  	int rtn;
  
  	shost_for_each_device(sdev, shost) {
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1442
  		if (scsi_host_eh_past_deadline(shost)) {
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1443
1444
1445
1446
1447
1448
1449
  			SCSI_LOG_ERROR_RECOVERY(3,
  				shost_printk(KERN_INFO, shost,
  					    "skip %s, past eh deadline
  ",
  					     __func__));
  			break;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1450
1451
1452
1453
1454
1455
1456
1457
1458
  		bdr_scmd = NULL;
  		list_for_each_entry(scmd, work_q, eh_entry)
  			if (scmd->device == sdev) {
  				bdr_scmd = scmd;
  				break;
  			}
  
  		if (!bdr_scmd)
  			continue;
91921e016   Hannes Reinecke   scsi: use dev_pri...
1459
1460
1461
1462
1463
  		SCSI_LOG_ERROR_RECOVERY(3,
  			shost_printk(KERN_INFO, shost,
  				     "%s: Sending BDR sdev: 0x%p
  ",
  				     current->comm, sdev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1464
  		rtn = scsi_try_bus_device_reset(bdr_scmd);
2f2eb5876   Christof Schmitt   [SCSI] Allow FC ...
1465
  		if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1466
  			if (!scsi_device_online(sdev) ||
2f2eb5876   Christof Schmitt   [SCSI] Allow FC ...
1467
  			    rtn == FAST_IO_FAIL ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1468
  			    !scsi_eh_tur(bdr_scmd)) {
937abeaad   Christoph Hellwig   [SCSI] use list_f...
1469
1470
  				list_for_each_entry_safe(scmd, next,
  							 work_q, eh_entry) {
2451079bc   James Bottomley   [SCSI] Fix errati...
1471
1472
  					if (scmd->device == sdev &&
  					    scsi_eh_action(scmd, rtn) != FAILED)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1473
1474
1475
1476
1477
  						scsi_eh_finish_cmd(scmd,
  								   done_q);
  				}
  			}
  		} else {
91921e016   Hannes Reinecke   scsi: use dev_pri...
1478
1479
1480
1481
1482
  			SCSI_LOG_ERROR_RECOVERY(3,
  				shost_printk(KERN_INFO, shost,
  					     "%s: BDR failed sdev: 0x%p
  ",
  					     current->comm, sdev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1483
1484
1485
1486
1487
1488
1489
  		}
  	}
  
  	return list_empty(work_q);
  }
  
  /**
30bd7df8c   Mike Christie   [SCSI] scsi_error...
1490
1491
   * scsi_eh_target_reset - send target reset if needed
   * @shost:	scsi host being recovered.
74cf298fe   Randy Dunlap   scsi: fix various...
1492
   * @work_q:	&list_head for pending commands.
30bd7df8c   Mike Christie   [SCSI] scsi_error...
1493
1494
1495
1496
1497
1498
1499
1500
1501
   * @done_q:	&list_head for processed commands.
   *
   * Notes:
   *    Try a target reset.
   */
  static int scsi_eh_target_reset(struct Scsi_Host *shost,
  				struct list_head *work_q,
  				struct list_head *done_q)
  {
98db51957   James Bottomley   [SCSI] fix id com...
1502
  	LIST_HEAD(tmp_list);
3eef6257d   David Jeffery   [SCSI] Reduce err...
1503
  	LIST_HEAD(check_list);
30bd7df8c   Mike Christie   [SCSI] scsi_error...
1504

98db51957   James Bottomley   [SCSI] fix id com...
1505
1506
1507
1508
1509
1510
  	list_splice_init(work_q, &tmp_list);
  
  	while (!list_empty(&tmp_list)) {
  		struct scsi_cmnd *next, *scmd;
  		int rtn;
  		unsigned int id;
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1511

b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1512
  		if (scsi_host_eh_past_deadline(shost)) {
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
  			/* push back on work queue for further processing */
  			list_splice_init(&check_list, work_q);
  			list_splice_init(&tmp_list, work_q);
  			SCSI_LOG_ERROR_RECOVERY(3,
  				shost_printk(KERN_INFO, shost,
  					    "skip %s, past eh deadline
  ",
  					     __func__));
  			return list_empty(work_q);
  		}
98db51957   James Bottomley   [SCSI] fix id com...
1523
1524
1525
  
  		scmd = list_entry(tmp_list.next, struct scsi_cmnd, eh_entry);
  		id = scmd_id(scmd);
30bd7df8c   Mike Christie   [SCSI] scsi_error...
1526

91921e016   Hannes Reinecke   scsi: use dev_pri...
1527
1528
1529
1530
1531
  		SCSI_LOG_ERROR_RECOVERY(3,
  			shost_printk(KERN_INFO, shost,
  				     "%s: Sending target reset to target %d
  ",
  				     current->comm, id));
98db51957   James Bottomley   [SCSI] fix id com...
1532
1533
  		rtn = scsi_try_target_reset(scmd);
  		if (rtn != SUCCESS && rtn != FAST_IO_FAIL)
91921e016   Hannes Reinecke   scsi: use dev_pri...
1534
1535
1536
1537
1538
1539
  			SCSI_LOG_ERROR_RECOVERY(3,
  				shost_printk(KERN_INFO, shost,
  					     "%s: Target reset failed"
  					     " target: %d
  ",
  					     current->comm, id));
98db51957   James Bottomley   [SCSI] fix id com...
1540
1541
1542
  		list_for_each_entry_safe(scmd, next, &tmp_list, eh_entry) {
  			if (scmd_id(scmd) != id)
  				continue;
3eef6257d   David Jeffery   [SCSI] Reduce err...
1543
1544
1545
  			if (rtn == SUCCESS)
  				list_move_tail(&scmd->eh_entry, &check_list);
  			else if (rtn == FAST_IO_FAIL)
98db51957   James Bottomley   [SCSI] fix id com...
1546
1547
1548
1549
1550
1551
  				scsi_eh_finish_cmd(scmd, done_q);
  			else
  				/* push back on work queue for further processing */
  				list_move(&scmd->eh_entry, work_q);
  		}
  	}
30bd7df8c   Mike Christie   [SCSI] scsi_error...
1552

3eef6257d   David Jeffery   [SCSI] Reduce err...
1553
  	return scsi_eh_test_devices(&check_list, work_q, done_q, 0);
30bd7df8c   Mike Christie   [SCSI] scsi_error...
1554
1555
1556
  }
  
  /**
0bf8c8697   Jesper Juhl   Reduce sequential...
1557
   * scsi_eh_bus_reset - send a bus reset
eb44820c2   Rob Landley   [SCSI] Add Docume...
1558
   * @shost:	&scsi host being recovered.
74cf298fe   Randy Dunlap   scsi: fix various...
1559
   * @work_q:	&list_head for pending commands.
eb44820c2   Rob Landley   [SCSI] Add Docume...
1560
   * @done_q:	&list_head for processed commands.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
1561
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1562
1563
1564
1565
  static int scsi_eh_bus_reset(struct Scsi_Host *shost,
  			     struct list_head *work_q,
  			     struct list_head *done_q)
  {
937abeaad   Christoph Hellwig   [SCSI] use list_f...
1566
  	struct scsi_cmnd *scmd, *chan_scmd, *next;
3eef6257d   David Jeffery   [SCSI] Reduce err...
1567
  	LIST_HEAD(check_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1568
1569
1570
1571
1572
1573
1574
  	unsigned int channel;
  	int rtn;
  
  	/*
  	 * we really want to loop over the various channels, and do this on
  	 * a channel by channel basis.  we should also check to see if any
  	 * of the failed commands are on soft_reset devices, and if so, skip
0bf8c8697   Jesper Juhl   Reduce sequential...
1575
  	 * the reset.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1576
1577
1578
  	 */
  
  	for (channel = 0; channel <= shost->max_channel; channel++) {
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1579
  		if (scsi_host_eh_past_deadline(shost)) {
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1580
1581
1582
1583
1584
1585
1586
1587
  			list_splice_init(&check_list, work_q);
  			SCSI_LOG_ERROR_RECOVERY(3,
  				shost_printk(KERN_INFO, shost,
  					    "skip %s, past eh deadline
  ",
  					     __func__));
  			return list_empty(work_q);
  		}
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
1588

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1589
1590
  		chan_scmd = NULL;
  		list_for_each_entry(scmd, work_q, eh_entry) {
422c0d61d   Jeff Garzik   [SCSI] use scmd_i...
1591
  			if (channel == scmd_channel(scmd)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
  				chan_scmd = scmd;
  				break;
  				/*
  				 * FIXME add back in some support for
  				 * soft_reset devices.
  				 */
  			}
  		}
  
  		if (!chan_scmd)
  			continue;
91921e016   Hannes Reinecke   scsi: use dev_pri...
1603
1604
1605
1606
1607
  		SCSI_LOG_ERROR_RECOVERY(3,
  			shost_printk(KERN_INFO, shost,
  				     "%s: Sending BRST chan: %d
  ",
  				     current->comm, channel));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1608
  		rtn = scsi_try_bus_reset(chan_scmd);
2f2eb5876   Christof Schmitt   [SCSI] Allow FC ...
1609
  		if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
937abeaad   Christoph Hellwig   [SCSI] use list_f...
1610
  			list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
3eef6257d   David Jeffery   [SCSI] Reduce err...
1611
1612
  				if (channel == scmd_channel(scmd)) {
  					if (rtn == FAST_IO_FAIL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1613
1614
  						scsi_eh_finish_cmd(scmd,
  								   done_q);
3eef6257d   David Jeffery   [SCSI] Reduce err...
1615
1616
1617
1618
  					else
  						list_move_tail(&scmd->eh_entry,
  							       &check_list);
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1619
1620
  			}
  		} else {
91921e016   Hannes Reinecke   scsi: use dev_pri...
1621
1622
1623
1624
1625
  			SCSI_LOG_ERROR_RECOVERY(3,
  				shost_printk(KERN_INFO, shost,
  					     "%s: BRST failed chan: %d
  ",
  					     current->comm, channel));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1626
1627
  		}
  	}
3eef6257d   David Jeffery   [SCSI] Reduce err...
1628
  	return scsi_eh_test_devices(&check_list, work_q, done_q, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1629
1630
1631
  }
  
  /**
0bf8c8697   Jesper Juhl   Reduce sequential...
1632
   * scsi_eh_host_reset - send a host reset
74cf298fe   Randy Dunlap   scsi: fix various...
1633
1634
1635
   * @shost:	host to be reset.
   * @work_q:	&list_head for pending commands.
   * @done_q:	&list_head for processed commands.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
1636
   */
91921e016   Hannes Reinecke   scsi: use dev_pri...
1637
1638
  static int scsi_eh_host_reset(struct Scsi_Host *shost,
  			      struct list_head *work_q,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1639
1640
  			      struct list_head *done_q)
  {
937abeaad   Christoph Hellwig   [SCSI] use list_f...
1641
  	struct scsi_cmnd *scmd, *next;
3eef6257d   David Jeffery   [SCSI] Reduce err...
1642
  	LIST_HEAD(check_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1643
  	int rtn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1644
1645
1646
1647
  
  	if (!list_empty(work_q)) {
  		scmd = list_entry(work_q->next,
  				  struct scsi_cmnd, eh_entry);
91921e016   Hannes Reinecke   scsi: use dev_pri...
1648
1649
1650
1651
1652
  		SCSI_LOG_ERROR_RECOVERY(3,
  			shost_printk(KERN_INFO, shost,
  				     "%s: Sending HRST
  ",
  				     current->comm));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1653
1654
  
  		rtn = scsi_try_host_reset(scmd);
3eef6257d   David Jeffery   [SCSI] Reduce err...
1655
1656
1657
  		if (rtn == SUCCESS) {
  			list_splice_init(work_q, &check_list);
  		} else if (rtn == FAST_IO_FAIL) {
937abeaad   Christoph Hellwig   [SCSI] use list_f...
1658
  			list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1659
1660
1661
  					scsi_eh_finish_cmd(scmd, done_q);
  			}
  		} else {
91921e016   Hannes Reinecke   scsi: use dev_pri...
1662
1663
1664
1665
1666
  			SCSI_LOG_ERROR_RECOVERY(3,
  				shost_printk(KERN_INFO, shost,
  					     "%s: HRST failed
  ",
  					     current->comm));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1667
1668
  		}
  	}
3eef6257d   David Jeffery   [SCSI] Reduce err...
1669
  	return scsi_eh_test_devices(&check_list, work_q, done_q, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1670
1671
1672
1673
  }
  
  /**
   * scsi_eh_offline_sdevs - offline scsi devices that fail to recover
74cf298fe   Randy Dunlap   scsi: fix various...
1674
1675
   * @work_q:	&list_head for pending commands.
   * @done_q:	&list_head for processed commands.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
1676
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1677
1678
1679
  static void scsi_eh_offline_sdevs(struct list_head *work_q,
  				  struct list_head *done_q)
  {
937abeaad   Christoph Hellwig   [SCSI] use list_f...
1680
  	struct scsi_cmnd *scmd, *next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1681

937abeaad   Christoph Hellwig   [SCSI] use list_f...
1682
  	list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
31765d7d3   Matthew Wilcox   [SCSI] Improve er...
1683
1684
1685
  		sdev_printk(KERN_INFO, scmd->device, "Device offlined - "
  			    "not ready after error recovery
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1686
  		scsi_device_set_state(scmd->device, SDEV_OFFLINE);
3111b0d16   Christoph Hellwig   [SCSI] remove scs...
1687
  		if (scmd->eh_eflags & SCSI_EH_CANCEL_CMD) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
  			/*
  			 * FIXME: Handle lost cmds.
  			 */
  		}
  		scsi_eh_finish_cmd(scmd, done_q);
  	}
  	return;
  }
  
  /**
e494f6a72   Hannes Reinecke   [SCSI] improved e...
1698
   * scsi_noretry_cmd - determine if command should be failed fast
4a27446f3   Mike Christie   [SCSI] modify scs...
1699
1700
1701
1702
1703
1704
1705
   * @scmd:	SCSI cmd to examine.
   */
  int scsi_noretry_cmd(struct scsi_cmnd *scmd)
  {
  	switch (host_byte(scmd->result)) {
  	case DID_OK:
  		break;
e494f6a72   Hannes Reinecke   [SCSI] improved e...
1706
1707
  	case DID_TIME_OUT:
  		goto check_type;
4a27446f3   Mike Christie   [SCSI] modify scs...
1708
  	case DID_BUS_BUSY:
33659ebba   Christoph Hellwig   block: remove wra...
1709
  		return (scmd->request->cmd_flags & REQ_FAILFAST_TRANSPORT);
4a27446f3   Mike Christie   [SCSI] modify scs...
1710
  	case DID_PARITY:
33659ebba   Christoph Hellwig   block: remove wra...
1711
  		return (scmd->request->cmd_flags & REQ_FAILFAST_DEV);
4a27446f3   Mike Christie   [SCSI] modify scs...
1712
1713
1714
1715
1716
1717
  	case DID_ERROR:
  		if (msg_byte(scmd->result) == COMMAND_COMPLETE &&
  		    status_byte(scmd->result) == RESERVATION_CONFLICT)
  			return 0;
  		/* fall through */
  	case DID_SOFT_ERROR:
33659ebba   Christoph Hellwig   block: remove wra...
1718
  		return (scmd->request->cmd_flags & REQ_FAILFAST_DRIVER);
4a27446f3   Mike Christie   [SCSI] modify scs...
1719
  	}
e494f6a72   Hannes Reinecke   [SCSI] improved e...
1720
1721
  	if (status_byte(scmd->result) != CHECK_CONDITION)
  		return 0;
4a27446f3   Mike Christie   [SCSI] modify scs...
1722

e494f6a72   Hannes Reinecke   [SCSI] improved e...
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
  check_type:
  	/*
  	 * assume caller has checked sense and determined
  	 * the check condition was retryable.
  	 */
  	if (scmd->request->cmd_flags & REQ_FAILFAST_DEV ||
  	    scmd->request->cmd_type == REQ_TYPE_BLOCK_PC)
  		return 1;
  	else
  		return 0;
4a27446f3   Mike Christie   [SCSI] modify scs...
1733
1734
1735
  }
  
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
   * scsi_decide_disposition - Disposition a cmd on return from LLD.
   * @scmd:	SCSI cmd to examine.
   *
   * Notes:
   *    This is *only* called when we are examining the status after sending
   *    out the actual data command.  any commands that are queued for error
   *    recovery (e.g. test_unit_ready) do *not* come through here.
   *
   *    When this routine returns failed, it means the error handler thread
   *    is woken.  In cases where the error code indicates an error that
   *    doesn't require the error handler read (i.e. we don't need to
   *    abort/reset), this function should return SUCCESS.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
1748
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1749
1750
1751
1752
1753
1754
1755
1756
1757
  int scsi_decide_disposition(struct scsi_cmnd *scmd)
  {
  	int rtn;
  
  	/*
  	 * if the device is offline, then we clearly just pass the result back
  	 * up to the top level.
  	 */
  	if (!scsi_device_online(scmd->device)) {
91921e016   Hannes Reinecke   scsi: use dev_pri...
1758
1759
1760
  		SCSI_LOG_ERROR_RECOVERY(5, scmd_printk(KERN_INFO, scmd,
  			"%s: device offline - report as SUCCESS
  ", __func__));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
  		return SUCCESS;
  	}
  
  	/*
  	 * first check the host byte, to see if there is anything in there
  	 * that would indicate what we need to do.
  	 */
  	switch (host_byte(scmd->result)) {
  	case DID_PASSTHROUGH:
  		/*
  		 * no matter what, pass this through to the upper layer.
  		 * nuke this special code so that it looks like we are saying
  		 * did_ok.
  		 */
  		scmd->result &= 0xff00ffff;
  		return SUCCESS;
  	case DID_OK:
  		/*
  		 * looks good.  drop through, and check the next byte.
  		 */
  		break;
e494f6a72   Hannes Reinecke   [SCSI] improved e...
1782
1783
  	case DID_ABORT:
  		if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) {
8922a9089   Ulrich Obergfell   scsi_error: fix i...
1784
  			set_host_byte(scmd, DID_TIME_OUT);
e494f6a72   Hannes Reinecke   [SCSI] improved e...
1785
1786
  			return SUCCESS;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1787
1788
  	case DID_NO_CONNECT:
  	case DID_BAD_TARGET:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1789
1790
1791
1792
1793
1794
1795
1796
  		/*
  		 * note - this means that we just report the status back
  		 * to the top level driver, not that we actually think
  		 * that it indicates SUCCESS.
  		 */
  		return SUCCESS;
  		/*
  		 * when the low level driver returns did_soft_error,
0bf8c8697   Jesper Juhl   Reduce sequential...
1797
  		 * it is responsible for keeping an internal retry counter
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
  		 * in order to avoid endless loops (db)
  		 *
  		 * actually this is a bug in this function here.  we should
  		 * be mindful of the maximum number of retries specified
  		 * and not get stuck in a loop.
  		 */
  	case DID_SOFT_ERROR:
  		goto maybe_retry;
  	case DID_IMM_RETRY:
  		return NEEDS_RETRY;
bf341919d   James Bottomley   scsi: add DID_REQ...
1808
1809
  	case DID_REQUEUE:
  		return ADD_TO_MLQUEUE;
a4dfaa6f2   Mike Christie   [SCSI] scsi: add ...
1810
1811
1812
1813
1814
  	case DID_TRANSPORT_DISRUPTED:
  		/*
  		 * LLD/transport was disrupted during processing of the IO.
  		 * The transport class is now blocked/blocking,
  		 * and the transport will decide what to do with the IO
939c2288c   Mike Christie   [SCSI] scsi_error...
1815
1816
  		 * based on its timers and recovery capablilities if
  		 * there are enough retries.
a4dfaa6f2   Mike Christie   [SCSI] scsi: add ...
1817
  		 */
939c2288c   Mike Christie   [SCSI] scsi_error...
1818
  		goto maybe_retry;
a4dfaa6f2   Mike Christie   [SCSI] scsi: add ...
1819
1820
1821
1822
1823
1824
  	case DID_TRANSPORT_FAILFAST:
  		/*
  		 * The transport decided to failfast the IO (most likely
  		 * the fast io fail tmo fired), so send IO directly upwards.
  		 */
  		return SUCCESS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1825
1826
1827
1828
1829
1830
1831
1832
1833
  	case DID_ERROR:
  		if (msg_byte(scmd->result) == COMMAND_COMPLETE &&
  		    status_byte(scmd->result) == RESERVATION_CONFLICT)
  			/*
  			 * execute reservation conflict processing code
  			 * lower down
  			 */
  			break;
  		/* fallthrough */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
  	case DID_BUS_BUSY:
  	case DID_PARITY:
  		goto maybe_retry;
  	case DID_TIME_OUT:
  		/*
  		 * when we scan the bus, we get timeout messages for
  		 * these commands if there is no device available.
  		 * other hosts report did_no_connect for the same thing.
  		 */
  		if ((scmd->cmnd[0] == TEST_UNIT_READY ||
  		     scmd->cmnd[0] == INQUIRY)) {
  			return SUCCESS;
  		} else {
  			return FAILED;
  		}
  	case DID_RESET:
  		return SUCCESS;
  	default:
  		return FAILED;
  	}
  
  	/*
  	 * next, check the message byte.
  	 */
  	if (msg_byte(scmd->result) != COMMAND_COMPLETE)
  		return FAILED;
  
  	/*
  	 * check the status byte to see if this indicates anything special.
  	 */
  	switch (status_byte(scmd->result)) {
  	case QUEUE_FULL:
42a6a9183   Mike Christie   [SCSI] scsi error...
1866
  		scsi_handle_queue_full(scmd->device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
  		/*
  		 * the case of trying to send too many commands to a
  		 * tagged queueing device.
  		 */
  	case BUSY:
  		/*
  		 * device can't talk to us at the moment.  Should only
  		 * occur (SAM-3) when the task queue is empty, so will cause
  		 * the empty queue handling to trigger a stall in the
  		 * device.
  		 */
  		return ADD_TO_MLQUEUE;
  	case GOOD:
279afdfe7   Ewan D. Milne   [SCSI] Generate u...
1880
1881
  		if (scmd->cmnd[0] == REPORT_LUNS)
  			scmd->device->sdev_target->expecting_lun_change = 0;
4a84067db   Vasu Dev   [SCSI] add queue_...
1882
  		scsi_handle_queue_ramp_up(scmd->device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1883
  	case COMMAND_TERMINATED:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1884
  		return SUCCESS;
a9b589d90   Vladislav Bolkhovitin   [SCSI] scsi_error...
1885
1886
  	case TASK_ABORTED:
  		goto maybe_retry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
  	case CHECK_CONDITION:
  		rtn = scsi_check_sense(scmd);
  		if (rtn == NEEDS_RETRY)
  			goto maybe_retry;
  		/* if rtn == FAILED, we have no sense information;
  		 * returning FAILED will wake the error handler thread
  		 * to collect the sense and redo the decide
  		 * disposition */
  		return rtn;
  	case CONDITION_GOOD:
  	case INTERMEDIATE_GOOD:
  	case INTERMEDIATE_C_GOOD:
  	case ACA_ACTIVE:
  		/*
  		 * who knows?  FIXME(eric)
  		 */
  		return SUCCESS;
  
  	case RESERVATION_CONFLICT:
9ccfc756a   James Bottomley   [SCSI] move the m...
1906
1907
1908
  		sdev_printk(KERN_INFO, scmd->device,
  			    "reservation conflict
  ");
2082ebc45   Moger, Babu   [SCSI] fix the ne...
1909
  		set_host_byte(scmd, DID_NEXUS_FAILURE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
  		return SUCCESS; /* causes immediate i/o error */
  	default:
  		return FAILED;
  	}
  	return FAILED;
  
        maybe_retry:
  
  	/* we requeue for retry because the error was retryable, and
  	 * the request was not marked fast fail.  Note that above,
  	 * even if the request is marked fast fail, we still requeue
  	 * for queue congestion conditions (QUEUE_FULL or BUSY) */
8884efab1   Brian King   [SCSI] scsi: scsi...
1922
  	if ((++scmd->retries) <= scmd->allowed
4a27446f3   Mike Christie   [SCSI] modify scs...
1923
  	    && !scsi_noretry_cmd(scmd)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1924
1925
1926
1927
1928
1929
1930
1931
  		return NEEDS_RETRY;
  	} else {
  		/*
  		 * no more retries - report this one back to upper level.
  		 */
  		return SUCCESS;
  	}
  }
f078727b2   FUJITA Tomonori   [SCSI] remove scs...
1932
1933
1934
1935
  static void eh_lock_door_done(struct request *req, int uptodate)
  {
  	__blk_put_request(req->q, req);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1936
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1937
1938
1939
1940
   * scsi_eh_lock_door - Prevent medium removal for the specified device
   * @sdev:	SCSI device to prevent medium removal
   *
   * Locking:
91bc31fb3   James Bottomley   [SCSI] fix up scs...
1941
   * 	We must be called from process context.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1942
1943
1944
1945
   *
   * Notes:
   * 	We queue up an asynchronous "ALLOW MEDIUM REMOVAL" request on the
   * 	head of the devices request queue, and continue.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
1946
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1947
1948
  static void scsi_eh_lock_door(struct scsi_device *sdev)
  {
f078727b2   FUJITA Tomonori   [SCSI] remove scs...
1949
  	struct request *req;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1950

91bc31fb3   James Bottomley   [SCSI] fix up scs...
1951
1952
1953
1954
  	/*
  	 * blk_get_request with GFP_KERNEL (__GFP_WAIT) sleeps until a
  	 * request becomes available
  	 */
f078727b2   FUJITA Tomonori   [SCSI] remove scs...
1955
  	req = blk_get_request(sdev->request_queue, READ, GFP_KERNEL);
a492f0754   Joe Lawrence   block,scsi: fixup...
1956
  	if (IS_ERR(req))
eb571eead   Joe Lawrence   block,scsi: verif...
1957
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1958

f27b087b8   Jens Axboe   block: add blk_rq...
1959
  	blk_rq_set_block_pc(req);
f078727b2   FUJITA Tomonori   [SCSI] remove scs...
1960
1961
1962
1963
1964
1965
  	req->cmd[0] = ALLOW_MEDIUM_REMOVAL;
  	req->cmd[1] = 0;
  	req->cmd[2] = 0;
  	req->cmd[3] = 0;
  	req->cmd[4] = SCSI_REMOVAL_PREVENT;
  	req->cmd[5] = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1966

f078727b2   FUJITA Tomonori   [SCSI] remove scs...
1967
  	req->cmd_len = COMMAND_SIZE(req->cmd[0]);
f078727b2   FUJITA Tomonori   [SCSI] remove scs...
1968
1969
1970
1971
1972
1973
  	req->cmd_flags |= REQ_QUIET;
  	req->timeout = 10 * HZ;
  	req->retries = 5;
  
  	blk_execute_rq_nowait(req->q, NULL, req, 1, eh_lock_door_done);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1974
1975
1976
1977
1978
1979
1980
1981
  
  /**
   * scsi_restart_operations - restart io operations to the specified host.
   * @shost:	Host we are restarting.
   *
   * Notes:
   *    When we entered the error handler, we blocked all further i/o to
   *    this device.  we need to 'reverse' this process.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
1982
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1983
1984
1985
  static void scsi_restart_operations(struct Scsi_Host *shost)
  {
  	struct scsi_device *sdev;
939647ee3   James Bottomley   [SCSI] fix oops o...
1986
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1987
1988
1989
1990
1991
1992
1993
  
  	/*
  	 * If the door was locked, we need to insert a door lock request
  	 * onto the head of the SCSI request queue for the device.  There
  	 * is no point trying to lock the door of an off-line device.
  	 */
  	shost_for_each_device(sdev, shost) {
48379270f   Christoph Hellwig   scsi: only re-loc...
1994
  		if (scsi_device_online(sdev) && sdev->was_reset && sdev->locked) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1995
  			scsi_eh_lock_door(sdev);
48379270f   Christoph Hellwig   scsi: only re-loc...
1996
1997
  			sdev->was_reset = 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1998
1999
2000
2001
2002
2003
2004
  	}
  
  	/*
  	 * next free up anything directly waiting upon the host.  this
  	 * will be requests for character device operations, and also for
  	 * ioctls to queued block devices.
  	 */
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
2005
  	SCSI_LOG_ERROR_RECOVERY(3,
91921e016   Hannes Reinecke   scsi: use dev_pri...
2006
2007
  		shost_printk(KERN_INFO, shost, "waking up host to restart
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2008

939647ee3   James Bottomley   [SCSI] fix oops o...
2009
2010
2011
2012
2013
  	spin_lock_irqsave(shost->host_lock, flags);
  	if (scsi_host_set_state(shost, SHOST_RUNNING))
  		if (scsi_host_set_state(shost, SHOST_CANCEL))
  			BUG_ON(scsi_host_set_state(shost, SHOST_DEL));
  	spin_unlock_irqrestore(shost->host_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
  
  	wake_up(&shost->host_wait);
  
  	/*
  	 * finally we need to re-initiate requests that may be pending.  we will
  	 * have had everything blocked while error handling is taking place, and
  	 * now that error recovery is done, we will need to ensure that these
  	 * requests are started.
  	 */
  	scsi_run_host_queues(shost);
57fc2e335   Dan Williams   [SCSI] fix eh wak...
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
  
  	/*
  	 * if eh is active and host_eh_scheduled is pending we need to re-run
  	 * recovery.  we do this check after scsi_run_host_queues() to allow
  	 * everything pent up since the last eh run a chance to make forward
  	 * progress before we sync again.  Either we'll immediately re-run
  	 * recovery or scsi_device_unbusy() will wake us again when these
  	 * pending commands complete.
  	 */
  	spin_lock_irqsave(shost->host_lock, flags);
  	if (shost->host_eh_scheduled)
  		if (scsi_host_set_state(shost, SHOST_RECOVERY))
  			WARN_ON(scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY));
  	spin_unlock_irqrestore(shost->host_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2038
2039
2040
2041
  }
  
  /**
   * scsi_eh_ready_devs - check device ready state and recover if not.
74cf298fe   Randy Dunlap   scsi: fix various...
2042
2043
   * @shost:	host to be recovered.
   * @work_q:	&list_head for pending commands.
eb44820c2   Rob Landley   [SCSI] Add Docume...
2044
   * @done_q:	&list_head for processed commands.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
2045
   */
dca84e469   Darrick J. Wong   [SCSI] scsi_error...
2046
2047
2048
  void scsi_eh_ready_devs(struct Scsi_Host *shost,
  			struct list_head *work_q,
  			struct list_head *done_q)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2049
2050
2051
  {
  	if (!scsi_eh_stu(shost, work_q, done_q))
  		if (!scsi_eh_bus_device_reset(shost, work_q, done_q))
30bd7df8c   Mike Christie   [SCSI] scsi_error...
2052
2053
  			if (!scsi_eh_target_reset(shost, work_q, done_q))
  				if (!scsi_eh_bus_reset(shost, work_q, done_q))
91921e016   Hannes Reinecke   scsi: use dev_pri...
2054
  					if (!scsi_eh_host_reset(shost, work_q, done_q))
30bd7df8c   Mike Christie   [SCSI] scsi_error...
2055
2056
  						scsi_eh_offline_sdevs(work_q,
  								      done_q);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2057
  }
dca84e469   Darrick J. Wong   [SCSI] scsi_error...
2058
  EXPORT_SYMBOL_GPL(scsi_eh_ready_devs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2059
2060
2061
2062
  
  /**
   * scsi_eh_flush_done_q - finish processed commands or retry them.
   * @done_q:	list_head of processed commands.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
2063
   */
041c5fc33   Tejun Heo   [PATCH] SCSI: exp...
2064
  void scsi_eh_flush_done_q(struct list_head *done_q)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2065
  {
937abeaad   Christoph Hellwig   [SCSI] use list_f...
2066
  	struct scsi_cmnd *scmd, *next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2067

937abeaad   Christoph Hellwig   [SCSI] use list_f...
2068
2069
  	list_for_each_entry_safe(scmd, next, done_q, eh_entry) {
  		list_del_init(&scmd->eh_entry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2070
  		if (scsi_device_online(scmd->device) &&
4a27446f3   Mike Christie   [SCSI] modify scs...
2071
  		    !scsi_noretry_cmd(scmd) &&
8884efab1   Brian King   [SCSI] scsi: scsi...
2072
  		    (++scmd->retries <= scmd->allowed)) {
91921e016   Hannes Reinecke   scsi: use dev_pri...
2073
2074
2075
2076
2077
  			SCSI_LOG_ERROR_RECOVERY(3,
  				scmd_printk(KERN_INFO, scmd,
  					     "%s: flush retry cmd: %p
  ",
  					     current->comm, scmd));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2078
2079
  				scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY);
  		} else {
793698ce2   Patrick Mansfield   [SCSI] saved and ...
2080
2081
2082
2083
2084
  			/*
  			 * If just we got sense for the device (called
  			 * scsi_eh_get_sense), scmd->result is already
  			 * set, do not set DRIVER_TIMEOUT.
  			 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2085
2086
  			if (!scmd->result)
  				scmd->result |= (DRIVER_TIMEOUT << 24);
91921e016   Hannes Reinecke   scsi: use dev_pri...
2087
2088
2089
2090
2091
  			SCSI_LOG_ERROR_RECOVERY(3,
  				scmd_printk(KERN_INFO, scmd,
  					     "%s: flush finish cmd: %p
  ",
  					     current->comm, scmd));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2092
2093
2094
2095
  			scsi_finish_command(scmd);
  		}
  	}
  }
041c5fc33   Tejun Heo   [PATCH] SCSI: exp...
2096
  EXPORT_SYMBOL(scsi_eh_flush_done_q);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
  
  /**
   * scsi_unjam_host - Attempt to fix a host which has a cmd that failed.
   * @shost:	Host to unjam.
   *
   * Notes:
   *    When we come in here, we *know* that all commands on the bus have
   *    either completed, failed or timed out.  we also know that no further
   *    commands are being sent to the host, so things are relatively quiet
   *    and we have freedom to fiddle with things as we wish.
   *
   *    This is only the *default* implementation.  it is possible for
   *    individual drivers to supply their own version of this function, and
   *    if the maintainer wishes to do this, it is strongly suggested that
   *    this function be taken as a template and modified.  this function
   *    was designed to correctly handle problems for about 95% of the
   *    different cases out there, and it should always provide at least a
   *    reasonable amount of error recovery.
   *
   *    Any command marked 'failed' or 'timeout' must eventually have
   *    scsi_finish_cmd() called for it.  we do all of the retry stuff
   *    here, so when we restart the host after we return it should have an
   *    empty queue.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
2120
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
  static void scsi_unjam_host(struct Scsi_Host *shost)
  {
  	unsigned long flags;
  	LIST_HEAD(eh_work_q);
  	LIST_HEAD(eh_done_q);
  
  	spin_lock_irqsave(shost->host_lock, flags);
  	list_splice_init(&shost->eh_cmd_q, &eh_work_q);
  	spin_unlock_irqrestore(shost->host_lock, flags);
  
  	SCSI_LOG_ERROR_RECOVERY(1, scsi_eh_prt_fail_stats(shost, &eh_work_q));
  
  	if (!scsi_eh_get_sense(&eh_work_q, &eh_done_q))
  		if (!scsi_eh_abort_cmds(&eh_work_q, &eh_done_q))
  			scsi_eh_ready_devs(shost, &eh_work_q, &eh_done_q);
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
2136
  	spin_lock_irqsave(shost->host_lock, flags);
bb3b621a3   Ren Mingxin   [SCSI] Set the mi...
2137
  	if (shost->eh_deadline != -1)
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
2138
2139
  		shost->last_reset = 0;
  	spin_unlock_irqrestore(shost->host_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2140
2141
2142
2143
  	scsi_eh_flush_done_q(&eh_done_q);
  }
  
  /**
ad42eb1b7   Christoph Hellwig   [SCSI] tidy up sc...
2144
   * scsi_error_handler - SCSI error handler thread
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2145
2146
2147
   * @data:	Host for which we are running.
   *
   * Notes:
ad42eb1b7   Christoph Hellwig   [SCSI] tidy up sc...
2148
2149
   *    This is the main error handling loop.  This is run as a kernel thread
   *    for every SCSI host and handles all error handling activity.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
2150
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2151
2152
  int scsi_error_handler(void *data)
  {
ad42eb1b7   Christoph Hellwig   [SCSI] tidy up sc...
2153
  	struct Scsi_Host *shost = data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2154

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2155
  	/*
ad42eb1b7   Christoph Hellwig   [SCSI] tidy up sc...
2156
2157
2158
  	 * We use TASK_INTERRUPTIBLE so that the thread is not
  	 * counted against the load average as a running process.
  	 * We never actually get interrupted because kthread_run
c03264a79   Frederik Schwarzer   trivial: fix sing...
2159
  	 * disables signal delivery for the created thread.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2160
  	 */
3ed7a4704   James Bottomley   [SCSI] Fix thread...
2161
  	while (!kthread_should_stop()) {
b9d5c6b7e   Dan Williams   [SCSI] cleanup se...
2162
  		set_current_state(TASK_INTERRUPTIBLE);
ee7863bc6   Tejun Heo   [PATCH] SCSI: imp...
2163
  		if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) ||
746650160   Christoph Hellwig   scsi: convert hos...
2164
  		    shost->host_failed != atomic_read(&shost->host_busy)) {
ad42eb1b7   Christoph Hellwig   [SCSI] tidy up sc...
2165
  			SCSI_LOG_ERROR_RECOVERY(1,
91921e016   Hannes Reinecke   scsi: use dev_pri...
2166
2167
2168
2169
  				shost_printk(KERN_INFO, shost,
  					     "scsi_eh_%d: sleeping
  ",
  					     shost->host_no));
3ed7a4704   James Bottomley   [SCSI] Fix thread...
2170
  			schedule();
3ed7a4704   James Bottomley   [SCSI] Fix thread...
2171
2172
  			continue;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2173

3ed7a4704   James Bottomley   [SCSI] Fix thread...
2174
  		__set_current_state(TASK_RUNNING);
ad42eb1b7   Christoph Hellwig   [SCSI] tidy up sc...
2175
  		SCSI_LOG_ERROR_RECOVERY(1,
91921e016   Hannes Reinecke   scsi: use dev_pri...
2176
2177
2178
2179
  			shost_printk(KERN_INFO, shost,
  				     "scsi_eh_%d: waking up %d/%d/%d
  ",
  				     shost->host_no, shost->host_eh_scheduled,
746650160   Christoph Hellwig   scsi: convert hos...
2180
2181
  				     shost->host_failed,
  				     atomic_read(&shost->host_busy)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2182

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2183
2184
2185
2186
2187
  		/*
  		 * We have a host that is failing for some reason.  Figure out
  		 * what we need to do to get it up and online again (if we can).
  		 * If we fail, we end up taking the thing offline.
  		 */
ae0751ffc   Lin Ming   [SCSI] add flag t...
2188
  		if (!shost->eh_noresume && scsi_autopm_get_host(shost) != 0) {
bc4f24014   Alan Stern   [SCSI] implement ...
2189
2190
2191
2192
2193
2194
2195
  			SCSI_LOG_ERROR_RECOVERY(1,
  				printk(KERN_ERR "Error handler scsi_eh_%d "
  						"unable to autoresume
  ",
  						shost->host_no));
  			continue;
  		}
9227c33de   Christoph Hellwig   [PATCH] move ->eh...
2196
2197
  		if (shost->transportt->eh_strategy_handler)
  			shost->transportt->eh_strategy_handler(shost);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2198
2199
  		else
  			scsi_unjam_host(shost);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2200
2201
2202
2203
2204
2205
2206
2207
  		/*
  		 * Note - if the above fails completely, the action is to take
  		 * individual devices offline and flush the queue of any
  		 * outstanding requests that may have been pending.  When we
  		 * restart, we restart any I/O to any other devices on the bus
  		 * which are still online.
  		 */
  		scsi_restart_operations(shost);
ae0751ffc   Lin Ming   [SCSI] add flag t...
2208
2209
  		if (!shost->eh_noresume)
  			scsi_autopm_put_host(shost);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2210
  	}
461a0ffbe   Steven Rostedt   [PATCH] scsi_erro...
2211
  	__set_current_state(TASK_RUNNING);
ad42eb1b7   Christoph Hellwig   [SCSI] tidy up sc...
2212
  	SCSI_LOG_ERROR_RECOVERY(1,
91921e016   Hannes Reinecke   scsi: use dev_pri...
2213
2214
2215
2216
  		shost_printk(KERN_INFO, shost,
  			     "Error handler scsi_eh_%d exiting
  ",
  			     shost->host_no));
3ed7a4704   James Bottomley   [SCSI] Fix thread...
2217
  	shost->ehandler = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
  	return 0;
  }
  
  /*
   * Function:    scsi_report_bus_reset()
   *
   * Purpose:     Utility function used by low-level drivers to report that
   *		they have observed a bus reset on the bus being handled.
   *
   * Arguments:   shost       - Host in question
   *		channel     - channel on which reset was observed.
   *
   * Returns:     Nothing
   *
   * Lock status: Host lock must be held.
   *
   * Notes:       This only needs to be called if the reset is one which
   *		originates from an unknown location.  Resets originated
   *		by the mid-level itself don't need to call this, but there
   *		should be no harm.
   *
   *		The main purpose of this is to make sure that a CHECK_CONDITION
   *		is properly treated.
   */
  void scsi_report_bus_reset(struct Scsi_Host *shost, int channel)
  {
  	struct scsi_device *sdev;
  
  	__shost_for_each_device(sdev, shost) {
30bd7df8c   Mike Christie   [SCSI] scsi_error...
2247
2248
  		if (channel == sdev_channel(sdev))
  			__scsi_report_device_reset(sdev, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
  	}
  }
  EXPORT_SYMBOL(scsi_report_bus_reset);
  
  /*
   * Function:    scsi_report_device_reset()
   *
   * Purpose:     Utility function used by low-level drivers to report that
   *		they have observed a device reset on the device being handled.
   *
   * Arguments:   shost       - Host in question
   *		channel     - channel on which reset was observed
   *		target	    - target on which reset was observed
   *
   * Returns:     Nothing
   *
   * Lock status: Host lock must be held
   *
   * Notes:       This only needs to be called if the reset is one which
   *		originates from an unknown location.  Resets originated
   *		by the mid-level itself don't need to call this, but there
   *		should be no harm.
   *
   *		The main purpose of this is to make sure that a CHECK_CONDITION
   *		is properly treated.
   */
  void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target)
  {
  	struct scsi_device *sdev;
  
  	__shost_for_each_device(sdev, shost) {
422c0d61d   Jeff Garzik   [SCSI] use scmd_i...
2280
  		if (channel == sdev_channel(sdev) &&
30bd7df8c   Mike Christie   [SCSI] scsi_error...
2281
2282
  		    target == sdev_id(sdev))
  			__scsi_report_device_reset(sdev, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
  	}
  }
  EXPORT_SYMBOL(scsi_report_device_reset);
  
  static void
  scsi_reset_provider_done_command(struct scsi_cmnd *scmd)
  {
  }
  
  /*
   * Function:	scsi_reset_provider
   *
   * Purpose:	Send requested reset to a bus or device at any phase.
   *
   * Arguments:	device	- device to send reset to
   *		flag - reset type (see scsi.h)
   *
   * Returns:	SUCCESS/FAILURE.
   *
   * Notes:	This is used by the SCSI Generic driver to provide
   *		Bus/Device reset capability.
   */
  int
  scsi_reset_provider(struct scsi_device *dev, int flag)
  {
bc4f24014   Alan Stern   [SCSI] implement ...
2308
  	struct scsi_cmnd *scmd;
d7a1bb0a0   James Smart   [SCSI] Block I/O ...
2309
  	struct Scsi_Host *shost = dev->host;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2310
  	struct request req;
d7a1bb0a0   James Smart   [SCSI] Block I/O ...
2311
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2312
  	int rtn;
bc4f24014   Alan Stern   [SCSI] implement ...
2313
2314
  	if (scsi_autopm_get_host(shost) < 0)
  		return FAILED;
047963368   Christoph Hellwig   [SCSI] do not man...
2315
2316
2317
2318
  	if (!get_device(&dev->sdev_gendev)) {
  		rtn = FAILED;
  		goto out_put_autopm_host;
  	}
bc4f24014   Alan Stern   [SCSI] implement ...
2319
  	scmd = scsi_get_command(dev, GFP_KERNEL);
95eeb5f58   Christoph Hellwig   scsi: handle comm...
2320
2321
2322
2323
2324
  	if (!scmd) {
  		rtn = FAILED;
  		put_device(&dev->sdev_gendev);
  		goto out_put_autopm_host;
  	}
4f54eec83   FUJITA Tomonori   block: use blk_rq...
2325
  	blk_rq_init(NULL, &req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2326
  	scmd->request = &req;
b4edcbcaf   Christoph Hellwig   [SCSI] remove scs...
2327

64a87b244   Boaz Harrosh   [SCSI] Let scsi_c...
2328
  	scmd->cmnd = req.cmd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2329
  	scmd->scsi_done		= scsi_reset_provider_done_command;
30b0c37b2   Boaz Harrosh   [SCSI] implement ...
2330
  	memset(&scmd->sdb, 0, sizeof(scmd->sdb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2331
2332
2333
2334
  
  	scmd->cmd_len			= 0;
  
  	scmd->sc_data_direction		= DMA_BIDIRECTIONAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2335

d7a1bb0a0   James Smart   [SCSI] Block I/O ...
2336
2337
2338
  	spin_lock_irqsave(shost->host_lock, flags);
  	shost->tmf_in_progress = 1;
  	spin_unlock_irqrestore(shost->host_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2339
2340
2341
2342
2343
2344
  	switch (flag) {
  	case SCSI_TRY_RESET_DEVICE:
  		rtn = scsi_try_bus_device_reset(scmd);
  		if (rtn == SUCCESS)
  			break;
  		/* FALLTHROUGH */
30bd7df8c   Mike Christie   [SCSI] scsi_error...
2345
2346
2347
2348
2349
  	case SCSI_TRY_RESET_TARGET:
  		rtn = scsi_try_target_reset(scmd);
  		if (rtn == SUCCESS)
  			break;
  		/* FALLTHROUGH */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
  	case SCSI_TRY_RESET_BUS:
  		rtn = scsi_try_bus_reset(scmd);
  		if (rtn == SUCCESS)
  			break;
  		/* FALLTHROUGH */
  	case SCSI_TRY_RESET_HOST:
  		rtn = scsi_try_host_reset(scmd);
  		break;
  	default:
  		rtn = FAILED;
  	}
d7a1bb0a0   James Smart   [SCSI] Block I/O ...
2361
2362
2363
2364
2365
2366
2367
2368
2369
  	spin_lock_irqsave(shost->host_lock, flags);
  	shost->tmf_in_progress = 0;
  	spin_unlock_irqrestore(shost->host_lock, flags);
  
  	/*
  	 * be sure to wake up anyone who was sleeping or had their queue
  	 * suspended while we performed the TMF.
  	 */
  	SCSI_LOG_ERROR_RECOVERY(3,
91921e016   Hannes Reinecke   scsi: use dev_pri...
2370
2371
2372
  		shost_printk(KERN_INFO, shost,
  			     "waking up host to restart after TMF
  "));
d7a1bb0a0   James Smart   [SCSI] Block I/O ...
2373
2374
2375
2376
  
  	wake_up(&shost->host_wait);
  
  	scsi_run_host_queues(shost);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2377
  	scsi_next_command(scmd);
047963368   Christoph Hellwig   [SCSI] do not man...
2378
  out_put_autopm_host:
bc4f24014   Alan Stern   [SCSI] implement ...
2379
  	scsi_autopm_put_host(shost);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
  	return rtn;
  }
  EXPORT_SYMBOL(scsi_reset_provider);
  
  /**
   * scsi_normalize_sense - normalize main elements from either fixed or
   *			descriptor sense data format into a common format.
   *
   * @sense_buffer:	byte array containing sense data returned by device
   * @sb_len:		number of valid bytes in sense_buffer
   * @sshdr:		pointer to instance of structure that common
   *			elements are written to.
   *
   * Notes:
   *	The "main elements" from sense data are: response_code, sense_key,
   *	asc, ascq and additional_length (only for descriptor format).
   *
   *	Typically this function can be called after a device has
   *	responded to a SCSI command with the CHECK_CONDITION status.
   *
   * Return value:
   *	1 if valid sense data information found, else 0;
dc8875e10   Randy Dunlap   [SCSI] docbook an...
2402
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2403
2404
2405
  int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
                           struct scsi_sense_hdr *sshdr)
  {
33aa687db   James Bottomley   [SCSI] convert SP...
2406
  	if (!sense_buffer || !sb_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2407
2408
2409
2410
2411
  		return 0;
  
  	memset(sshdr, 0, sizeof(struct scsi_sense_hdr));
  
  	sshdr->response_code = (sense_buffer[0] & 0x7f);
33aa687db   James Bottomley   [SCSI] convert SP...
2412
2413
2414
  
  	if (!scsi_sense_valid(sshdr))
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
  	if (sshdr->response_code >= 0x72) {
  		/*
  		 * descriptor format
  		 */
  		if (sb_len > 1)
  			sshdr->sense_key = (sense_buffer[1] & 0xf);
  		if (sb_len > 2)
  			sshdr->asc = sense_buffer[2];
  		if (sb_len > 3)
  			sshdr->ascq = sense_buffer[3];
  		if (sb_len > 7)
  			sshdr->additional_length = sense_buffer[7];
  	} else {
0bf8c8697   Jesper Juhl   Reduce sequential...
2428
  		/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
  		 * fixed format
  		 */
  		if (sb_len > 2)
  			sshdr->sense_key = (sense_buffer[2] & 0xf);
  		if (sb_len > 7) {
  			sb_len = (sb_len < (sense_buffer[7] + 8)) ?
  					 sb_len : (sense_buffer[7] + 8);
  			if (sb_len > 12)
  				sshdr->asc = sense_buffer[12];
  			if (sb_len > 13)
  				sshdr->ascq = sense_buffer[13];
  		}
  	}
  
  	return 1;
  }
  EXPORT_SYMBOL(scsi_normalize_sense);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2446
2447
2448
2449
  int scsi_command_normalize_sense(struct scsi_cmnd *cmd,
  				 struct scsi_sense_hdr *sshdr)
  {
  	return scsi_normalize_sense(cmd->sense_buffer,
b80ca4f7e   FUJITA Tomonori   [SCSI] replace si...
2450
  			SCSI_SENSE_BUFFERSIZE, sshdr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2451
2452
2453
2454
  }
  EXPORT_SYMBOL(scsi_command_normalize_sense);
  
  /**
eb44820c2   Rob Landley   [SCSI] Add Docume...
2455
   * scsi_sense_desc_find - search for a given descriptor type in	descriptor sense data format.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
   * @sense_buffer:	byte array of descriptor format sense data
   * @sb_len:		number of valid bytes in sense_buffer
   * @desc_type:		value of descriptor type to find
   *			(e.g. 0 -> information)
   *
   * Notes:
   *	only valid when sense data is in descriptor format
   *
   * Return value:
   *	pointer to start of (first) descriptor if found else NULL
dc8875e10   Randy Dunlap   [SCSI] docbook an...
2466
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
  const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,
  				int desc_type)
  {
  	int add_sen_len, add_len, desc_len, k;
  	const u8 * descp;
  
  	if ((sb_len < 8) || (0 == (add_sen_len = sense_buffer[7])))
  		return NULL;
  	if ((sense_buffer[0] < 0x72) || (sense_buffer[0] > 0x73))
  		return NULL;
  	add_sen_len = (add_sen_len < (sb_len - 8)) ?
  			add_sen_len : (sb_len - 8);
  	descp = &sense_buffer[8];
  	for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) {
  		descp += desc_len;
  		add_len = (k < (add_sen_len - 1)) ? descp[1]: -1;
  		desc_len = add_len + 2;
  		if (descp[0] == desc_type)
  			return descp;
  		if (add_len < 0) // short descriptor ??
  			break;
  	}
  	return NULL;
  }
  EXPORT_SYMBOL(scsi_sense_desc_find);
  
  /**
eb44820c2   Rob Landley   [SCSI] Add Docume...
2494
   * scsi_get_sense_info_fld - get information field from sense data (either fixed or descriptor format)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2495
2496
2497
2498
2499
2500
2501
   * @sense_buffer:	byte array of sense data
   * @sb_len:		number of valid bytes in sense_buffer
   * @info_out:		pointer to 64 integer where 8 or 4 byte information
   *			field will be placed if found.
   *
   * Return value:
   *	1 if information field found, 0 if not found.
dc8875e10   Randy Dunlap   [SCSI] docbook an...
2502
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
  int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
  			    u64 * info_out)
  {
  	int j;
  	const u8 * ucp;
  	u64 ull;
  
  	if (sb_len < 7)
  		return 0;
  	switch (sense_buffer[0] & 0x7f) {
  	case 0x70:
  	case 0x71:
  		if (sense_buffer[0] & 0x80) {
  			*info_out = (sense_buffer[3] << 24) +
  				    (sense_buffer[4] << 16) +
  				    (sense_buffer[5] << 8) + sense_buffer[6];
  			return 1;
  		} else
  			return 0;
  	case 0x72:
  	case 0x73:
  		ucp = scsi_sense_desc_find(sense_buffer, sb_len,
  					   0 /* info desc */);
  		if (ucp && (0xa == ucp[1])) {
  			ull = 0;
  			for (j = 0; j < 8; ++j) {
  				if (j > 0)
  					ull <<= 8;
  				ull |= ucp[4 + j];
  			}
  			*info_out = ull;
  			return 1;
  		} else
  			return 0;
  	default:
  		return 0;
  	}
  }
  EXPORT_SYMBOL(scsi_get_sense_info_fld);
3bc6a2619   FUJITA Tomonori   [SCSI] add scsi_b...
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
  
  /**
   * scsi_build_sense_buffer - build sense data in a buffer
   * @desc:	Sense format (non zero == descriptor format,
   * 		0 == fixed format)
   * @buf:	Where to build sense data
   * @key:	Sense key
   * @asc:	Additional sense code
   * @ascq:	Additional sense code qualifier
   *
   **/
  void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq)
  {
  	if (desc) {
  		buf[0] = 0x72;	/* descriptor, current */
  		buf[1] = key;
  		buf[2] = asc;
  		buf[3] = ascq;
  		buf[7] = 0;
  	} else {
  		buf[0] = 0x70;	/* fixed, current */
  		buf[2] = key;
  		buf[7] = 0xa;
  		buf[12] = asc;
  		buf[13] = ascq;
  	}
  }
  EXPORT_SYMBOL(scsi_build_sense_buffer);