Blame view

drivers/scsi/scsi_proc.c 11.1 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
  /*
   * linux/drivers/scsi/scsi_proc.c
   *
   * The functions in this file provide an interface between
   * the PROC file system and the SCSI device drivers
   * It is mainly used for debugging, statistics and to pass 
   * information directly to the lowlevel driver.
   *
   * (c) 1995 Michael Neuffer neuffer@goofy.zdv.uni-mainz.de 
   * Version: 0.99.8   last change: 95/09/13
   * 
   * generic command parser provided by: 
   * Andreas Heilwagen <crashcar@informatik.uni-koblenz.de>
   *
   * generic_proc_info() support of xxxx_info() by:
   * Michael A. Griffith <grif@acm.org>
   */
  
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/string.h>
  #include <linux/mm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
26
  #include <linux/proc_fs.h>
  #include <linux/errno.h>
  #include <linux/blkdev.h>
  #include <linux/seq_file.h>
0b9506723   Arjan van de Ven   [SCSI] turn most ...
27
  #include <linux/mutex.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
28
  #include <linux/gfp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
33
  #include <asm/uaccess.h>
  
  #include <scsi/scsi.h>
  #include <scsi/scsi_device.h>
  #include <scsi/scsi_host.h>
e02f3f592   Christoph Hellwig   [SCSI] remove tar...
34
  #include <scsi/scsi_transport.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
37
38
39
40
41
42
43
44
45
  
  #include "scsi_priv.h"
  #include "scsi_logging.h"
  
  
  /* 4K page size, but our output routines, use some slack for overruns */
  #define PROC_BLOCK_SIZE (3*1024)
  
  static struct proc_dir_entry *proc_scsi;
  
  /* Protect sht->present and sht->proc_dir */
0b9506723   Arjan van de Ven   [SCSI] turn most ...
46
  static DEFINE_MUTEX(global_host_template_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47

0ffddfbb8   Al Viro   scsi: saner repla...
48
49
50
  static ssize_t proc_scsi_host_write(struct file *file, const char __user *buf,
                             size_t count, loff_t *ppos)
  {
d9dda78ba   Al Viro   procfs: new helpe...
51
  	struct Scsi_Host *shost = PDE_DATA(file_inode(file));
0ffddfbb8   Al Viro   scsi: saner repla...
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  	ssize_t ret = -ENOMEM;
  	char *page;
      
  	if (count > PROC_BLOCK_SIZE)
  		return -EOVERFLOW;
  
  	if (!shost->hostt->write_info)
  		return -EINVAL;
  
  	page = (char *)__get_free_page(GFP_KERNEL);
  	if (page) {
  		ret = -EFAULT;
  		if (copy_from_user(page, buf, count))
  			goto out;
  		ret = shost->hostt->write_info(shost, page, count);
  	}
  out:
  	free_page((unsigned long)page);
  	return ret;
  }
  
  static int proc_scsi_show(struct seq_file *m, void *v)
  {
  	struct Scsi_Host *shost = m->private;
  	return shost->hostt->show_info(m, shost);
  }
  
  static int proc_scsi_host_open(struct inode *inode, struct file *file)
  {
d9dda78ba   Al Viro   procfs: new helpe...
81
  	return single_open_size(file, proc_scsi_show, PDE_DATA(inode),
859d22f9c   Al Viro   scsi_proc: make p...
82
  				4 * PAGE_SIZE);
0ffddfbb8   Al Viro   scsi: saner repla...
83
84
85
86
  }
  
  static const struct file_operations proc_scsi_fops = {
  	.open = proc_scsi_host_open,
801d9d26b   Jan Beulich   fix buffer leak a...
87
  	.release = single_release,
0ffddfbb8   Al Viro   scsi: saner repla...
88
89
90
91
  	.read = seq_read,
  	.llseek = seq_lseek,
  	.write = proc_scsi_host_write
  };
eb44820c2   Rob Landley   [SCSI] Add Docume...
92
93
94
95
96
97
  /**
   * scsi_proc_hostdir_add - Create directory in /proc for a scsi host
   * @sht: owner of this directory
   *
   * Sets sht->proc_dir to the new directory.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
  void scsi_proc_hostdir_add(struct scsi_host_template *sht)
  {
70ef457dc   Al Viro   scsi: bury ->proc...
100
  	if (!sht->show_info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
  		return;
0b9506723   Arjan van de Ven   [SCSI] turn most ...
102
  	mutex_lock(&global_host_template_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
105
106
107
  	if (!sht->present++) {
  		sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi);
          	if (!sht->proc_dir)
  			printk(KERN_ERR "%s: proc_mkdir failed for %s
  ",
cadbd4a5e   Harvey Harrison   [SCSI] replace __...
108
  			       __func__, sht->proc_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
  	}
0b9506723   Arjan van de Ven   [SCSI] turn most ...
110
  	mutex_unlock(&global_host_template_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  }
eb44820c2   Rob Landley   [SCSI] Add Docume...
112
113
114
115
  /**
   * scsi_proc_hostdir_rm - remove directory in /proc for a scsi host
   * @sht: owner of directory
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
  void scsi_proc_hostdir_rm(struct scsi_host_template *sht)
  {
70ef457dc   Al Viro   scsi: bury ->proc...
118
  	if (!sht->show_info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
  		return;
0b9506723   Arjan van de Ven   [SCSI] turn most ...
120
  	mutex_lock(&global_host_template_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
  	if (!--sht->present && sht->proc_dir) {
  		remove_proc_entry(sht->proc_name, proc_scsi);
  		sht->proc_dir = NULL;
  	}
0b9506723   Arjan van de Ven   [SCSI] turn most ...
125
  	mutex_unlock(&global_host_template_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
  }
eb44820c2   Rob Landley   [SCSI] Add Docume...
127
128
129
130
131
  
  /**
   * scsi_proc_host_add - Add entry for this host to appropriate /proc dir
   * @shost: host to add
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
133
134
135
136
137
138
139
140
141
  void scsi_proc_host_add(struct Scsi_Host *shost)
  {
  	struct scsi_host_template *sht = shost->hostt;
  	struct proc_dir_entry *p;
  	char name[10];
  
  	if (!sht->proc_dir)
  		return;
  
  	sprintf(name,"%d", shost->host_no);
70ef457dc   Al Viro   scsi: bury ->proc...
142
143
144
145
146
147
148
  	p = proc_create_data(name, S_IRUGO | S_IWUSR,
  		sht->proc_dir, &proc_scsi_fops, shost);
  	if (!p)
  		printk(KERN_ERR "%s: Failed to register host %d in"
  		       "%s
  ", __func__, shost->host_no,
  		       sht->proc_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
  }
eb44820c2   Rob Landley   [SCSI] Add Docume...
150
151
152
153
  /**
   * scsi_proc_host_rm - remove this host's entry from /proc
   * @shost: which host
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
157
158
159
160
161
162
163
  void scsi_proc_host_rm(struct Scsi_Host *shost)
  {
  	char name[10];
  
  	if (!shost->hostt->proc_dir)
  		return;
  
  	sprintf(name,"%d", shost->host_no);
  	remove_proc_entry(name, shost->hostt->proc_dir);
  }
eb44820c2   Rob Landley   [SCSI] Add Docume...
164
165
166
167
168
169
170
171
  /**
   * proc_print_scsidevice - return data about this host
   * @dev: A scsi device
   * @data: &struct seq_file to output to.
   *
   * Description: prints Host, Channel, Id, Lun, Vendor, Model, Rev, Type,
   * and revision.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
  static int proc_print_scsidevice(struct device *dev, void *data)
  {
b0ed43360   Hannes Reinecke   [SCSI] add scsi_h...
174
  	struct scsi_device *sdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
  	struct seq_file *s = data;
  	int i;
b0ed43360   Hannes Reinecke   [SCSI] add scsi_h...
177
178
179
180
  	if (!scsi_is_sdev_device(dev))
  		goto out;
  
  	sdev = to_scsi_device(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
  	seq_printf(s,
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
182
183
  		"Host: scsi%d Channel: %02d Id: %02d Lun: %02llu
    Vendor: ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
186
  		sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
  	for (i = 0; i < 8; i++) {
  		if (sdev->vendor[i] >= 0x20)
91c40f24f   Rasmus Villemoes   scsi: replace seq...
187
  			seq_putc(s, sdev->vendor[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  		else
f50332ff2   Rasmus Villemoes   scsi: print singl...
189
  			seq_putc(s, ' ');
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  	}
91c40f24f   Rasmus Villemoes   scsi: replace seq...
191
  	seq_puts(s, " Model: ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
  	for (i = 0; i < 16; i++) {
  		if (sdev->model[i] >= 0x20)
91c40f24f   Rasmus Villemoes   scsi: replace seq...
194
  			seq_putc(s, sdev->model[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
  		else
f50332ff2   Rasmus Villemoes   scsi: print singl...
196
  			seq_putc(s, ' ');
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
  	}
91c40f24f   Rasmus Villemoes   scsi: replace seq...
198
  	seq_puts(s, " Rev: ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
  	for (i = 0; i < 4; i++) {
  		if (sdev->rev[i] >= 0x20)
91c40f24f   Rasmus Villemoes   scsi: replace seq...
201
  			seq_putc(s, sdev->rev[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  		else
f50332ff2   Rasmus Villemoes   scsi: print singl...
203
  			seq_putc(s, ' ');
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
  	}
f50332ff2   Rasmus Villemoes   scsi: print singl...
205
206
  	seq_putc(s, '
  ');
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207

4ff36718e   Matthew Wilcox   [SCSI] Improve in...
208
  	seq_printf(s, "  Type:   %s ", scsi_device_type(sdev->type));
74feb53e8   Alan Stern   [SCSI] scsi_proc....
209
210
  	seq_printf(s, "               ANSI  SCSI revision: %02x",
  			sdev->scsi_level - (sdev->scsi_level > 1));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
  	if (sdev->scsi_level == 2)
91c40f24f   Rasmus Villemoes   scsi: replace seq...
212
213
  		seq_puts(s, " CCS
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
  	else
f50332ff2   Rasmus Villemoes   scsi: print singl...
215
216
  		seq_putc(s, '
  ');
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217

b0ed43360   Hannes Reinecke   [SCSI] add scsi_h...
218
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
220
  	return 0;
  }
eb44820c2   Rob Landley   [SCSI] Add Docume...
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  /**
   * scsi_add_single_device - Respond to user request to probe for/add device
   * @host: user-supplied decimal integer
   * @channel: user-supplied decimal integer
   * @id: user-supplied decimal integer
   * @lun: user-supplied decimal integer
   *
   * Description: called by writing "scsi add-single-device" to /proc/scsi/scsi.
   *
   * does scsi_host_lookup() and either user_scan() if that transport
   * type supports it, or else scsi_scan_host_selected()
   *
   * Note: this seems to be aimed exclusively at SCSI parallel busses.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
236
237
238
239
240
  static int scsi_add_single_device(uint host, uint channel, uint id, uint lun)
  {
  	struct Scsi_Host *shost;
  	int error = -ENXIO;
  
  	shost = scsi_host_lookup(host);
315cb0ad1   James Smart   [SCSI] scsi_host_...
241
242
  	if (!shost)
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243

e02f3f592   Christoph Hellwig   [SCSI] remove tar...
244
245
246
247
  	if (shost->transportt->user_scan)
  		error = shost->transportt->user_scan(shost, channel, id, lun);
  	else
  		error = scsi_scan_host_selected(shost, channel, id, lun, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
249
250
  	scsi_host_put(shost);
  	return error;
  }
eb44820c2   Rob Landley   [SCSI] Add Docume...
251
252
253
254
255
256
257
258
259
260
  /**
   * scsi_remove_single_device - Respond to user request to remove a device
   * @host: user-supplied decimal integer
   * @channel: user-supplied decimal integer
   * @id: user-supplied decimal integer
   * @lun: user-supplied decimal integer
   *
   * Description: called by writing "scsi remove-single-device" to
   * /proc/scsi/scsi.  Does a scsi_device_lookup() and scsi_remove_device()
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
263
264
265
266
267
  static int scsi_remove_single_device(uint host, uint channel, uint id, uint lun)
  {
  	struct scsi_device *sdev;
  	struct Scsi_Host *shost;
  	int error = -ENXIO;
  
  	shost = scsi_host_lookup(host);
315cb0ad1   James Smart   [SCSI] scsi_host_...
268
269
  	if (!shost)
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
271
272
273
274
275
276
277
278
279
  	sdev = scsi_device_lookup(shost, channel, id, lun);
  	if (sdev) {
  		scsi_remove_device(sdev);
  		scsi_device_put(sdev);
  		error = 0;
  	}
  
  	scsi_host_put(shost);
  	return error;
  }
eb44820c2   Rob Landley   [SCSI] Add Docume...
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
  /**
   * proc_scsi_write - handle writes to /proc/scsi/scsi
   * @file: not used
   * @buf: buffer to write
   * @length: length of buf, at most PAGE_SIZE
   * @ppos: not used
   *
   * Description: this provides a legacy mechanism to add or remove devices by
   * Host, Channel, ID, and Lun.  To use,
   * "echo 'scsi add-single-device 0 1 2 3' > /proc/scsi/scsi" or
   * "echo 'scsi remove-single-device 0 1 2 3' > /proc/scsi/scsi" with
   * "0 1 2 3" replaced by the Host, Channel, Id, and Lun.
   *
   * Note: this seems to be aimed at parallel SCSI. Most modern busses (USB,
   * SATA, Firewire, Fibre Channel, etc) dynamically assign these values to
   * provide a unique identifier and nothing more.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
  static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
  			       size_t length, loff_t *ppos)
  {
  	int host, channel, id, lun;
  	char *buffer, *p;
  	int err;
  
  	if (!buf || length > PAGE_SIZE)
  		return -EINVAL;
  
  	buffer = (char *)__get_free_page(GFP_KERNEL);
  	if (!buffer)
  		return -ENOMEM;
  
  	err = -EFAULT;
  	if (copy_from_user(buffer, buf, length))
  		goto out;
  
  	err = -EINVAL;
  	if (length < PAGE_SIZE)
  		buffer[length] = '\0';
  	else if (buffer[PAGE_SIZE-1])
  		goto out;
  
  	/*
  	 * Usage: echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi
  	 * with  "0 1 2 3" replaced by your "Host Channel Id Lun".
  	 */
  	if (!strncmp("scsi add-single-device", buffer, 22)) {
  		p = buffer + 23;
  
  		host = simple_strtoul(p, &p, 0);
  		channel = simple_strtoul(p + 1, &p, 0);
  		id = simple_strtoul(p + 1, &p, 0);
  		lun = simple_strtoul(p + 1, &p, 0);
  
  		err = scsi_add_single_device(host, channel, id, lun);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
  
  	/*
  	 * Usage: echo "scsi remove-single-device 0 1 2 3" >/proc/scsi/scsi
  	 * with  "0 1 2 3" replaced by your "Host Channel Id Lun".
  	 */
  	} else if (!strncmp("scsi remove-single-device", buffer, 25)) {
  		p = buffer + 26;
  
  		host = simple_strtoul(p, &p, 0);
  		channel = simple_strtoul(p + 1, &p, 0);
  		id = simple_strtoul(p + 1, &p, 0);
  		lun = simple_strtoul(p + 1, &p, 0);
  
  		err = scsi_remove_single_device(host, channel, id, lun);
  	}
2ca48a132   James Bottomley   [SCSI] fix proc_s...
349
350
351
352
353
354
  	/*
  	 * convert success returns so that we return the 
  	 * number of bytes consumed.
  	 */
  	if (!err)
  		err = length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355
356
357
358
   out:
  	free_page((unsigned long)buffer);
  	return err;
  }
e37c4913c   Jeff Mahoney   [SCSI] iterate ov...
359
  static int always_match(struct device *dev, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
  {
e37c4913c   Jeff Mahoney   [SCSI] iterate ov...
361
362
363
364
365
366
367
368
369
  	return 1;
  }
  
  static inline struct device *next_scsi_device(struct device *start)
  {
  	struct device *next = bus_find_device(&scsi_bus_type, start, NULL,
  					      always_match);
  	put_device(start);
  	return next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
  }
e37c4913c   Jeff Mahoney   [SCSI] iterate ov...
371
372
373
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
  static void *scsi_seq_start(struct seq_file *sfile, loff_t *pos)
  {
  	struct device *dev = NULL;
  	loff_t n = *pos;
  
  	while ((dev = next_scsi_device(dev))) {
  		if (!n--)
  			break;
  		sfile->private++;
  	}
  	return dev;
  }
  
  static void *scsi_seq_next(struct seq_file *sfile, void *v, loff_t *pos)
  {
  	(*pos)++;
  	sfile->private++;
  	return next_scsi_device(v);
  }
  
  static void scsi_seq_stop(struct seq_file *sfile, void *v)
  {
  	put_device(v);
  }
  
  static int scsi_seq_show(struct seq_file *sfile, void *dev)
  {
  	if (!sfile->private)
  		seq_puts(sfile, "Attached devices:
  ");
  
  	return proc_print_scsidevice(dev, sfile);
  }
  
  static const struct seq_operations scsi_seq_ops = {
  	.start	= scsi_seq_start,
  	.next	= scsi_seq_next,
  	.stop	= scsi_seq_stop,
  	.show	= scsi_seq_show
  };
eb44820c2   Rob Landley   [SCSI] Add Docume...
411
412
413
414
415
416
417
  /**
   * proc_scsi_open - glue function
   * @inode: not used
   * @file: passed to single_open()
   *
   * Associates proc_scsi_show with this file
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
419
420
  static int proc_scsi_open(struct inode *inode, struct file *file)
  {
  	/*
eb44820c2   Rob Landley   [SCSI] Add Docume...
421
  	 * We don't really need this for the write case but it doesn't
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
423
  	 * harm either.
  	 */
e37c4913c   Jeff Mahoney   [SCSI] iterate ov...
424
  	return seq_open(file, &scsi_seq_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
  }
00977a59b   Arjan van de Ven   [PATCH] mark stru...
426
  static const struct file_operations proc_scsi_operations = {
a973909fc   Denis V. Lunev   scsi: use non-rac...
427
  	.owner		= THIS_MODULE,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
429
430
431
  	.open		= proc_scsi_open,
  	.read		= seq_read,
  	.write		= proc_scsi_write,
  	.llseek		= seq_lseek,
e37c4913c   Jeff Mahoney   [SCSI] iterate ov...
432
  	.release	= seq_release,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
  };
eb44820c2   Rob Landley   [SCSI] Add Docume...
434
435
436
  /**
   * scsi_init_procfs - create scsi and scsi/scsi in procfs
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
438
439
440
441
442
443
  int __init scsi_init_procfs(void)
  {
  	struct proc_dir_entry *pde;
  
  	proc_scsi = proc_mkdir("scsi", NULL);
  	if (!proc_scsi)
  		goto err1;
a973909fc   Denis V. Lunev   scsi: use non-rac...
444
  	pde = proc_create("scsi/scsi", 0, NULL, &proc_scsi_operations);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445
446
  	if (!pde)
  		goto err2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
448
449
450
451
452
453
454
  
  	return 0;
  
  err2:
  	remove_proc_entry("scsi", NULL);
  err1:
  	return -ENOMEM;
  }
eb44820c2   Rob Landley   [SCSI] Add Docume...
455
456
457
  /**
   * scsi_exit_procfs - Remove scsi/scsi and scsi from procfs
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
460
461
462
  void scsi_exit_procfs(void)
  {
  	remove_proc_entry("scsi/scsi", NULL);
  	remove_proc_entry("scsi", NULL);
  }