Blame view

drivers/scsi/scsi.c 32.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
  /*
   *  scsi.c Copyright (C) 1992 Drew Eckhardt
   *         Copyright (C) 1993, 1994, 1995, 1999 Eric Youngdale
   *         Copyright (C) 2002, 2003 Christoph Hellwig
   *
   *  generic mid-level SCSI driver
   *      Initial versions: Drew Eckhardt
   *      Subsequent revisions: Eric Youngdale
   *
   *  <drew@colorado.edu>
   *
   *  Bug correction thanks go to :
   *      Rik Faith <faith@cs.unc.edu>
   *      Tommy Thorn <tthorn>
   *      Thomas Wuensche <tw@fgb1.fgb.mw.tu-muenchen.de>
   *
   *  Modified by Eric Youngdale eric@andante.org or ericy@gnu.ai.mit.edu to
   *  add scatter-gather, multiple outstanding request, and other
   *  enhancements.
   *
   *  Native multichannel, wide scsi, /proc/scsi and hot plugging
   *  support added by Michael Neuffer <mike@i-connect.net>
   *
   *  Added request_module("scsi_hostadapter") for kerneld:
   *  (Put an "alias scsi_hostadapter your_hostadapter" in /etc/modprobe.conf)
   *  Bjorn Ekwall  <bj0rn@blox.se>
   *  (changed to kmod)
   *
   *  Major improvements to the timeout, abort, and reset processing,
   *  as well as performance modifications for large queue depths by
   *  Leonard N. Zubkoff <lnz@dandelion.com>
   *
   *  Converted cli() code to spinlocks, Ingo Molnar
   *
   *  Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
   *
   *  out_of_space hacks, D. Gilbert (dpg) 990608
   */
  
  #include <linux/module.h>
  #include <linux/moduleparam.h>
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
45
46
47
48
49
  #include <linux/timer.h>
  #include <linux/string.h>
  #include <linux/slab.h>
  #include <linux/blkdev.h>
  #include <linux/delay.h>
  #include <linux/init.h>
  #include <linux/completion.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
54
55
  #include <linux/unistd.h>
  #include <linux/spinlock.h>
  #include <linux/kmod.h>
  #include <linux/interrupt.h>
  #include <linux/notifier.h>
  #include <linux/cpu.h>
0b9506723   Arjan van de Ven   [SCSI] turn most ...
56
  #include <linux/mutex.h>
2955b47d2   Dan Williams   [SCSI] async: int...
57
  #include <linux/async.h>
3c6bdaeab   Martin K. Petersen   [SCSI] Add a repo...
58
  #include <asm/unaligned.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
62
63
  
  #include <scsi/scsi.h>
  #include <scsi/scsi_cmnd.h>
  #include <scsi/scsi_dbg.h>
  #include <scsi/scsi_device.h>
7b3d9545f   Linus Torvalds   Revert "scsi: rev...
64
  #include <scsi/scsi_driver.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
66
67
  #include <scsi/scsi_eh.h>
  #include <scsi/scsi_host.h>
  #include <scsi/scsi_tcq.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
  
  #include "scsi_priv.h"
  #include "scsi_logging.h"
bf8162354   Kei Tokunaga   [SCSI] add scsi t...
71
72
  #define CREATE_TRACE_POINTS
  #include <trace/events/scsi.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
75
  /*
   * Definitions and constants.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
80
81
82
83
   * Note - the initial logging level can be set here to log events at boot time.
   * After the system is up, you may enable logging via the /proc interface.
   */
  unsigned int scsi_logging_level;
  #if defined(CONFIG_SCSI_LOGGING)
  EXPORT_SYMBOL(scsi_logging_level);
  #endif
ea80dadec   James Bottomley   [SCSI] Fix sd_pro...
84
  /* sd, scsi core and power management need to coordinate flushing async actions */
2955b47d2   Dan Williams   [SCSI] async: int...
85
  ASYNC_DOMAIN(scsi_sd_probe_domain);
a7a20d103   Dan Williams   [SCSI] sd: limit ...
86
  EXPORT_SYMBOL(scsi_sd_probe_domain);
a7a20d103   Dan Williams   [SCSI] sd: limit ...
87

3c31b52f9   Dan Williams   scsi: async sd re...
88
89
90
91
92
93
94
95
  /*
   * Separate domain (from scsi_sd_probe_domain) to maximize the benefit of
   * asynchronous system resume operations.  It is marked 'exclusive' to avoid
   * being included in the async_synchronize_full() that is invoked by
   * dpm_resume()
   */
  ASYNC_DOMAIN_EXCLUSIVE(scsi_sd_pm_domain);
  EXPORT_SYMBOL(scsi_sd_pm_domain);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
  struct scsi_host_cmd_pool {
5b7f16804   James Bottomley   [SCSI] don't use ...
97
98
99
100
101
102
103
  	struct kmem_cache	*cmd_slab;
  	struct kmem_cache	*sense_slab;
  	unsigned int		users;
  	char			*cmd_name;
  	char			*sense_name;
  	unsigned int		slab_flags;
  	gfp_t			gfp_mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
  };
  
  static struct scsi_host_cmd_pool scsi_cmd_pool = {
5b7f16804   James Bottomley   [SCSI] don't use ...
107
108
  	.cmd_name	= "scsi_cmd_cache",
  	.sense_name	= "scsi_sense_cache",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
112
  	.slab_flags	= SLAB_HWCACHE_ALIGN,
  };
  
  static struct scsi_host_cmd_pool scsi_cmd_dma_pool = {
5b7f16804   James Bottomley   [SCSI] don't use ...
113
114
  	.cmd_name	= "scsi_cmd_cache(DMA)",
  	.sense_name	= "scsi_sense_cache(DMA)",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
116
117
  	.slab_flags	= SLAB_HWCACHE_ALIGN|SLAB_CACHE_DMA,
  	.gfp_mask	= __GFP_DMA,
  };
0b9506723   Arjan van de Ven   [SCSI] turn most ...
118
  static DEFINE_MUTEX(host_cmd_pool_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119

eb44820c2   Rob Landley   [SCSI] Add Docume...
120
  /**
7c2833412   Christoph Hellwig   [SCSI] simplify c...
121
122
   * scsi_host_free_command - internal function to release a command
   * @shost:	host to free the command for
e507e30b8   James Bottomley   [SCSI] consolidat...
123
124
125
   * @cmd:	command to release
   *
   * the command must previously have been allocated by
7c2833412   Christoph Hellwig   [SCSI] simplify c...
126
   * scsi_host_alloc_command.
e507e30b8   James Bottomley   [SCSI] consolidat...
127
128
   */
  static void
7c2833412   Christoph Hellwig   [SCSI] simplify c...
129
  scsi_host_free_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
e507e30b8   James Bottomley   [SCSI] consolidat...
130
  {
7c2833412   Christoph Hellwig   [SCSI] simplify c...
131
  	struct scsi_host_cmd_pool *pool = shost->cmd_pool;
7027ad72a   Martin K. Petersen   [SCSI] Support de...
132
133
  	if (cmd->prot_sdb)
  		kmem_cache_free(scsi_sdb_cache, cmd->prot_sdb);
e507e30b8   James Bottomley   [SCSI] consolidat...
134
135
136
137
138
  	kmem_cache_free(pool->sense_slab, cmd->sense_buffer);
  	kmem_cache_free(pool->cmd_slab, cmd);
  }
  
  /**
7027ad72a   Martin K. Petersen   [SCSI] Support de...
139
140
141
142
143
144
145
146
147
148
   * scsi_host_alloc_command - internal function to allocate command
   * @shost:	SCSI host whose pool to allocate from
   * @gfp_mask:	mask for the allocation
   *
   * Returns a fully allocated command with sense buffer and protection
   * data buffer (where applicable) or NULL on failure
   */
  static struct scsi_cmnd *
  scsi_host_alloc_command(struct Scsi_Host *shost, gfp_t gfp_mask)
  {
7c2833412   Christoph Hellwig   [SCSI] simplify c...
149
  	struct scsi_host_cmd_pool *pool = shost->cmd_pool;
7027ad72a   Martin K. Petersen   [SCSI] Support de...
150
  	struct scsi_cmnd *cmd;
7c2833412   Christoph Hellwig   [SCSI] simplify c...
151
  	cmd = kmem_cache_zalloc(pool->cmd_slab, gfp_mask | pool->gfp_mask);
7027ad72a   Martin K. Petersen   [SCSI] Support de...
152
  	if (!cmd)
7c2833412   Christoph Hellwig   [SCSI] simplify c...
153
154
155
156
157
158
  		goto fail;
  
  	cmd->sense_buffer = kmem_cache_alloc(pool->sense_slab,
  					     gfp_mask | pool->gfp_mask);
  	if (!cmd->sense_buffer)
  		goto fail_free_cmd;
7027ad72a   Martin K. Petersen   [SCSI] Support de...
159
160
161
  
  	if (scsi_host_get_prot(shost) >= SHOST_DIX_TYPE0_PROTECTION) {
  		cmd->prot_sdb = kmem_cache_zalloc(scsi_sdb_cache, gfp_mask);
7c2833412   Christoph Hellwig   [SCSI] simplify c...
162
163
  		if (!cmd->prot_sdb)
  			goto fail_free_sense;
7027ad72a   Martin K. Petersen   [SCSI] Support de...
164
165
166
  	}
  
  	return cmd;
7c2833412   Christoph Hellwig   [SCSI] simplify c...
167
168
169
170
171
172
173
  
  fail_free_sense:
  	kmem_cache_free(pool->sense_slab, cmd->sense_buffer);
  fail_free_cmd:
  	kmem_cache_free(pool->cmd_slab, cmd);
  fail:
  	return NULL;
7027ad72a   Martin K. Petersen   [SCSI] Support de...
174
175
176
  }
  
  /**
eb44820c2   Rob Landley   [SCSI] Add Docume...
177
178
179
180
181
182
183
   * __scsi_get_command - Allocate a struct scsi_cmnd
   * @shost: host to transmit command
   * @gfp_mask: allocation mask
   *
   * Description: allocate a struct scsi_cmd from host's slab, recycling from the
   *              host's free_list if necessary.
   */
f1bea55d5   Christoph Hellwig   scsi: remove vari...
184
185
  static struct scsi_cmnd *
  __scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
  {
b4c2554d4   Martin K. Petersen   [SCSI] Fix protec...
187
  	struct scsi_cmnd *cmd = scsi_host_alloc_command(shost, gfp_mask);
164fc5dcd   Hugh Dickins   scsi: fix sense_s...
188

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
191
192
193
194
195
196
197
198
  	if (unlikely(!cmd)) {
  		unsigned long flags;
  
  		spin_lock_irqsave(&shost->free_list_lock, flags);
  		if (likely(!list_empty(&shost->free_list))) {
  			cmd = list_entry(shost->free_list.next,
  					 struct scsi_cmnd, list);
  			list_del_init(&cmd->list);
  		}
  		spin_unlock_irqrestore(&shost->free_list_lock, flags);
de25deb18   FUJITA Tomonori   [SCSI] use dynami...
199
200
  
  		if (cmd) {
b4c2554d4   Martin K. Petersen   [SCSI] Fix protec...
201
  			void *buf, *prot;
de25deb18   FUJITA Tomonori   [SCSI] use dynami...
202
  			buf = cmd->sense_buffer;
b4c2554d4   Martin K. Petersen   [SCSI] Fix protec...
203
  			prot = cmd->prot_sdb;
de25deb18   FUJITA Tomonori   [SCSI] use dynami...
204
  			memset(cmd, 0, sizeof(*cmd));
b4c2554d4   Martin K. Petersen   [SCSI] Fix protec...
205

de25deb18   FUJITA Tomonori   [SCSI] use dynami...
206
  			cmd->sense_buffer = buf;
b4c2554d4   Martin K. Petersen   [SCSI] Fix protec...
207
  			cmd->prot_sdb = prot;
de25deb18   FUJITA Tomonori   [SCSI] use dynami...
208
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
211
212
  	}
  
  	return cmd;
  }
eb44820c2   Rob Landley   [SCSI] Add Docume...
213
214
215
216
  /**
   * scsi_get_command - Allocate and setup a scsi command block
   * @dev: parent scsi device
   * @gfp_mask: allocator flags
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
219
   *
   * Returns:	The allocated scsi command structure.
   */
c53033f6b   Al Viro   [PATCH] gfp_t: dr...
220
  struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
  {
047963368   Christoph Hellwig   [SCSI] do not man...
222
223
  	struct scsi_cmnd *cmd = __scsi_get_command(dev->host, gfp_mask);
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224

047963368   Christoph Hellwig   [SCSI] do not man...
225
  	if (unlikely(cmd == NULL))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
  		return NULL;
047963368   Christoph Hellwig   [SCSI] do not man...
227
228
229
230
231
232
233
  	cmd->device = dev;
  	INIT_LIST_HEAD(&cmd->list);
  	INIT_DELAYED_WORK(&cmd->abort_work, scmd_eh_abort_handler);
  	spin_lock_irqsave(&dev->list_lock, flags);
  	list_add_tail(&cmd->list, &dev->cmd_list);
  	spin_unlock_irqrestore(&dev->list_lock, flags);
  	cmd->jiffies_at_alloc = jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
  	return cmd;
b58d91547   FUJITA Tomonori   [SCSI] export scs...
235
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236

eb44820c2   Rob Landley   [SCSI] Add Docume...
237
238
239
240
  /**
   * __scsi_put_command - Free a struct scsi_cmnd
   * @shost: dev->host
   * @cmd: Command to free
eb44820c2   Rob Landley   [SCSI] Add Docume...
241
   */
f1bea55d5   Christoph Hellwig   scsi: remove vari...
242
  static void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
b58d91547   FUJITA Tomonori   [SCSI] export scs...
243
244
  {
  	unsigned long flags;
b58d91547   FUJITA Tomonori   [SCSI] export scs...
245
  	if (unlikely(list_empty(&shost->free_list))) {
44b93b59d   Christoph Hellwig   [SCSI] avoid usel...
246
247
248
249
250
251
  		spin_lock_irqsave(&shost->free_list_lock, flags);
  		if (list_empty(&shost->free_list)) {
  			list_add(&cmd->list, &shost->free_list);
  			cmd = NULL;
  		}
  		spin_unlock_irqrestore(&shost->free_list_lock, flags);
b58d91547   FUJITA Tomonori   [SCSI] export scs...
252
  	}
b58d91547   FUJITA Tomonori   [SCSI] export scs...
253

e507e30b8   James Bottomley   [SCSI] consolidat...
254
  	if (likely(cmd != NULL))
7c2833412   Christoph Hellwig   [SCSI] simplify c...
255
  		scsi_host_free_command(shost, cmd);
b58d91547   FUJITA Tomonori   [SCSI] export scs...
256
  }
b58d91547   FUJITA Tomonori   [SCSI] export scs...
257

eb44820c2   Rob Landley   [SCSI] Add Docume...
258
259
260
  /**
   * scsi_put_command - Free a scsi command block
   * @cmd: command block to free
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
263
264
265
266
267
   *
   * Returns:	Nothing.
   *
   * Notes:	The command must not belong to any lists.
   */
  void scsi_put_command(struct scsi_cmnd *cmd)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
  	unsigned long flags;
b58d91547   FUJITA Tomonori   [SCSI] export scs...
269

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
271
272
273
  	/* serious error if the command hasn't come from a device list */
  	spin_lock_irqsave(&cmd->device->list_lock, flags);
  	BUG_ON(list_empty(&cmd->list));
  	list_del_init(&cmd->list);
b58d91547   FUJITA Tomonori   [SCSI] export scs...
274
  	spin_unlock_irqrestore(&cmd->device->list_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275

fcc95a763   Bart Van Assche   scsi: remove two ...
276
  	BUG_ON(delayed_work_pending(&cmd->abort_work));
e494f6a72   Hannes Reinecke   [SCSI] improved e...
277

047963368   Christoph Hellwig   [SCSI] do not man...
278
  	__scsi_put_command(cmd->device->host, cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280

89d9a5679   Christoph Hellwig   [SCSI] add suppor...
281
282
  static struct scsi_host_cmd_pool *
  scsi_find_host_cmd_pool(struct Scsi_Host *shost)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
  {
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
  	if (shost->hostt->cmd_size)
  		return shost->hostt->cmd_pool;
  	if (shost->unchecked_isa_dma)
  		return &scsi_cmd_dma_pool;
  	return &scsi_cmd_pool;
  }
  
  static void
  scsi_free_host_cmd_pool(struct scsi_host_cmd_pool *pool)
  {
  	kfree(pool->sense_name);
  	kfree(pool->cmd_name);
  	kfree(pool);
  }
  
  static struct scsi_host_cmd_pool *
  scsi_alloc_host_cmd_pool(struct Scsi_Host *shost)
  {
  	struct scsi_host_template *hostt = shost->hostt;
  	struct scsi_host_cmd_pool *pool;
  
  	pool = kzalloc(sizeof(*pool), GFP_KERNEL);
  	if (!pool)
  		return NULL;
884ffee01   James Bottomley   scsi: use short d...
308
309
  	pool->cmd_name = kasprintf(GFP_KERNEL, "%s_cmd", hostt->proc_name);
  	pool->sense_name = kasprintf(GFP_KERNEL, "%s_sense", hostt->proc_name);
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
310
311
312
313
314
315
316
317
318
319
  	if (!pool->cmd_name || !pool->sense_name) {
  		scsi_free_host_cmd_pool(pool);
  		return NULL;
  	}
  
  	pool->slab_flags = SLAB_HWCACHE_ALIGN;
  	if (shost->unchecked_isa_dma) {
  		pool->slab_flags |= SLAB_CACHE_DMA;
  		pool->gfp_mask = __GFP_DMA;
  	}
f6105c080   Juergen Gross   [SCSI] save comma...
320
321
322
  
  	if (hostt->cmd_size)
  		hostt->cmd_pool = pool;
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
323
324
325
326
327
328
329
  	return pool;
  }
  
  static struct scsi_host_cmd_pool *
  scsi_get_host_cmd_pool(struct Scsi_Host *shost)
  {
  	struct scsi_host_template *hostt = shost->hostt;
1c353f7d6   James Bottomley   [SCSI] export com...
330
  	struct scsi_host_cmd_pool *retval = NULL, *pool;
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
331
  	size_t cmd_size = sizeof(struct scsi_cmnd) + hostt->cmd_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
333
  	/*
  	 * Select a command slab for this host and create it if not
eb44820c2   Rob Landley   [SCSI] Add Docume...
334
  	 * yet existent.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
  	 */
0b9506723   Arjan van de Ven   [SCSI] turn most ...
336
  	mutex_lock(&host_cmd_pool_mutex);
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
337
338
339
340
341
342
  	pool = scsi_find_host_cmd_pool(shost);
  	if (!pool) {
  		pool = scsi_alloc_host_cmd_pool(shost);
  		if (!pool)
  			goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
  	if (!pool->users) {
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
344
  		pool->cmd_slab = kmem_cache_create(pool->cmd_name, cmd_size, 0,
5b7f16804   James Bottomley   [SCSI] don't use ...
345
346
  						   pool->slab_flags, NULL);
  		if (!pool->cmd_slab)
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
347
  			goto out_free_pool;
5b7f16804   James Bottomley   [SCSI] don't use ...
348
349
350
351
  
  		pool->sense_slab = kmem_cache_create(pool->sense_name,
  						     SCSI_SENSE_BUFFERSIZE, 0,
  						     pool->slab_flags, NULL);
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
352
353
  		if (!pool->sense_slab)
  			goto out_free_slab;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
355
356
  	}
  
  	pool->users++;
1c353f7d6   James Bottomley   [SCSI] export com...
357
  	retval = pool;
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
358
  out:
0b9506723   Arjan van de Ven   [SCSI] turn most ...
359
  	mutex_unlock(&host_cmd_pool_mutex);
1c353f7d6   James Bottomley   [SCSI] export com...
360
  	return retval;
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
361
362
363
364
  
  out_free_slab:
  	kmem_cache_destroy(pool->cmd_slab);
  out_free_pool:
f6105c080   Juergen Gross   [SCSI] save comma...
365
  	if (hostt->cmd_size) {
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
366
  		scsi_free_host_cmd_pool(pool);
f6105c080   Juergen Gross   [SCSI] save comma...
367
368
  		hostt->cmd_pool = NULL;
  	}
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
369
  	goto out;
1c353f7d6   James Bottomley   [SCSI] export com...
370
  }
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
371
  static void scsi_put_host_cmd_pool(struct Scsi_Host *shost)
1c353f7d6   James Bottomley   [SCSI] export com...
372
  {
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
373
  	struct scsi_host_template *hostt = shost->hostt;
1c353f7d6   James Bottomley   [SCSI] export com...
374
  	struct scsi_host_cmd_pool *pool;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375

1c353f7d6   James Bottomley   [SCSI] export com...
376
  	mutex_lock(&host_cmd_pool_mutex);
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
377
  	pool = scsi_find_host_cmd_pool(shost);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
  	/*
1c353f7d6   James Bottomley   [SCSI] export com...
379
380
381
  	 * This may happen if a driver has a mismatched get and put
  	 * of the command pool; the driver should be implicated in
  	 * the stack trace
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
  	 */
1c353f7d6   James Bottomley   [SCSI] export com...
383
  	BUG_ON(pool->users == 0);
de25deb18   FUJITA Tomonori   [SCSI] use dynami...
384

5b7f16804   James Bottomley   [SCSI] don't use ...
385
386
387
  	if (!--pool->users) {
  		kmem_cache_destroy(pool->cmd_slab);
  		kmem_cache_destroy(pool->sense_slab);
f6105c080   Juergen Gross   [SCSI] save comma...
388
  		if (hostt->cmd_size) {
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
389
  			scsi_free_host_cmd_pool(pool);
f6105c080   Juergen Gross   [SCSI] save comma...
390
391
  			hostt->cmd_pool = NULL;
  		}
5b7f16804   James Bottomley   [SCSI] don't use ...
392
  	}
0b9506723   Arjan van de Ven   [SCSI] turn most ...
393
  	mutex_unlock(&host_cmd_pool_mutex);
1c353f7d6   James Bottomley   [SCSI] export com...
394
395
396
  }
  
  /**
1c353f7d6   James Bottomley   [SCSI] export com...
397
398
399
400
401
402
403
404
405
406
407
   * scsi_setup_command_freelist - Setup the command freelist for a scsi host.
   * @shost: host to allocate the freelist for.
   *
   * Description: The command freelist protects against system-wide out of memory
   * deadlock by preallocating one SCSI command structure for each host, so the
   * system can always write to a swap file on a device associated with that host.
   *
   * Returns:	Nothing.
   */
  int scsi_setup_command_freelist(struct Scsi_Host *shost)
  {
1c353f7d6   James Bottomley   [SCSI] export com...
408
  	const gfp_t gfp_mask = shost->unchecked_isa_dma ? GFP_DMA : GFP_KERNEL;
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
409
  	struct scsi_cmnd *cmd;
1c353f7d6   James Bottomley   [SCSI] export com...
410
411
412
  
  	spin_lock_init(&shost->free_list_lock);
  	INIT_LIST_HEAD(&shost->free_list);
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
413
  	shost->cmd_pool = scsi_get_host_cmd_pool(shost);
1c353f7d6   James Bottomley   [SCSI] export com...
414
415
416
417
418
419
  	if (!shost->cmd_pool)
  		return -ENOMEM;
  
  	/*
  	 * Get one backup command for this host.
  	 */
7027ad72a   Martin K. Petersen   [SCSI] Support de...
420
  	cmd = scsi_host_alloc_command(shost, gfp_mask);
1c353f7d6   James Bottomley   [SCSI] export com...
421
  	if (!cmd) {
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
422
  		scsi_put_host_cmd_pool(shost);
61d7416a2   Alan D. Brunelle   [SCSI] bug fix fo...
423
  		shost->cmd_pool = NULL;
1c353f7d6   James Bottomley   [SCSI] export com...
424
425
426
427
  		return -ENOMEM;
  	}
  	list_add(&cmd->list, &shost->free_list);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
  }
eb44820c2   Rob Landley   [SCSI] Add Docume...
429
430
431
  /**
   * scsi_destroy_command_freelist - Release the command freelist for a scsi host.
   * @shost: host whose freelist is going to be destroyed
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
433
434
   */
  void scsi_destroy_command_freelist(struct Scsi_Host *shost)
  {
61d7416a2   Alan D. Brunelle   [SCSI] bug fix fo...
435
436
437
438
439
440
  	/*
  	 * If cmd_pool is NULL the free list was not initialized, so
  	 * do not attempt to release resources.
  	 */
  	if (!shost->cmd_pool)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
442
443
444
445
  	while (!list_empty(&shost->free_list)) {
  		struct scsi_cmnd *cmd;
  
  		cmd = list_entry(shost->free_list.next, struct scsi_cmnd, list);
  		list_del_init(&cmd->list);
7c2833412   Christoph Hellwig   [SCSI] simplify c...
446
  		scsi_host_free_command(shost, cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
  	}
1c353f7d6   James Bottomley   [SCSI] export com...
448
  	shost->cmd_pool = NULL;
89d9a5679   Christoph Hellwig   [SCSI] add suppor...
449
  	scsi_put_host_cmd_pool(shost);
de25deb18   FUJITA Tomonori   [SCSI] use dynami...
450
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
452
453
454
  #ifdef CONFIG_SCSI_LOGGING
  void scsi_log_send(struct scsi_cmnd *cmd)
  {
  	unsigned int level;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
456
457
458
459
460
  
  	/*
  	 * If ML QUEUE log level is greater than or equal to:
  	 *
  	 * 1: nothing (match completion)
  	 *
c11c004b1   Hannes Reinecke   scsi: simplify sc...
461
  	 * 2: log opcode + command of all commands + cmd address
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
  	 *
c11c004b1   Hannes Reinecke   scsi: simplify sc...
463
  	 * 3: same as 2
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
  	 *
a4a6afb47   Hannes Reinecke   scsi: Do not disp...
465
  	 * 4: same as 3
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466
467
468
469
470
  	 */
  	if (unlikely(scsi_logging_level)) {
  		level = SCSI_LOG_LEVEL(SCSI_LOG_MLQUEUE_SHIFT,
  				       SCSI_LOG_MLQUEUE_BITS);
  		if (level > 1) {
c11c004b1   Hannes Reinecke   scsi: simplify sc...
471
472
473
  			scmd_printk(KERN_INFO, cmd,
  				    "Send: scmd 0x%p
  ", cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
  			scsi_print_command(cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
476
477
478
479
480
481
  		}
  	}
  }
  
  void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
  {
  	unsigned int level;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
483
484
485
486
487
488
489
490
  
  	/*
  	 * If ML COMPLETE log level is greater than or equal to:
  	 *
  	 * 1: log disposition, result, opcode + command, and conditionally
  	 * sense data for failures or non SUCCESS dispositions.
  	 *
  	 * 2: same as 1 but for all command completions.
  	 *
c11c004b1   Hannes Reinecke   scsi: simplify sc...
491
  	 * 3: same as 2
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
493
494
495
496
497
498
499
  	 *
  	 * 4: same as 3 plus dump extra junk
  	 */
  	if (unlikely(scsi_logging_level)) {
  		level = SCSI_LOG_LEVEL(SCSI_LOG_MLCOMPLETE_SHIFT,
  				       SCSI_LOG_MLCOMPLETE_BITS);
  		if (((level > 0) && (cmd->result || disposition != SUCCESS)) ||
  		    (level > 1)) {
026f8da8d   Hannes Reinecke   scsi: use per-cpu...
500
  			scsi_print_result(cmd, "Done", disposition);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
  			scsi_print_command(cmd);
a4d04a4cd   Martin K. Petersen   [SCSI] Make error...
502
  			if (status_byte(cmd->result) & CHECK_CONDITION)
d811b848e   Hannes Reinecke   scsi: use sdev as...
503
  				scsi_print_sense(cmd);
a4d04a4cd   Martin K. Petersen   [SCSI] Make error...
504
505
506
507
  			if (level > 3)
  				scmd_printk(KERN_INFO, cmd,
  					    "scsi host busy %d failed %d
  ",
746650160   Christoph Hellwig   scsi: convert hos...
508
  					    atomic_read(&cmd->device->host->host_busy),
a4d04a4cd   Martin K. Petersen   [SCSI] Make error...
509
  					    cmd->device->host->host_failed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510
511
512
513
  		}
  	}
  }
  #endif
eb44820c2   Rob Landley   [SCSI] Add Docume...
514
515
516
517
518
519
  /**
   * scsi_cmd_get_serial - Assign a serial number to a command
   * @host: the scsi host
   * @cmd: command to assign serial number to
   *
   * Description: a serial number identifies a request for error recovery
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
521
   * and debugging purposes.  Protected by the Host_Lock of host.
   */
f281233d3   Jeff Garzik   SCSI host lock pu...
522
  void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
524
525
526
  {
  	cmd->serial_number = host->cmd_serial_number++;
  	if (cmd->serial_number == 0) 
  		cmd->serial_number = host->cmd_serial_number++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
  }
f281233d3   Jeff Garzik   SCSI host lock pu...
528
  EXPORT_SYMBOL(scsi_cmd_get_serial);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529

eb44820c2   Rob Landley   [SCSI] Add Docume...
530
  /**
eb44820c2   Rob Landley   [SCSI] Add Docume...
531
532
   * scsi_finish_command - cleanup and pass command back to upper layer
   * @cmd: the command
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
   *
eb44820c2   Rob Landley   [SCSI] Add Docume...
534
   * Description: Pass command off to upper layer for finishing of I/O
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
537
538
539
540
   *              request, waking processes that are waiting on results,
   *              etc.
   */
  void scsi_finish_command(struct scsi_cmnd *cmd)
  {
  	struct scsi_device *sdev = cmd->device;
f0c0a376d   Mike Christie   [SCSI] Add helper...
541
  	struct scsi_target *starget = scsi_target(sdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542
  	struct Scsi_Host *shost = sdev->host;
7b3d9545f   Linus Torvalds   Revert "scsi: rev...
543
544
  	struct scsi_driver *drv;
  	unsigned int good_bytes;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
546
  
  	scsi_device_unbusy(sdev);
cd9070c9c   Christoph Hellwig   scsi: fix the {ho...
547
548
549
550
551
552
553
554
555
556
  	/*
  	 * Clear the flags that say that the device/target/host is no longer
  	 * capable of accepting new commands.
  	 */
  	if (atomic_read(&shost->host_blocked))
  		atomic_set(&shost->host_blocked, 0);
  	if (atomic_read(&starget->target_blocked))
  		atomic_set(&starget->target_blocked, 0);
  	if (atomic_read(&sdev->device_blocked))
  		atomic_set(&sdev->device_blocked, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
558
559
560
561
562
563
  
  	/*
  	 * If we have valid sense information, then some kind of recovery
  	 * must have taken place.  Make a note of this.
  	 */
  	if (SCSI_SENSE_VALID(cmd))
  		cmd->result |= (DRIVER_SENSE << 24);
3bf743e7c   Jeff Garzik   [SCSI] use {sdev,...
564
565
566
567
  	SCSI_LOG_MLCOMPLETE(4, sdev_printk(KERN_INFO, sdev,
  				"Notifying upper driver of completion "
  				"(result %x)
  ", cmd->result));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568

f18573abc   FUJITA Tomonori   block: move the p...
569
  	good_bytes = scsi_bufflen(cmd);
7b3d9545f   Linus Torvalds   Revert "scsi: rev...
570
          if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
427e59f09   James Bottomley   [SCSI] make use o...
571
  		int old_good_bytes = good_bytes;
7b3d9545f   Linus Torvalds   Revert "scsi: rev...
572
573
574
  		drv = scsi_cmd_to_driver(cmd);
  		if (drv->done)
  			good_bytes = drv->done(cmd);
427e59f09   James Bottomley   [SCSI] make use o...
575
576
577
578
579
580
581
582
  		/*
  		 * USB may not give sense identifying bad sector and
  		 * simply return a residue instead, so subtract off the
  		 * residue if drv->done() error processing indicates no
  		 * change to the completion length.
  		 */
  		if (good_bytes == old_good_bytes)
  			good_bytes -= scsi_get_resid(cmd);
7b3d9545f   Linus Torvalds   Revert "scsi: rev...
583
584
  	}
  	scsi_io_completion(cmd, good_bytes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586

eb44820c2   Rob Landley   [SCSI] Add Docume...
587
  /**
db5ed4dfd   Christoph Hellwig   scsi: drop reason...
588
   * scsi_change_queue_depth - change a device's queue depth
eb44820c2   Rob Landley   [SCSI] Add Docume...
589
   * @sdev: SCSI Device in question
db5ed4dfd   Christoph Hellwig   scsi: drop reason...
590
   * @depth: number of commands allowed to be queued to the driver
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591
   *
db5ed4dfd   Christoph Hellwig   scsi: drop reason...
592
   * Sets the device queue depth and returns the new value.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
593
   */
db5ed4dfd   Christoph Hellwig   scsi: drop reason...
594
  int scsi_change_queue_depth(struct scsi_device *sdev, int depth)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
  {
64d513ac3   Christoph Hellwig   scsi: use host wi...
596
597
598
  	if (depth > 0) {
  		sdev->queue_depth = depth;
  		wmb();
885ace9e2   Mike Christie   [SCSI] fix shared...
599
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600

db5ed4dfd   Christoph Hellwig   scsi: drop reason...
601
  	return sdev->queue_depth;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
602
  }
db5ed4dfd   Christoph Hellwig   scsi: drop reason...
603
  EXPORT_SYMBOL(scsi_change_queue_depth);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604

eb44820c2   Rob Landley   [SCSI] Add Docume...
605
606
607
608
609
  /**
   * scsi_track_queue_full - track QUEUE_FULL events to adjust queue depth
   * @sdev: SCSI Device in question
   * @depth: Current number of outstanding SCSI commands on this device,
   *         not counting the one returned as QUEUE_FULL.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
   *
eb44820c2   Rob Landley   [SCSI] Add Docume...
611
   * Description:	This function will track successive QUEUE_FULL events on a
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
613
614
   * 		specific SCSI device to determine if and when there is a
   * 		need to adjust the queue depth on the device.
   *
eb44820c2   Rob Landley   [SCSI] Add Docume...
615
   * Returns:	0 - No change needed, >0 - Adjust queue depth to this new depth,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
616
617
618
619
620
621
622
623
624
625
   * 		-1 - Drop back to untagged operation using host->cmd_per_lun
   * 			as the untagged command depth
   *
   * Lock Status:	None held on entry
   *
   * Notes:	Low level drivers may call this at any time and we will do
   * 		"The Right Thing."  We are interrupt context safe.
   */
  int scsi_track_queue_full(struct scsi_device *sdev, int depth)
  {
4a84067db   Vasu Dev   [SCSI] add queue_...
626
627
628
629
630
631
632
  
  	/*
  	 * Don't let QUEUE_FULLs on the same
  	 * jiffies count, they could all be from
  	 * same event.
  	 */
  	if ((jiffies >> 4) == (sdev->last_queue_full_time >> 4))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
633
  		return 0;
4a84067db   Vasu Dev   [SCSI] add queue_...
634
  	sdev->last_queue_full_time = jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
636
637
638
639
640
641
642
643
  	if (sdev->last_queue_full_depth != depth) {
  		sdev->last_queue_full_count = 1;
  		sdev->last_queue_full_depth = depth;
  	} else {
  		sdev->last_queue_full_count++;
  	}
  
  	if (sdev->last_queue_full_count <= 10)
  		return 0;
609aa22f3   Christoph Hellwig   scsi: remove orde...
644

db5ed4dfd   Christoph Hellwig   scsi: drop reason...
645
  	return scsi_change_queue_depth(sdev, depth);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646
647
648
649
  }
  EXPORT_SYMBOL(scsi_track_queue_full);
  
  /**
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
650
651
652
653
654
655
656
657
658
   * scsi_vpd_inquiry - Request a device provide us with a VPD page
   * @sdev: The device to ask
   * @buffer: Where to put the result
   * @page: Which Vital Product Data to return
   * @len: The length of the buffer
   *
   * This is an internal helper function.  You probably want to use
   * scsi_get_vpd_page instead.
   *
bc8945df3   Hannes Reinecke   [SCSI] Return VPD...
659
   * Returns size of the vpd page on success or a negative error number.
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
660
661
662
663
664
665
   */
  static int scsi_vpd_inquiry(struct scsi_device *sdev, unsigned char *buffer,
  							u8 page, unsigned len)
  {
  	int result;
  	unsigned char cmd[16];
bc8945df3   Hannes Reinecke   [SCSI] Return VPD...
666
667
  	if (len < 4)
  		return -EINVAL;
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
668
669
670
671
672
673
674
675
676
677
678
679
  	cmd[0] = INQUIRY;
  	cmd[1] = 1;		/* EVPD */
  	cmd[2] = page;
  	cmd[3] = len >> 8;
  	cmd[4] = len & 0xff;
  	cmd[5] = 0;		/* Control byte */
  
  	/*
  	 * I'm not convinced we need to try quite this hard to get VPD, but
  	 * all the existing users tried this hard.
  	 */
  	result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer,
95a3639e2   James Bottomley   [SCSI] fix bugs i...
680
  				  len, NULL, 30 * HZ, 3, NULL);
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
681
  	if (result)
bc8945df3   Hannes Reinecke   [SCSI] Return VPD...
682
  		return -EIO;
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
683
684
685
686
  
  	/* Sanity check that we got the page back that we asked for */
  	if (buffer[1] != page)
  		return -EIO;
bc8945df3   Hannes Reinecke   [SCSI] Return VPD...
687
  	return get_unaligned_be16(&buffer[2]) + 4;
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
688
689
690
691
692
693
  }
  
  /**
   * scsi_get_vpd_page - Get Vital Product Data from a SCSI device
   * @sdev: The device to ask
   * @page: Which Vital Product Data to return
786f8ba2e   Randy Dunlap   scsi.c: add missi...
694
695
   * @buf: where to store the VPD
   * @buf_len: number of bytes in the VPD buffer area
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
696
697
698
699
700
701
702
703
   *
   * SCSI devices may optionally supply Vital Product Data.  Each 'page'
   * of VPD is defined in the appropriate SCSI document (eg SPC, SBC).
   * If the device supports this VPD page, this routine returns a pointer
   * to a buffer containing the data from that page.  The caller is
   * responsible for calling kfree() on this pointer when it is no longer
   * needed.  If we cannot retrieve the VPD page this routine returns %NULL.
   */
e3deec090   James Bottomley   [SCSI] eliminate ...
704
705
  int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf,
  		      int buf_len)
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
706
707
  {
  	int i, result;
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
708

7562523e8   Martin K. Petersen   [SCSI] Don't atte...
709
710
  	if (sdev->skip_vpd_pages)
  		goto fail;
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
711
  	/* Ask for all the pages supported by this device */
e3deec090   James Bottomley   [SCSI] eliminate ...
712
  	result = scsi_vpd_inquiry(sdev, buf, 0, buf_len);
bc8945df3   Hannes Reinecke   [SCSI] Return VPD...
713
  	if (result < 4)
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
714
715
716
717
  		goto fail;
  
  	/* If the user actually wanted this page, we can skip the rest */
  	if (page == 0)
16d3ea26f   Martin K. Petersen   [SCSI] Fix VPD in...
718
  		return 0;
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
719

bc8945df3   Hannes Reinecke   [SCSI] Return VPD...
720
721
  	for (i = 4; i < min(result, buf_len); i++)
  		if (buf[i] == page)
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
722
  			goto found;
e3deec090   James Bottomley   [SCSI] eliminate ...
723

bc8945df3   Hannes Reinecke   [SCSI] Return VPD...
724
  	if (i < result && i >= buf_len)
e3deec090   James Bottomley   [SCSI] eliminate ...
725
726
  		/* ran off the end of the buffer, give us benefit of doubt */
  		goto found;
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
727
728
729
730
  	/* The device claims it doesn't support the requested page */
  	goto fail;
  
   found:
e3deec090   James Bottomley   [SCSI] eliminate ...
731
  	result = scsi_vpd_inquiry(sdev, buf, page, buf_len);
bc8945df3   Hannes Reinecke   [SCSI] Return VPD...
732
  	if (result < 0)
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
733
  		goto fail;
e3deec090   James Bottomley   [SCSI] eliminate ...
734
  	return 0;
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
735
736
  
   fail:
e3deec090   James Bottomley   [SCSI] eliminate ...
737
  	return -EINVAL;
881a256d8   Matthew Wilcox   [SCSI] Add VPD he...
738
739
740
741
  }
  EXPORT_SYMBOL_GPL(scsi_get_vpd_page);
  
  /**
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
742
743
744
745
746
747
748
749
750
751
752
753
754
755
   * scsi_attach_vpd - Attach Vital Product Data to a SCSI device structure
   * @sdev: The device to ask
   *
   * Attach the 'Device Identification' VPD page (0x83) and the
   * 'Unit Serial Number' VPD page (0x80) to a SCSI device
   * structure. This information can be used to identify the device
   * uniquely.
   */
  void scsi_attach_vpd(struct scsi_device *sdev)
  {
  	int result, i;
  	int vpd_len = SCSI_VPD_PG_LEN;
  	int pg80_supported = 0;
  	int pg83_supported = 0;
09e2b0b14   Hannes Reinecke   scsi: rescan VPD ...
756
  	unsigned char __rcu *vpd_buf, *orig_vpd_buf = NULL;
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
  
  	if (sdev->skip_vpd_pages)
  		return;
  retry_pg0:
  	vpd_buf = kmalloc(vpd_len, GFP_KERNEL);
  	if (!vpd_buf)
  		return;
  
  	/* Ask for all the pages supported by this device */
  	result = scsi_vpd_inquiry(sdev, vpd_buf, 0, vpd_len);
  	if (result < 0) {
  		kfree(vpd_buf);
  		return;
  	}
  	if (result > vpd_len) {
  		vpd_len = result;
  		kfree(vpd_buf);
  		goto retry_pg0;
  	}
  
  	for (i = 4; i < result; i++) {
  		if (vpd_buf[i] == 0x80)
  			pg80_supported = 1;
  		if (vpd_buf[i] == 0x83)
  			pg83_supported = 1;
  	}
  	kfree(vpd_buf);
  	vpd_len = SCSI_VPD_PG_LEN;
  
  	if (pg80_supported) {
  retry_pg80:
  		vpd_buf = kmalloc(vpd_len, GFP_KERNEL);
  		if (!vpd_buf)
  			return;
  
  		result = scsi_vpd_inquiry(sdev, vpd_buf, 0x80, vpd_len);
  		if (result < 0) {
  			kfree(vpd_buf);
  			return;
  		}
  		if (result > vpd_len) {
  			vpd_len = result;
  			kfree(vpd_buf);
  			goto retry_pg80;
  		}
09e2b0b14   Hannes Reinecke   scsi: rescan VPD ...
802
803
  		mutex_lock(&sdev->inquiry_mutex);
  		orig_vpd_buf = sdev->vpd_pg80;
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
804
  		sdev->vpd_pg80_len = result;
09e2b0b14   Hannes Reinecke   scsi: rescan VPD ...
805
806
807
808
809
810
811
  		rcu_assign_pointer(sdev->vpd_pg80, vpd_buf);
  		mutex_unlock(&sdev->inquiry_mutex);
  		synchronize_rcu();
  		if (orig_vpd_buf) {
  			kfree(orig_vpd_buf);
  			orig_vpd_buf = NULL;
  		}
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
  		vpd_len = SCSI_VPD_PG_LEN;
  	}
  
  	if (pg83_supported) {
  retry_pg83:
  		vpd_buf = kmalloc(vpd_len, GFP_KERNEL);
  		if (!vpd_buf)
  			return;
  
  		result = scsi_vpd_inquiry(sdev, vpd_buf, 0x83, vpd_len);
  		if (result < 0) {
  			kfree(vpd_buf);
  			return;
  		}
  		if (result > vpd_len) {
  			vpd_len = result;
  			kfree(vpd_buf);
  			goto retry_pg83;
  		}
09e2b0b14   Hannes Reinecke   scsi: rescan VPD ...
831
832
  		mutex_lock(&sdev->inquiry_mutex);
  		orig_vpd_buf = sdev->vpd_pg83;
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
833
  		sdev->vpd_pg83_len = result;
09e2b0b14   Hannes Reinecke   scsi: rescan VPD ...
834
835
836
837
838
  		rcu_assign_pointer(sdev->vpd_pg83, vpd_buf);
  		mutex_unlock(&sdev->inquiry_mutex);
  		synchronize_rcu();
  		if (orig_vpd_buf)
  			kfree(orig_vpd_buf);
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
839
840
841
842
  	}
  }
  
  /**
3c6bdaeab   Martin K. Petersen   [SCSI] Add a repo...
843
844
845
846
847
848
849
   * scsi_report_opcode - Find out if a given command opcode is supported
   * @sdev:	scsi device to query
   * @buffer:	scratch buffer (must be at least 20 bytes long)
   * @len:	length of buffer
   * @opcode:	opcode for command to look up
   *
   * Uses the REPORT SUPPORTED OPERATION CODES to look up the given
66c28f971   Martin K. Petersen   [SCSI] sd: Update...
850
851
   * opcode. Returns -EINVAL if RSOC fails, 0 if the command opcode is
   * unsupported and 1 if the device claims to support the command.
3c6bdaeab   Martin K. Petersen   [SCSI] Add a repo...
852
853
854
855
856
857
858
859
860
   */
  int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
  		       unsigned int len, unsigned char opcode)
  {
  	unsigned char cmd[16];
  	struct scsi_sense_hdr sshdr;
  	int result;
  
  	if (sdev->no_report_opcodes || sdev->scsi_level < SCSI_SPC_3)
66c28f971   Martin K. Petersen   [SCSI] sd: Update...
861
  		return -EINVAL;
3c6bdaeab   Martin K. Petersen   [SCSI] Add a repo...
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
  
  	memset(cmd, 0, 16);
  	cmd[0] = MAINTENANCE_IN;
  	cmd[1] = MI_REPORT_SUPPORTED_OPERATION_CODES;
  	cmd[2] = 1;		/* One command format */
  	cmd[3] = opcode;
  	put_unaligned_be32(len, &cmd[6]);
  	memset(buffer, 0, len);
  
  	result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len,
  				  &sshdr, 30 * HZ, 3, NULL);
  
  	if (result && scsi_sense_valid(&sshdr) &&
  	    sshdr.sense_key == ILLEGAL_REQUEST &&
  	    (sshdr.asc == 0x20 || sshdr.asc == 0x24) && sshdr.ascq == 0x00)
66c28f971   Martin K. Petersen   [SCSI] sd: Update...
877
  		return -EINVAL;
3c6bdaeab   Martin K. Petersen   [SCSI] Add a repo...
878
879
880
881
882
883
884
885
886
  
  	if ((buffer[1] & 3) == 3) /* Command supported */
  		return 1;
  
  	return 0;
  }
  EXPORT_SYMBOL(scsi_report_opcode);
  
  /**
eb44820c2   Rob Landley   [SCSI] Add Docume...
887
   * scsi_device_get  -  get an additional reference to a scsi_device
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
888
889
   * @sdev:	device to get a reference to
   *
eb44820c2   Rob Landley   [SCSI] Add Docume...
890
   * Description: Gets a reference to the scsi_device and increments the use count
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
891
892
   * of the underlying LLDD module.  You must hold host_lock of the
   * parent Scsi_Host or already have a reference when calling this.
cff549e48   Christoph Hellwig   scsi: proper stat...
893
894
895
   *
   * This will fail if a device is deleted or cancelled, or when the LLD module
   * is in the process of being unloaded.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
896
897
898
   */
  int scsi_device_get(struct scsi_device *sdev)
  {
cff549e48   Christoph Hellwig   scsi: proper stat...
899
900
  	if (sdev->sdev_state == SDEV_DEL || sdev->sdev_state == SDEV_CANCEL)
  		goto fail;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
901
  	if (!get_device(&sdev->sdev_gendev))
cff549e48   Christoph Hellwig   scsi: proper stat...
902
903
904
  		goto fail;
  	if (!try_module_get(sdev->host->hostt->module))
  		goto fail_put_device;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
  	return 0;
cff549e48   Christoph Hellwig   scsi: proper stat...
906
907
908
909
910
  
  fail_put_device:
  	put_device(&sdev->sdev_gendev);
  fail:
  	return -ENXIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
911
912
913
914
915
916
917
  }
  EXPORT_SYMBOL(scsi_device_get);
  
  /**
   * scsi_device_put  -  release a reference to a scsi_device
   * @sdev:	device to release a reference on.
   *
eb44820c2   Rob Landley   [SCSI] Add Docume...
918
919
   * Description: Release a reference to the scsi_device and decrements the use
   * count of the underlying LLDD module.  The device is freed once the last
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
920
921
922
923
   * user vanishes.
   */
  void scsi_device_put(struct scsi_device *sdev)
  {
dc4515ea2   Rusty Russell   scsi: always incr...
924
  	module_put(sdev->host->hostt->module);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
925
926
927
  	put_device(&sdev->sdev_gendev);
  }
  EXPORT_SYMBOL(scsi_device_put);
eb44820c2   Rob Landley   [SCSI] Add Docume...
928
  /* helper for shost_for_each_device, see that for documentation */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
  struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *shost,
  					   struct scsi_device *prev)
  {
  	struct list_head *list = (prev ? &prev->siblings : &shost->__devices);
  	struct scsi_device *next = NULL;
  	unsigned long flags;
  
  	spin_lock_irqsave(shost->host_lock, flags);
  	while (list->next != &shost->__devices) {
  		next = list_entry(list->next, struct scsi_device, siblings);
  		/* skip devices that we can't get a reference to */
  		if (!scsi_device_get(next))
  			break;
  		next = NULL;
  		list = list->next;
  	}
  	spin_unlock_irqrestore(shost->host_lock, flags);
  
  	if (prev)
  		scsi_device_put(prev);
  	return next;
  }
  EXPORT_SYMBOL(__scsi_iterate_devices);
  
  /**
   * starget_for_each_device  -  helper to walk all devices of a target
   * @starget:	target whose devices we want to iterate over.
eb44820c2   Rob Landley   [SCSI] Add Docume...
956
957
   * @data:	Opaque passed to each function call.
   * @fn:		Function to call on each device
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
   *
522939d45   Maciej W. Rozycki   esp_scsi: fix res...
959
   * This traverses over each device of @starget.  The devices have
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
960
961
962
   * a reference that must be released by scsi_host_put when breaking
   * out of the loop.
   */
522939d45   Maciej W. Rozycki   esp_scsi: fix res...
963
  void starget_for_each_device(struct scsi_target *starget, void *data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
964
965
966
967
968
969
970
971
972
973
974
975
976
977
  		     void (*fn)(struct scsi_device *, void *))
  {
  	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
  	struct scsi_device *sdev;
  
  	shost_for_each_device(sdev, shost) {
  		if ((sdev->channel == starget->channel) &&
  		    (sdev->id == starget->id))
  			fn(sdev, data);
  	}
  }
  EXPORT_SYMBOL(starget_for_each_device);
  
  /**
14f501a4b   Randy Dunlap   [SCSI] kernel-doc...
978
   * __starget_for_each_device - helper to walk all devices of a target (UNLOCKED)
522939d45   Maciej W. Rozycki   esp_scsi: fix res...
979
   * @starget:	target whose devices we want to iterate over.
14f501a4b   Randy Dunlap   [SCSI] kernel-doc...
980
981
   * @data:	parameter for callback @fn()
   * @fn:		callback function that is invoked for each device
522939d45   Maciej W. Rozycki   esp_scsi: fix res...
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
   *
   * This traverses over each device of @starget.  It does _not_
   * take a reference on the scsi_device, so the whole loop must be
   * protected by shost->host_lock.
   *
   * Note:  The only reason why drivers would want to use this is because
   * they need to access the device list in irq context.  Otherwise you
   * really want to use starget_for_each_device instead.
   **/
  void __starget_for_each_device(struct scsi_target *starget, void *data,
  			       void (*fn)(struct scsi_device *, void *))
  {
  	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
  	struct scsi_device *sdev;
  
  	__shost_for_each_device(sdev, shost) {
  		if ((sdev->channel == starget->channel) &&
  		    (sdev->id == starget->id))
  			fn(sdev, data);
  	}
  }
  EXPORT_SYMBOL(__starget_for_each_device);
  
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1006
1007
1008
1009
   * __scsi_device_lookup_by_target - find a device given the target (UNLOCKED)
   * @starget:	SCSI target pointer
   * @lun:	SCSI Logical Unit Number
   *
eb44820c2   Rob Landley   [SCSI] Add Docume...
1010
1011
   * Description: Looks up the scsi_device with the specified @lun for a given
   * @starget.  The returned scsi_device does not have an additional
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1012
   * reference.  You must hold the host's host_lock over this call and
32aeef605   Hannes Reinecke   [SCSI] Skip delet...
1013
1014
   * any access to the returned scsi_device. A scsi_device in state
   * SDEV_DEL is skipped.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
   *
dc8875e10   Randy Dunlap   [SCSI] docbook an...
1016
   * Note:  The only reason why drivers should use this is because
eb44820c2   Rob Landley   [SCSI] Add Docume...
1017
   * they need to access the device list in irq context.  Otherwise you
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1018
1019
1020
   * really want to use scsi_device_lookup_by_target instead.
   **/
  struct scsi_device *__scsi_device_lookup_by_target(struct scsi_target *starget,
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
1021
  						   u64 lun)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
1023
1024
1025
  {
  	struct scsi_device *sdev;
  
  	list_for_each_entry(sdev, &starget->devices, same_target_siblings) {
32aeef605   Hannes Reinecke   [SCSI] Skip delet...
1026
1027
  		if (sdev->sdev_state == SDEV_DEL)
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
  		if (sdev->lun ==lun)
  			return sdev;
  	}
  
  	return NULL;
  }
  EXPORT_SYMBOL(__scsi_device_lookup_by_target);
  
  /**
   * scsi_device_lookup_by_target - find a device given the target
   * @starget:	SCSI target pointer
   * @lun:	SCSI Logical Unit Number
   *
477e608c0   Bartlomiej Zolnierkiewicz   [SCSI] fix docume...
1041
1042
   * Description: Looks up the scsi_device with the specified @lun for a given
   * @starget.  The returned scsi_device has an additional reference that
eb44820c2   Rob Landley   [SCSI] Add Docume...
1043
   * needs to be released with scsi_device_put once you're done with it.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1044
1045
   **/
  struct scsi_device *scsi_device_lookup_by_target(struct scsi_target *starget,
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
1046
  						 u64 lun)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
  {
  	struct scsi_device *sdev;
  	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
  	unsigned long flags;
  
  	spin_lock_irqsave(shost->host_lock, flags);
  	sdev = __scsi_device_lookup_by_target(starget, lun);
  	if (sdev && scsi_device_get(sdev))
  		sdev = NULL;
  	spin_unlock_irqrestore(shost->host_lock, flags);
  
  	return sdev;
  }
  EXPORT_SYMBOL(scsi_device_lookup_by_target);
  
  /**
eb44820c2   Rob Landley   [SCSI] Add Docume...
1063
   * __scsi_device_lookup - find a device given the host (UNLOCKED)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1064
1065
   * @shost:	SCSI host pointer
   * @channel:	SCSI channel (zero if only one channel)
eb44820c2   Rob Landley   [SCSI] Add Docume...
1066
   * @id:		SCSI target number (physical unit number)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1067
1068
   * @lun:	SCSI Logical Unit Number
   *
eb44820c2   Rob Landley   [SCSI] Add Docume...
1069
1070
1071
1072
   * Description: Looks up the scsi_device with the specified @channel, @id, @lun
   * for a given host. The returned scsi_device does not have an additional
   * reference.  You must hold the host's host_lock over this call and any access
   * to the returned scsi_device.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1073
1074
   *
   * Note:  The only reason why drivers would want to use this is because
eb44820c2   Rob Landley   [SCSI] Add Docume...
1075
   * they need to access the device list in irq context.  Otherwise you
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1076
1077
1078
   * really want to use scsi_device_lookup instead.
   **/
  struct scsi_device *__scsi_device_lookup(struct Scsi_Host *shost,
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
1079
  		uint channel, uint id, u64 lun)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
  {
  	struct scsi_device *sdev;
  
  	list_for_each_entry(sdev, &shost->__devices, siblings) {
  		if (sdev->channel == channel && sdev->id == id &&
  				sdev->lun ==lun)
  			return sdev;
  	}
  
  	return NULL;
  }
  EXPORT_SYMBOL(__scsi_device_lookup);
  
  /**
   * scsi_device_lookup - find a device given the host
   * @shost:	SCSI host pointer
   * @channel:	SCSI channel (zero if only one channel)
   * @id:		SCSI target number (physical unit number)
   * @lun:	SCSI Logical Unit Number
   *
eb44820c2   Rob Landley   [SCSI] Add Docume...
1100
1101
1102
   * Description: Looks up the scsi_device with the specified @channel, @id, @lun
   * for a given host.  The returned scsi_device has an additional reference that
   * needs to be released with scsi_device_put once you're done with it.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1103
1104
   **/
  struct scsi_device *scsi_device_lookup(struct Scsi_Host *shost,
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
1105
  		uint channel, uint id, u64 lun)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
  {
  	struct scsi_device *sdev;
  	unsigned long flags;
  
  	spin_lock_irqsave(shost->host_lock, flags);
  	sdev = __scsi_device_lookup(shost, channel, id, lun);
  	if (sdev && scsi_device_get(sdev))
  		sdev = NULL;
  	spin_unlock_irqrestore(shost->host_lock, flags);
  
  	return sdev;
  }
  EXPORT_SYMBOL(scsi_device_lookup);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1119
1120
1121
1122
1123
  MODULE_DESCRIPTION("SCSI core");
  MODULE_LICENSE("GPL");
  
  module_param(scsi_logging_level, int, S_IRUGO|S_IWUSR);
  MODULE_PARM_DESC(scsi_logging_level, "a bit mask of logging levels");
24c20f105   Christoph Hellwig   scsi: add a CONFI...
1124
1125
1126
  #ifdef CONFIG_SCSI_MQ_DEFAULT
  bool scsi_use_blk_mq = true;
  #else
d285203cf   Christoph Hellwig   scsi: add support...
1127
  bool scsi_use_blk_mq = false;
24c20f105   Christoph Hellwig   scsi: add a CONFI...
1128
  #endif
d285203cf   Christoph Hellwig   scsi: add support...
1129
  module_param_named(use_blk_mq, scsi_use_blk_mq, bool, S_IWUSR | S_IRUGO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1130
1131
  static int __init init_scsi(void)
  {
9bf09c238   Jens Axboe   [PATCH] SCSI: scs...
1132
  	int error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
  
  	error = scsi_init_queue();
  	if (error)
  		return error;
  	error = scsi_init_procfs();
  	if (error)
  		goto cleanup_queue;
  	error = scsi_init_devinfo();
  	if (error)
  		goto cleanup_procfs;
  	error = scsi_init_hosts();
  	if (error)
  		goto cleanup_devlist;
  	error = scsi_init_sysctl();
  	if (error)
  		goto cleanup_hosts;
  	error = scsi_sysfs_register();
  	if (error)
  		goto cleanup_sysctl;
84314fd47   James Smart   [SCSI] SCSI and F...
1152
  	scsi_netlink_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
  	printk(KERN_NOTICE "SCSI subsystem initialized
  ");
  	return 0;
  
  cleanup_sysctl:
  	scsi_exit_sysctl();
  cleanup_hosts:
  	scsi_exit_hosts();
  cleanup_devlist:
  	scsi_exit_devinfo();
  cleanup_procfs:
  	scsi_exit_procfs();
  cleanup_queue:
  	scsi_exit_queue();
  	printk(KERN_ERR "SCSI subsystem failed to initialize, error = %d
  ",
  	       -error);
  	return error;
  }
  
  static void __exit exit_scsi(void)
  {
84314fd47   James Smart   [SCSI] SCSI and F...
1175
  	scsi_netlink_exit();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1176
1177
1178
1179
  	scsi_sysfs_unregister();
  	scsi_exit_sysctl();
  	scsi_exit_hosts();
  	scsi_exit_devinfo();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180
1181
  	scsi_exit_procfs();
  	scsi_exit_queue();
a4683487f   Dan Williams   [SCSI] async: mak...
1182
  	async_unregister_domain(&scsi_sd_probe_domain);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1183
1184
1185
1186
  }
  
  subsys_initcall(init_scsi);
  module_exit(exit_scsi);