Blame view

drivers/scsi/scsi_sysfs.c 37.7 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /*
   * scsi_sysfs.c
   *
   * SCSI sysfs interface routines.
   *
   * Created to pull SCSI mid layer sysfs routines into one file.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
9
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
  #include <linux/init.h>
  #include <linux/blkdev.h>
  #include <linux/device.h>
bc4f24014   Alan Stern   [SCSI] implement ...
13
  #include <linux/pm_runtime.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
16
17
18
  
  #include <scsi/scsi.h>
  #include <scsi/scsi_device.h>
  #include <scsi/scsi_host.h>
  #include <scsi/scsi_tcq.h>
41f95dd2e   Hannes Reinecke   scsi_dh: move 'dh...
19
  #include <scsi/scsi_dh.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  #include <scsi/scsi_transport.h>
44818efba   Adrian Bunk   [SCSI] small clea...
21
  #include <scsi/scsi_driver.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
  
  #include "scsi_priv.h"
  #include "scsi_logging.h"
b0ed43360   Hannes Reinecke   [SCSI] add scsi_h...
25
  static struct device_type scsi_dev_type;
0ad78200b   Arjan van de Ven   [SCSI] Mark some ...
26
  static const struct {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
31
32
33
34
35
  	enum scsi_device_state	value;
  	char			*name;
  } sdev_states[] = {
  	{ SDEV_CREATED, "created" },
  	{ SDEV_RUNNING, "running" },
  	{ SDEV_CANCEL, "cancel" },
  	{ SDEV_DEL, "deleted" },
  	{ SDEV_QUIESCE, "quiesce" },
  	{ SDEV_OFFLINE,	"offline" },
1b8d26206   Mike Christie   [SCSI] add new SD...
36
  	{ SDEV_TRANSPORT_OFFLINE, "transport-offline" },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
  	{ SDEV_BLOCK,	"blocked" },
6f4267e3b   James Bottomley   [SCSI] Update the...
38
  	{ SDEV_CREATED_BLOCK, "created-blocked" },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
41
42
43
44
  };
  
  const char *scsi_device_state_name(enum scsi_device_state state)
  {
  	int i;
  	char *name = NULL;
6391a1137   Tobias Klauser   [SCSI] drivers/sc...
45
  	for (i = 0; i < ARRAY_SIZE(sdev_states); i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
49
50
51
52
  		if (sdev_states[i].value == state) {
  			name = sdev_states[i].name;
  			break;
  		}
  	}
  	return name;
  }
0ad78200b   Arjan van de Ven   [SCSI] Mark some ...
53
  static const struct {
d33018740   Mike Anderson   [SCSI] host state...
54
55
56
57
58
59
60
61
  	enum scsi_host_state	value;
  	char			*name;
  } shost_states[] = {
  	{ SHOST_CREATED, "created" },
  	{ SHOST_RUNNING, "running" },
  	{ SHOST_CANCEL, "cancel" },
  	{ SHOST_DEL, "deleted" },
  	{ SHOST_RECOVERY, "recovery" },
939647ee3   James Bottomley   [SCSI] fix oops o...
62
63
  	{ SHOST_CANCEL_RECOVERY, "cancel/recovery" },
  	{ SHOST_DEL_RECOVERY, "deleted/recovery", },
d33018740   Mike Anderson   [SCSI] host state...
64
65
66
67
68
  };
  const char *scsi_host_state_name(enum scsi_host_state state)
  {
  	int i;
  	char *name = NULL;
6391a1137   Tobias Klauser   [SCSI] drivers/sc...
69
  	for (i = 0; i < ARRAY_SIZE(shost_states); i++) {
d33018740   Mike Anderson   [SCSI] host state...
70
71
72
73
74
75
76
  		if (shost_states[i].value == state) {
  			name = shost_states[i].name;
  			break;
  		}
  	}
  	return name;
  }
d78540dae   Bart Van Assche   scsi: Declare loc...
77
  #ifdef CONFIG_SCSI_DH
77c9df964   Hannes Reinecke   scsi: Add 'access...
78
79
80
81
82
83
84
85
86
87
88
89
  static const struct {
  	unsigned char	value;
  	char		*name;
  } sdev_access_states[] = {
  	{ SCSI_ACCESS_STATE_OPTIMAL, "active/optimized" },
  	{ SCSI_ACCESS_STATE_ACTIVE, "active/non-optimized" },
  	{ SCSI_ACCESS_STATE_STANDBY, "standby" },
  	{ SCSI_ACCESS_STATE_UNAVAILABLE, "unavailable" },
  	{ SCSI_ACCESS_STATE_LBA, "lba-dependent" },
  	{ SCSI_ACCESS_STATE_OFFLINE, "offline" },
  	{ SCSI_ACCESS_STATE_TRANSITIONING, "transitioning" },
  };
d78540dae   Bart Van Assche   scsi: Declare loc...
90
  static const char *scsi_access_state_name(unsigned char state)
77c9df964   Hannes Reinecke   scsi: Add 'access...
91
92
93
94
95
96
97
98
99
100
101
102
  {
  	int i;
  	char *name = NULL;
  
  	for (i = 0; i < ARRAY_SIZE(sdev_access_states); i++) {
  		if (sdev_access_states[i].value == state) {
  			name = sdev_access_states[i].name;
  			break;
  		}
  	}
  	return name;
  }
d78540dae   Bart Van Assche   scsi: Declare loc...
103
  #endif
77c9df964   Hannes Reinecke   scsi: Add 'access...
104

9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
105
  static int check_set(unsigned long long *val, char *src)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
108
109
110
111
112
113
114
  {
  	char *last;
  
  	if (strncmp(src, "-", 20) == 0) {
  		*val = SCAN_WILD_CARD;
  	} else {
  		/*
  		 * Doesn't check for int overflow
  		 */
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
115
  		*val = simple_strtoull(src, &last, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
119
120
121
122
123
  		if (*last != '\0')
  			return 1;
  	}
  	return 0;
  }
  
  static int scsi_scan(struct Scsi_Host *shost, const char *str)
  {
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
124
125
  	char s1[15], s2[15], s3[17], junk;
  	unsigned long long channel, id, lun;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
  	int res;
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
127
  	res = sscanf(str, "%10s %10s %16s %c", s1, s2, s3, &junk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
129
130
131
132
133
134
135
  	if (res != 3)
  		return -EINVAL;
  	if (check_set(&channel, s1))
  		return -EINVAL;
  	if (check_set(&id, s2))
  		return -EINVAL;
  	if (check_set(&lun, s3))
  		return -EINVAL;
e02f3f592   Christoph Hellwig   [SCSI] remove tar...
136
137
138
  	if (shost->transportt->user_scan)
  		res = shost->transportt->user_scan(shost, channel, id, lun);
  	else
1d6450881   Hannes Reinecke   scsi: disable aut...
139
140
  		res = scsi_scan_host_selected(shost, channel, id, lun,
  					      SCSI_SCAN_MANUAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
144
145
146
147
148
149
  	return res;
  }
  
  /*
   * shost_show_function: macro to create an attr function that can be used to
   * show a non-bit field.
   */
  #define shost_show_function(name, field, format_string)			\
  static ssize_t								\
ee959b00c   Tony Jones   SCSI: convert str...
150
151
  show_##name (struct device *dev, struct device_attribute *attr, 	\
  	     char *buf)							\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
  {									\
ee959b00c   Tony Jones   SCSI: convert str...
153
  	struct Scsi_Host *shost = class_to_shost(dev);			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
157
158
159
160
161
162
  	return snprintf (buf, 20, format_string, shost->field);		\
  }
  
  /*
   * shost_rd_attr: macro to create a function and attribute variable for a
   * read only field.
   */
  #define shost_rd_attr2(name, field, format_string)			\
  	shost_show_function(name, field, format_string)			\
ee959b00c   Tony Jones   SCSI: convert str...
163
  static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
167
168
169
170
  
  #define shost_rd_attr(field, format_string) \
  shost_rd_attr2(field, field, format_string)
  
  /*
   * Create the actual show/store functions and data structures.
   */
ee959b00c   Tony Jones   SCSI: convert str...
171
172
173
  static ssize_t
  store_scan(struct device *dev, struct device_attribute *attr,
  	   const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
  {
ee959b00c   Tony Jones   SCSI: convert str...
175
  	struct Scsi_Host *shost = class_to_shost(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
178
179
180
181
182
  	int res;
  
  	res = scsi_scan(shost, buf);
  	if (res == 0)
  		res = count;
  	return res;
  };
ee959b00c   Tony Jones   SCSI: convert str...
183
  static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184

d33018740   Mike Anderson   [SCSI] host state...
185
  static ssize_t
ee959b00c   Tony Jones   SCSI: convert str...
186
187
  store_shost_state(struct device *dev, struct device_attribute *attr,
  		  const char *buf, size_t count)
d33018740   Mike Anderson   [SCSI] host state...
188
189
  {
  	int i;
ee959b00c   Tony Jones   SCSI: convert str...
190
  	struct Scsi_Host *shost = class_to_shost(dev);
d33018740   Mike Anderson   [SCSI] host state...
191
  	enum scsi_host_state state = 0;
6391a1137   Tobias Klauser   [SCSI] drivers/sc...
192
  	for (i = 0; i < ARRAY_SIZE(shost_states); i++) {
d33018740   Mike Anderson   [SCSI] host state...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
  		const int len = strlen(shost_states[i].name);
  		if (strncmp(shost_states[i].name, buf, len) == 0 &&
  		   buf[len] == '
  ') {
  			state = shost_states[i].value;
  			break;
  		}
  	}
  	if (!state)
  		return -EINVAL;
  
  	if (scsi_host_set_state(shost, state))
  		return -EINVAL;
  	return count;
  }
  
  static ssize_t
ee959b00c   Tony Jones   SCSI: convert str...
210
  show_shost_state(struct device *dev, struct device_attribute *attr, char *buf)
d33018740   Mike Anderson   [SCSI] host state...
211
  {
ee959b00c   Tony Jones   SCSI: convert str...
212
  	struct Scsi_Host *shost = class_to_shost(dev);
d33018740   Mike Anderson   [SCSI] host state...
213
214
215
216
217
218
219
220
  	const char *name = scsi_host_state_name(shost->shost_state);
  
  	if (!name)
  		return -EINVAL;
  
  	return snprintf(buf, 20, "%s
  ", name);
  }
ee959b00c   Tony Jones   SCSI: convert str...
221
  /* DEVICE_ATTR(state) clashes with dev_attr_state for sdev */
d78540dae   Bart Van Assche   scsi: Declare loc...
222
  static struct device_attribute dev_attr_hstate =
ee959b00c   Tony Jones   SCSI: convert str...
223
  	__ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state);
d33018740   Mike Anderson   [SCSI] host state...
224

5dc2b89e1   FUJITA Tomonori   [SCSI] add suppor...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
  static ssize_t
  show_shost_mode(unsigned int mode, char *buf)
  {
  	ssize_t len = 0;
  
  	if (mode & MODE_INITIATOR)
  		len = sprintf(buf, "%s", "Initiator");
  
  	if (mode & MODE_TARGET)
  		len += sprintf(buf + len, "%s%s", len ? ", " : "", "Target");
  
  	len += sprintf(buf + len, "
  ");
  
  	return len;
  }
ee959b00c   Tony Jones   SCSI: convert str...
241
242
243
  static ssize_t
  show_shost_supported_mode(struct device *dev, struct device_attribute *attr,
  			  char *buf)
5dc2b89e1   FUJITA Tomonori   [SCSI] add suppor...
244
  {
ee959b00c   Tony Jones   SCSI: convert str...
245
  	struct Scsi_Host *shost = class_to_shost(dev);
7a39ac3f2   James Bottomley   [SCSI] make suppo...
246
  	unsigned int supported_mode = shost->hostt->supported_mode;
5dc2b89e1   FUJITA Tomonori   [SCSI] add suppor...
247

7a39ac3f2   James Bottomley   [SCSI] make suppo...
248
249
250
251
252
  	if (supported_mode == MODE_UNKNOWN)
  		/* by default this should be initiator */
  		supported_mode = MODE_INITIATOR;
  
  	return show_shost_mode(supported_mode, buf);
5dc2b89e1   FUJITA Tomonori   [SCSI] add suppor...
253
  }
ee959b00c   Tony Jones   SCSI: convert str...
254
  static DEVICE_ATTR(supported_mode, S_IRUGO | S_IWUSR, show_shost_supported_mode, NULL);
5dc2b89e1   FUJITA Tomonori   [SCSI] add suppor...
255

ee959b00c   Tony Jones   SCSI: convert str...
256
257
258
  static ssize_t
  show_shost_active_mode(struct device *dev,
  		       struct device_attribute *attr, char *buf)
5dc2b89e1   FUJITA Tomonori   [SCSI] add suppor...
259
  {
ee959b00c   Tony Jones   SCSI: convert str...
260
  	struct Scsi_Host *shost = class_to_shost(dev);
5dc2b89e1   FUJITA Tomonori   [SCSI] add suppor...
261
262
263
264
265
266
267
  
  	if (shost->active_mode == MODE_UNKNOWN)
  		return snprintf(buf, 20, "unknown
  ");
  	else
  		return show_shost_mode(shost->active_mode, buf);
  }
ee959b00c   Tony Jones   SCSI: convert str...
268
  static DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL);
5dc2b89e1   FUJITA Tomonori   [SCSI] add suppor...
269

072f19b4b   Sasha Levin   [SCSI] prevent st...
270
  static int check_reset_type(const char *str)
294436914   Vikas Chaudhary   [SCSI] scsi: Adde...
271
  {
072f19b4b   Sasha Levin   [SCSI] prevent st...
272
  	if (sysfs_streq(str, "adapter"))
294436914   Vikas Chaudhary   [SCSI] scsi: Adde...
273
  		return SCSI_ADAPTER_RESET;
072f19b4b   Sasha Levin   [SCSI] prevent st...
274
  	else if (sysfs_streq(str, "firmware"))
294436914   Vikas Chaudhary   [SCSI] scsi: Adde...
275
276
277
278
279
280
281
282
283
284
285
286
  		return SCSI_FIRMWARE_RESET;
  	else
  		return 0;
  }
  
  static ssize_t
  store_host_reset(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
  {
  	struct Scsi_Host *shost = class_to_shost(dev);
  	struct scsi_host_template *sht = shost->hostt;
  	int ret = -EINVAL;
294436914   Vikas Chaudhary   [SCSI] scsi: Adde...
287
  	int type;
072f19b4b   Sasha Levin   [SCSI] prevent st...
288
  	type = check_reset_type(buf);
294436914   Vikas Chaudhary   [SCSI] scsi: Adde...
289
290
291
292
293
294
295
296
297
298
299
300
301
  	if (!type)
  		goto exit_store_host_reset;
  
  	if (sht->host_reset)
  		ret = sht->host_reset(shost, type);
  
  exit_store_host_reset:
  	if (ret == 0)
  		ret = count;
  	return ret;
  }
  
  static DEVICE_ATTR(host_reset, S_IWUSR, NULL, store_host_reset);
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
302
303
304
305
306
  static ssize_t
  show_shost_eh_deadline(struct device *dev,
  		      struct device_attribute *attr, char *buf)
  {
  	struct Scsi_Host *shost = class_to_shost(dev);
bb3b621a3   Ren Mingxin   [SCSI] Set the mi...
307
308
309
310
311
  	if (shost->eh_deadline == -1)
  		return snprintf(buf, strlen("off") + 2, "off
  ");
  	return sprintf(buf, "%u
  ", shost->eh_deadline / HZ);
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
312
313
314
315
316
317
318
319
  }
  
  static ssize_t
  store_shost_eh_deadline(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
  {
  	struct Scsi_Host *shost = class_to_shost(dev);
  	int ret = -EINVAL;
bb3b621a3   Ren Mingxin   [SCSI] Set the mi...
320
  	unsigned long deadline, flags;
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
321

ad469a576   Hannes Reinecke   [SCSI] scsi_error...
322
323
324
  	if (shost->transportt &&
  	    (shost->transportt->eh_strategy_handler ||
  	     !shost->hostt->eh_host_reset_handler))
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
325
  		return ret;
bb3b621a3   Ren Mingxin   [SCSI] Set the mi...
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
  	if (!strncmp(buf, "off", strlen("off")))
  		deadline = -1;
  	else {
  		ret = kstrtoul(buf, 10, &deadline);
  		if (ret)
  			return ret;
  		if (deadline * HZ > UINT_MAX)
  			return -EINVAL;
  	}
  
  	spin_lock_irqsave(shost->host_lock, flags);
  	if (scsi_host_in_recovery(shost))
  		ret = -EBUSY;
  	else {
  		if (deadline == -1)
  			shost->eh_deadline = -1;
  		else
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
343
  			shost->eh_deadline = deadline * HZ;
bb3b621a3   Ren Mingxin   [SCSI] Set the mi...
344
345
  
  		ret = count;
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
346
  	}
bb3b621a3   Ren Mingxin   [SCSI] Set the mi...
347
  	spin_unlock_irqrestore(shost->host_lock, flags);
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
348
349
350
351
  	return ret;
  }
  
  static DEVICE_ATTR(eh_deadline, S_IRUGO | S_IWUSR, show_shost_eh_deadline, store_shost_eh_deadline);
d285203cf   Christoph Hellwig   scsi: add support...
352
353
  shost_rd_attr(use_blk_mq, "%d
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
355
  shost_rd_attr(unique_id, "%u
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
357
  shost_rd_attr(cmd_per_lun, "%hd
  ");
ed632da84   James Bottomley   [SCSI] add can_qu...
358
359
  shost_rd_attr(can_queue, "%hd
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
361
  shost_rd_attr(sg_tablesize, "%hu
  ");
13f05c8d8   Martin K. Petersen   block/scsi: Provi...
362
363
  shost_rd_attr(sg_prot_tablesize, "%hu
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
365
  shost_rd_attr(unchecked_isa_dma, "%d
  ");
4469f9878   Martin K. Petersen   [SCSI] Host prote...
366
367
368
369
  shost_rd_attr(prot_capabilities, "%u
  ");
  shost_rd_attr(prot_guard_type, "%hd
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
  shost_rd_attr2(proc_name, hostt->proc_name, "%s
  ");
746650160   Christoph Hellwig   scsi: convert hos...
372
373
374
375
376
377
378
379
  static ssize_t
  show_host_busy(struct device *dev, struct device_attribute *attr, char *buf)
  {
  	struct Scsi_Host *shost = class_to_shost(dev);
  	return snprintf(buf, 20, "%d
  ", atomic_read(&shost->host_busy));
  }
  static DEVICE_ATTR(host_busy, S_IRUGO, show_host_busy, NULL);
f7120a4f7   Hannes Reinecke   [SCSI] use defaul...
380
  static struct attribute *scsi_sysfs_shost_attrs[] = {
d285203cf   Christoph Hellwig   scsi: add support...
381
  	&dev_attr_use_blk_mq.attr,
f7120a4f7   Hannes Reinecke   [SCSI] use defaul...
382
383
384
385
386
  	&dev_attr_unique_id.attr,
  	&dev_attr_host_busy.attr,
  	&dev_attr_cmd_per_lun.attr,
  	&dev_attr_can_queue.attr,
  	&dev_attr_sg_tablesize.attr,
13f05c8d8   Martin K. Petersen   block/scsi: Provi...
387
  	&dev_attr_sg_prot_tablesize.attr,
f7120a4f7   Hannes Reinecke   [SCSI] use defaul...
388
389
390
391
392
393
  	&dev_attr_unchecked_isa_dma.attr,
  	&dev_attr_proc_name.attr,
  	&dev_attr_scan.attr,
  	&dev_attr_hstate.attr,
  	&dev_attr_supported_mode.attr,
  	&dev_attr_active_mode.attr,
4469f9878   Martin K. Petersen   [SCSI] Host prote...
394
395
  	&dev_attr_prot_capabilities.attr,
  	&dev_attr_prot_guard_type.attr,
294436914   Vikas Chaudhary   [SCSI] scsi: Adde...
396
  	&dev_attr_host_reset.attr,
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
397
  	&dev_attr_eh_deadline.attr,
f7120a4f7   Hannes Reinecke   [SCSI] use defaul...
398
399
  	NULL
  };
d78540dae   Bart Van Assche   scsi: Declare loc...
400
  static struct attribute_group scsi_shost_attr_group = {
f7120a4f7   Hannes Reinecke   [SCSI] use defaul...
401
402
  	.attrs =	scsi_sysfs_shost_attrs,
  };
a4dbd6740   David Brownell   driver model: con...
403
  const struct attribute_group *scsi_sysfs_shost_attr_groups[] = {
f7120a4f7   Hannes Reinecke   [SCSI] use defaul...
404
  	&scsi_shost_attr_group,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
406
  	NULL
  };
ee959b00c   Tony Jones   SCSI: convert str...
407
  static void scsi_device_cls_release(struct device *class_dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
409
410
411
412
413
  {
  	struct scsi_device *sdev;
  
  	sdev = class_to_sdev(class_dev);
  	put_device(&sdev->sdev_gendev);
  }
65f27f384   David Howells   WorkStruct: Pass ...
414
  static void scsi_device_dev_release_usercontext(struct work_struct *work)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
416
417
  {
  	struct scsi_device *sdev;
  	struct device *parent;
a341cd0f6   Jeff Garzik   SCSI: add asynchr...
418
  	struct list_head *this, *tmp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
  	unsigned long flags;
65f27f384   David Howells   WorkStruct: Pass ...
420
  	sdev = container_of(work, struct scsi_device, ew.work);
23695e41a   Junichi Nomura   scsi_dh: fix use-...
421
  	scsi_dh_release_device(sdev);
65f27f384   David Howells   WorkStruct: Pass ...
422
  	parent = sdev->sdev_gendev.parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
424
  
  	spin_lock_irqsave(sdev->host->host_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
426
427
428
  	list_del(&sdev->siblings);
  	list_del(&sdev->same_target_siblings);
  	list_del(&sdev->starved_entry);
  	spin_unlock_irqrestore(sdev->host->host_lock, flags);
a341cd0f6   Jeff Garzik   SCSI: add asynchr...
429
430
431
432
433
434
435
436
437
  	cancel_work_sync(&sdev->event_work);
  
  	list_for_each_safe(this, tmp, &sdev->event_list) {
  		struct scsi_event *evt;
  
  		evt = list_entry(this, struct scsi_event, node);
  		list_del(&evt->node);
  		kfree(evt);
  	}
e73e079bf   James Bottomley   [SCSI] Fix oops c...
438
  	blk_put_queue(sdev->request_queue);
86cbfb560   James Bottomley   [SCSI] put strict...
439
440
  	/* NULL queue means the device can't be used */
  	sdev->request_queue = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441

b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
442
443
  	kfree(sdev->vpd_pg83);
  	kfree(sdev->vpd_pg80);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
445
446
447
448
449
  	kfree(sdev->inquiry);
  	kfree(sdev);
  
  	if (parent)
  		put_device(parent);
  }
65110b216   James Bottomley   [SCSI] fix wrong ...
450
451
  static void scsi_device_dev_release(struct device *dev)
  {
ffedb4522   James Bottomley   [SCSI] fix scsi p...
452
  	struct scsi_device *sdp = to_scsi_device(dev);
65f27f384   David Howells   WorkStruct: Pass ...
453
  	execute_in_process_context(scsi_device_dev_release_usercontext,
ffedb4522   James Bottomley   [SCSI] fix scsi p...
454
  				   &sdp->ew);
65110b216   James Bottomley   [SCSI] fix wrong ...
455
  }
52c1da395   Adrian Bunk   [PATCH] make vari...
456
  static struct class sdev_class = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
  	.name		= "scsi_device",
ee959b00c   Tony Jones   SCSI: convert str...
458
  	.dev_release	= scsi_device_cls_release,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
460
461
462
463
  };
  
  /* all probing is done in the individual ->probe routines */
  static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
  {
b0ed43360   Hannes Reinecke   [SCSI] add scsi_h...
464
465
466
467
468
469
  	struct scsi_device *sdp;
  
  	if (dev->type != &scsi_dev_type)
  		return 0;
  
  	sdp = to_scsi_device(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
471
472
473
  	if (sdp->no_uld_attach)
  		return 0;
  	return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
  }
7eff2e7a8   Kay Sievers   Driver core: chan...
474
  static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
d7b8bcb0a   Michael Tokarev   [SCSI] modalias f...
475
  {
1f42ea7bc   James Bottomley   [SCSI] fix interm...
476
477
478
479
480
481
  	struct scsi_device *sdev;
  
  	if (dev->type != &scsi_dev_type)
  		return 0;
  
  	sdev = to_scsi_device(dev);
d7b8bcb0a   Michael Tokarev   [SCSI] modalias f...
482

7eff2e7a8   Kay Sievers   Driver core: chan...
483
  	add_uevent_var(env, "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type);
d7b8bcb0a   Michael Tokarev   [SCSI] modalias f...
484
485
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
487
488
  struct bus_type scsi_bus_type = {
          .name		= "scsi",
          .match		= scsi_bus_match,
d7b8bcb0a   Michael Tokarev   [SCSI] modalias f...
489
  	.uevent		= scsi_bus_uevent,
aa3386015   Rafael J. Wysocki   PM: Remove CONFIG...
490
  #ifdef CONFIG_PM
db5bd1e0b   Alan Stern   [SCSI] convert to...
491
  	.pm		= &scsi_bus_pm_ops,
e6da54d84   Alan Stern   SCSI: remove fake...
492
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
  };
a6a8d9f87   Chandra Seetharaman   [SCSI] scsi_dh: a...
494
  EXPORT_SYMBOL_GPL(scsi_bus_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
  
  int scsi_sysfs_register(void)
  {
  	int error;
  
  	error = bus_register(&scsi_bus_type);
  	if (!error) {
  		error = class_register(&sdev_class);
  		if (error)
  			bus_unregister(&scsi_bus_type);
  	}
  
  	return error;
  }
  
  void scsi_sysfs_unregister(void)
  {
  	class_unregister(&sdev_class);
  	bus_unregister(&scsi_bus_type);
  }
  
  /*
   * sdev_show_function: macro to create an attr function that can be used to
   * show a non-bit field.
   */
  #define sdev_show_function(field, format_string)				\
  static ssize_t								\
ee959b00c   Tony Jones   SCSI: convert str...
522
523
  sdev_show_##field (struct device *dev, struct device_attribute *attr,	\
  		   char *buf)						\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
  {									\
  	struct scsi_device *sdev;					\
  	sdev = to_scsi_device(dev);					\
  	return snprintf (buf, 20, format_string, sdev->field);		\
  }									\
  
  /*
   * sdev_rd_attr: macro to create a function and attribute variable for a
   * read only field.
   */
  #define sdev_rd_attr(field, format_string)				\
  	sdev_show_function(field, format_string)			\
  static DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL);
  
  
  /*
160e7f671   Tomohiro Kusumi   [SCSI] fix sdev_r...
540
   * sdev_rw_attr: create a function and attribute variable for a
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
543
544
545
546
   * read/write field.
   */
  #define sdev_rw_attr(field, format_string)				\
  	sdev_show_function(field, format_string)				\
  									\
  static ssize_t								\
ee959b00c   Tony Jones   SCSI: convert str...
547
548
  sdev_store_##field (struct device *dev, struct device_attribute *attr,	\
  		    const char *buf, size_t count)			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549
550
551
  {									\
  	struct scsi_device *sdev;					\
  	sdev = to_scsi_device(dev);					\
160e7f671   Tomohiro Kusumi   [SCSI] fix sdev_r...
552
  	sscanf (buf, format_string, &sdev->field);			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
  	return count;							\
  }									\
  static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field);
  
  /* Currently we don't export bit fields, but we might in future,
   * so leave this code in */
  #if 0
  /*
   * sdev_rd_attr: create a function and attribute variable for a
   * read/write bit field.
   */
  #define sdev_rw_attr_bit(field)						\
  	sdev_show_function(field, "%d
  ")					\
  									\
  static ssize_t								\
ee959b00c   Tony Jones   SCSI: convert str...
569
570
  sdev_store_##field (struct device *dev, struct device_attribute *attr,	\
  		    const char *buf, size_t count)			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
  {									\
  	int ret;							\
  	struct scsi_device *sdev;					\
  	ret = scsi_sdev_check_buf_bit(buf);				\
  	if (ret >= 0)	{						\
  		sdev = to_scsi_device(dev);				\
  		sdev->field = ret;					\
  		ret = count;						\
  	}								\
  	return ret;							\
  }									\
  static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field);
  
  /*
   * scsi_sdev_check_buf_bit: return 0 if buf is "0", return 1 if buf is "1",
   * else return -EINVAL.
   */
  static int scsi_sdev_check_buf_bit(const char *buf)
  {
  	if ((buf[1] == '\0') || ((buf[1] == '
  ') && (buf[2] == '\0'))) {
  		if (buf[0] == '1')
  			return 1;
  		else if (buf[0] == '0')
  			return 0;
  		else 
  			return -EINVAL;
  	} else
  		return -EINVAL;
  }
  #endif
  /*
   * Create the actual show/store functions and data structures.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
606
607
608
609
610
611
612
613
614
  sdev_rd_attr (type, "%d
  ");
  sdev_rd_attr (scsi_level, "%d
  ");
  sdev_rd_attr (vendor, "%.8s
  ");
  sdev_rd_attr (model, "%.16s
  ");
  sdev_rd_attr (rev, "%.4s
  ");
71e75c97f   Christoph Hellwig   scsi: convert dev...
615
616
617
618
619
620
621
622
623
  static ssize_t
  sdev_show_device_busy(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct scsi_device *sdev = to_scsi_device(dev);
  	return snprintf(buf, 20, "%d
  ", atomic_read(&sdev->device_busy));
  }
  static DEVICE_ATTR(device_busy, S_IRUGO, sdev_show_device_busy, NULL);
cd9070c9c   Christoph Hellwig   scsi: fix the {ho...
624
625
626
627
628
629
630
631
632
  static ssize_t
  sdev_show_device_blocked(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct scsi_device *sdev = to_scsi_device(dev);
  	return snprintf(buf, 20, "%d
  ", atomic_read(&sdev->device_blocked));
  }
  static DEVICE_ATTR(device_blocked, S_IRUGO, sdev_show_device_blocked, NULL);
242f9dcb8   Jens Axboe   block: unify requ...
633
634
635
  /*
   * TODO: can we make these symlinks to the block layer ones?
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636
  static ssize_t
10523b3b8   Yani Ioannou   [PATCH] Driver Co...
637
  sdev_show_timeout (struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
639
640
  {
  	struct scsi_device *sdev;
  	sdev = to_scsi_device(dev);
242f9dcb8   Jens Axboe   block: unify requ...
641
642
  	return snprintf(buf, 20, "%d
  ", sdev->request_queue->rq_timeout / HZ);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
644
645
  }
  
  static ssize_t
ee959b00c   Tony Jones   SCSI: convert str...
646
647
  sdev_store_timeout (struct device *dev, struct device_attribute *attr,
  		    const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
649
650
651
652
653
  {
  	struct scsi_device *sdev;
  	int timeout;
  	sdev = to_scsi_device(dev);
  	sscanf (buf, "%d
  ", &timeout);
242f9dcb8   Jens Axboe   block: unify requ...
654
  	blk_queue_rq_timeout(sdev->request_queue, timeout * HZ);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
656
657
658
659
  	return count;
  }
  static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout);
  
  static ssize_t
0816c9251   Martin K. Petersen   [SCSI] Allow erro...
660
661
662
663
664
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
  sdev_show_eh_timeout(struct device *dev, struct device_attribute *attr, char *buf)
  {
  	struct scsi_device *sdev;
  	sdev = to_scsi_device(dev);
  	return snprintf(buf, 20, "%u
  ", sdev->eh_timeout / HZ);
  }
  
  static ssize_t
  sdev_store_eh_timeout(struct device *dev, struct device_attribute *attr,
  		    const char *buf, size_t count)
  {
  	struct scsi_device *sdev;
  	unsigned int eh_timeout;
  	int err;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EACCES;
  
  	sdev = to_scsi_device(dev);
  	err = kstrtouint(buf, 10, &eh_timeout);
  	if (err)
  		return err;
  	sdev->eh_timeout = eh_timeout * HZ;
  
  	return count;
  }
  static DEVICE_ATTR(eh_timeout, S_IRUGO | S_IWUSR, sdev_show_eh_timeout, sdev_store_eh_timeout);
  
  static ssize_t
ee959b00c   Tony Jones   SCSI: convert str...
690
691
  store_rescan_field (struct device *dev, struct device_attribute *attr,
  		    const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
693
694
695
696
  {
  	scsi_rescan_device(dev);
  	return count;
  }
  static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);
ee959b00c   Tony Jones   SCSI: convert str...
697
698
699
  static ssize_t
  sdev_store_delete(struct device *dev, struct device_attribute *attr,
  		  const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
  {
ac0ece917   Tejun Heo   scsi: use device_...
701
702
  	if (device_remove_file_self(dev, attr))
  		scsi_remove_device(to_scsi_device(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
704
705
706
707
  	return count;
  };
  static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
  
  static ssize_t
ee959b00c   Tony Jones   SCSI: convert str...
708
709
  store_state_field(struct device *dev, struct device_attribute *attr,
  		  const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
711
712
713
  {
  	int i;
  	struct scsi_device *sdev = to_scsi_device(dev);
  	enum scsi_device_state state = 0;
6391a1137   Tobias Klauser   [SCSI] drivers/sc...
714
  	for (i = 0; i < ARRAY_SIZE(sdev_states); i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
  		const int len = strlen(sdev_states[i].name);
  		if (strncmp(sdev_states[i].name, buf, len) == 0 &&
  		   buf[len] == '
  ') {
  			state = sdev_states[i].value;
  			break;
  		}
  	}
  	if (!state)
  		return -EINVAL;
  
  	if (scsi_device_set_state(sdev, state))
  		return -EINVAL;
  	return count;
  }
  
  static ssize_t
10523b3b8   Yani Ioannou   [PATCH] Driver Co...
732
  show_state_field(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
734
735
736
737
738
739
740
741
742
743
744
745
746
  {
  	struct scsi_device *sdev = to_scsi_device(dev);
  	const char *name = scsi_device_state_name(sdev->sdev_state);
  
  	if (!name)
  		return -EINVAL;
  
  	return snprintf(buf, 20, "%s
  ", name);
  }
  
  static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_state_field, store_state_field);
  
  static ssize_t
ee959b00c   Tony Jones   SCSI: convert str...
747
748
  show_queue_type_field(struct device *dev, struct device_attribute *attr,
  		      char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
749
750
751
  {
  	struct scsi_device *sdev = to_scsi_device(dev);
  	const char *name = "none";
609aa22f3   Christoph Hellwig   scsi: remove orde...
752
  	if (sdev->simple_tags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
753
754
755
756
757
  		name = "simple";
  
  	return snprintf(buf, 20, "%s
  ", name);
  }
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
758
759
760
761
762
  static ssize_t
  store_queue_type_field(struct device *dev, struct device_attribute *attr,
  		       const char *buf, size_t count)
  {
  	struct scsi_device *sdev = to_scsi_device(dev);
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
763

efc3c1df5   Christoph Hellwig   scsi: remove ->ch...
764
  	if (!sdev->tagged_supported)
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
765
  		return -EINVAL;
efc3c1df5   Christoph Hellwig   scsi: remove ->ch...
766
767
768
  		
  	sdev_printk(KERN_INFO, sdev,
  		    "ignoring write to deprecated queue_type attribute");
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
769
770
771
772
773
  	return count;
  }
  
  static DEVICE_ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field,
  		   store_queue_type_field);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774

b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
775
776
777
778
779
780
781
782
  #define sdev_vpd_pg_attr(_page)						\
  static ssize_t							\
  show_vpd_##_page(struct file *filp, struct kobject *kobj,	\
  		 struct bin_attribute *bin_attr,			\
  		 char *buf, loff_t off, size_t count)			\
  {									\
  	struct device *dev = container_of(kobj, struct device, kobj);	\
  	struct scsi_device *sdev = to_scsi_device(dev);			\
09e2b0b14   Hannes Reinecke   scsi: rescan VPD ...
783
  	int ret;							\
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
784
785
  	if (!sdev->vpd_##_page)						\
  		return -EINVAL;						\
09e2b0b14   Hannes Reinecke   scsi: rescan VPD ...
786
787
788
  	rcu_read_lock();						\
  	ret = memory_read_from_buffer(buf, count, &off,			\
  				      rcu_dereference(sdev->vpd_##_page), \
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
789
  				       sdev->vpd_##_page##_len);	\
09e2b0b14   Hannes Reinecke   scsi: rescan VPD ...
790
791
  	rcu_read_unlock();						\
  	return ret;						\
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
792
793
794
795
796
797
798
799
800
  }									\
  static struct bin_attribute dev_attr_vpd_##_page = {		\
  	.attr =	{.name = __stringify(vpd_##_page), .mode = S_IRUGO },	\
  	.size = 0,							\
  	.read = show_vpd_##_page,					\
  };
  
  sdev_vpd_pg_attr(pg83);
  sdev_vpd_pg_attr(pg80);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
801

92e6246c8   Johannes Thumshirn   scsi: Export SCSI...
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
  static ssize_t show_inquiry(struct file *filep, struct kobject *kobj,
  			    struct bin_attribute *bin_attr,
  			    char *buf, loff_t off, size_t count)
  {
  	struct device *dev = container_of(kobj, struct device, kobj);
  	struct scsi_device *sdev = to_scsi_device(dev);
  
  	if (!sdev->inquiry)
  		return -EINVAL;
  
  	return memory_read_from_buffer(buf, count, &off, sdev->inquiry,
  				       sdev->inquiry_len);
  }
  
  static struct bin_attribute dev_attr_inquiry = {
  	.attr = {
  		.name = "inquiry",
  		.mode = S_IRUGO,
  	},
  	.size = 0,
  	.read = show_inquiry,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
  static ssize_t
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
825
826
  show_iostat_counterbits(struct device *dev, struct device_attribute *attr,
  			char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
827
828
829
830
831
832
833
834
835
  {
  	return snprintf(buf, 20, "%d
  ", (int)sizeof(atomic_t) * 8);
  }
  
  static DEVICE_ATTR(iocounterbits, S_IRUGO, show_iostat_counterbits, NULL);
  
  #define show_sdev_iostat(field)						\
  static ssize_t								\
ee959b00c   Tony Jones   SCSI: convert str...
836
837
  show_iostat_##field(struct device *dev, struct device_attribute *attr,	\
  		    char *buf)						\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
839
840
841
842
843
844
845
846
847
848
  {									\
  	struct scsi_device *sdev = to_scsi_device(dev);			\
  	unsigned long long count = atomic_read(&sdev->field);		\
  	return snprintf(buf, 20, "0x%llx
  ", count);			\
  }									\
  static DEVICE_ATTR(field, S_IRUGO, show_iostat_##field, NULL)
  
  show_sdev_iostat(iorequest_cnt);
  show_sdev_iostat(iodone_cnt);
  show_sdev_iostat(ioerr_cnt);
d7b8bcb0a   Michael Tokarev   [SCSI] modalias f...
849
850
851
852
853
854
855
856
857
  static ssize_t
  sdev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
  {
  	struct scsi_device *sdev;
  	sdev = to_scsi_device(dev);
  	return snprintf (buf, 20, SCSI_DEVICE_MODALIAS_FMT "
  ", sdev->type);
  }
  static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858

a341cd0f6   Jeff Garzik   SCSI: add asynchr...
859
860
861
  #define DECLARE_EVT_SHOW(name, Cap_name)				\
  static ssize_t								\
  sdev_show_evt_##name(struct device *dev, struct device_attribute *attr,	\
ee959b00c   Tony Jones   SCSI: convert str...
862
  		     char *buf)						\
a341cd0f6   Jeff Garzik   SCSI: add asynchr...
863
864
865
866
867
868
869
870
871
  {									\
  	struct scsi_device *sdev = to_scsi_device(dev);			\
  	int val = test_bit(SDEV_EVT_##Cap_name, sdev->supported_events);\
  	return snprintf(buf, 20, "%d
  ", val);				\
  }
  
  #define DECLARE_EVT_STORE(name, Cap_name)				\
  static ssize_t								\
ee959b00c   Tony Jones   SCSI: convert str...
872
  sdev_store_evt_##name(struct device *dev, struct device_attribute *attr,\
a341cd0f6   Jeff Garzik   SCSI: add asynchr...
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
  		      const char *buf, size_t count)			\
  {									\
  	struct scsi_device *sdev = to_scsi_device(dev);			\
  	int val = simple_strtoul(buf, NULL, 0);				\
  	if (val == 0)							\
  		clear_bit(SDEV_EVT_##Cap_name, sdev->supported_events);	\
  	else if (val == 1)						\
  		set_bit(SDEV_EVT_##Cap_name, sdev->supported_events);	\
  	else								\
  		return -EINVAL;						\
  	return count;							\
  }
  
  #define DECLARE_EVT(name, Cap_name)					\
  	DECLARE_EVT_SHOW(name, Cap_name)				\
  	DECLARE_EVT_STORE(name, Cap_name)				\
  	static DEVICE_ATTR(evt_##name, S_IRUGO, sdev_show_evt_##name,	\
  			   sdev_store_evt_##name);
  #define REF_EVT(name) &dev_attr_evt_##name.attr
  
  DECLARE_EVT(media_change, MEDIA_CHANGE)
279afdfe7   Ewan D. Milne   [SCSI] Generate u...
894
895
896
897
898
  DECLARE_EVT(inquiry_change_reported, INQUIRY_CHANGE_REPORTED)
  DECLARE_EVT(capacity_change_reported, CAPACITY_CHANGE_REPORTED)
  DECLARE_EVT(soft_threshold_reached, SOFT_THRESHOLD_REACHED_REPORTED)
  DECLARE_EVT(mode_parameter_change_reported, MODE_PARAMETER_CHANGE_REPORTED)
  DECLARE_EVT(lun_change_reported, LUN_CHANGE_REPORTED)
a341cd0f6   Jeff Garzik   SCSI: add asynchr...
899

ee959b00c   Tony Jones   SCSI: convert str...
900
  static ssize_t
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
901
902
  sdev_store_queue_depth(struct device *dev, struct device_attribute *attr,
  		       const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
904
905
906
907
908
909
910
911
  {
  	int depth, retval;
  	struct scsi_device *sdev = to_scsi_device(dev);
  	struct scsi_host_template *sht = sdev->host->hostt;
  
  	if (!sht->change_queue_depth)
  		return -EINVAL;
  
  	depth = simple_strtoul(buf, NULL, 0);
1278dd680   Jens Axboe   scsi: fix host ma...
912
  	if (depth < 1 || depth > sdev->host->can_queue)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
913
  		return -EINVAL;
db5ed4dfd   Christoph Hellwig   scsi: drop reason...
914
  	retval = sht->change_queue_depth(sdev, depth);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
915
916
  	if (retval < 0)
  		return retval;
4a84067db   Vasu Dev   [SCSI] add queue_...
917
  	sdev->max_queue_depth = sdev->queue_depth;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918
919
  	return count;
  }
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
920
921
  sdev_show_function(queue_depth, "%d
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
922

276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
923
924
  static DEVICE_ATTR(queue_depth, S_IRUGO | S_IWUSR, sdev_show_queue_depth,
  		   sdev_store_queue_depth);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
925

248d4fe95   Hannes Reinecke   scsi: export 'wwi...
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
  static ssize_t
  sdev_show_wwid(struct device *dev, struct device_attribute *attr,
  		    char *buf)
  {
  	struct scsi_device *sdev = to_scsi_device(dev);
  	ssize_t count;
  
  	count = scsi_vpd_lun_id(sdev, buf, PAGE_SIZE);
  	if (count > 0) {
  		buf[count] = '
  ';
  		count++;
  	}
  	return count;
  }
  static DEVICE_ATTR(wwid, S_IRUGO, sdev_show_wwid, NULL);
41f95dd2e   Hannes Reinecke   scsi_dh: move 'dh...
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
  #ifdef CONFIG_SCSI_DH
  static ssize_t
  sdev_show_dh_state(struct device *dev, struct device_attribute *attr,
  		   char *buf)
  {
  	struct scsi_device *sdev = to_scsi_device(dev);
  
  	if (!sdev->handler)
  		return snprintf(buf, 20, "detached
  ");
  
  	return snprintf(buf, 20, "%s
  ", sdev->handler->name);
  }
  
  static ssize_t
  sdev_store_dh_state(struct device *dev, struct device_attribute *attr,
  		    const char *buf, size_t count)
  {
  	struct scsi_device *sdev = to_scsi_device(dev);
  	int err = -EINVAL;
  
  	if (sdev->sdev_state == SDEV_CANCEL ||
  	    sdev->sdev_state == SDEV_DEL)
  		return -ENODEV;
  
  	if (!sdev->handler) {
  		/*
  		 * Attach to a device handler
  		 */
  		err = scsi_dh_attach(sdev->request_queue, buf);
  	} else if (!strncmp(buf, "activate", 8)) {
  		/*
  		 * Activate a device handler
  		 */
  		if (sdev->handler->activate)
  			err = sdev->handler->activate(sdev, NULL, NULL);
  		else
  			err = 0;
  	} else if (!strncmp(buf, "detach", 6)) {
  		/*
  		 * Detach from a device handler
  		 */
  		sdev_printk(KERN_WARNING, sdev,
  			    "can't detach handler %s.
  ",
  			    sdev->handler->name);
  		err = -EINVAL;
  	}
  
  	return err < 0 ? err : count;
  }
  
  static DEVICE_ATTR(dh_state, S_IRUGO | S_IWUSR, sdev_show_dh_state,
  		   sdev_store_dh_state);
77c9df964   Hannes Reinecke   scsi: Add 'access...
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
  
  static ssize_t
  sdev_show_access_state(struct device *dev,
  		       struct device_attribute *attr,
  		       char *buf)
  {
  	struct scsi_device *sdev = to_scsi_device(dev);
  	unsigned char access_state;
  	const char *access_state_name;
  
  	if (!sdev->handler)
  		return -EINVAL;
  
  	access_state = (sdev->access_state & SCSI_ACCESS_STATE_MASK);
  	access_state_name = scsi_access_state_name(access_state);
  
  	return sprintf(buf, "%s
  ",
  		       access_state_name ? access_state_name : "unknown");
  }
  static DEVICE_ATTR(access_state, S_IRUGO, sdev_show_access_state, NULL);
  
  static ssize_t
  sdev_show_preferred_path(struct device *dev,
  			 struct device_attribute *attr,
  			 char *buf)
  {
  	struct scsi_device *sdev = to_scsi_device(dev);
  
  	if (!sdev->handler)
  		return -EINVAL;
  
  	if (sdev->access_state & SCSI_ACCESS_STATE_PREFERRED)
  		return sprintf(buf, "1
  ");
  	else
  		return sprintf(buf, "0
  ");
  }
  static DEVICE_ATTR(preferred_path, S_IRUGO, sdev_show_preferred_path, NULL);
41f95dd2e   Hannes Reinecke   scsi_dh: move 'dh...
1037
  #endif
ee959b00c   Tony Jones   SCSI: convert str...
1038
  static ssize_t
4a84067db   Vasu Dev   [SCSI] add queue_...
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
  sdev_show_queue_ramp_up_period(struct device *dev,
  			       struct device_attribute *attr,
  			       char *buf)
  {
  	struct scsi_device *sdev;
  	sdev = to_scsi_device(dev);
  	return snprintf(buf, 20, "%u
  ",
  			jiffies_to_msecs(sdev->queue_ramp_up_period));
  }
  
  static ssize_t
  sdev_store_queue_ramp_up_period(struct device *dev,
  				struct device_attribute *attr,
  				const char *buf, size_t count)
  {
  	struct scsi_device *sdev = to_scsi_device(dev);
f7c65af51   Daniel Walter   drivers/scsi: rep...
1056
  	unsigned int period;
4a84067db   Vasu Dev   [SCSI] add queue_...
1057

f7c65af51   Daniel Walter   drivers/scsi: rep...
1058
  	if (kstrtouint(buf, 10, &period))
4a84067db   Vasu Dev   [SCSI] add queue_...
1059
1060
1061
  		return -EINVAL;
  
  	sdev->queue_ramp_up_period = msecs_to_jiffies(period);
5cb9b40d6   Peter Oberparleiter   scsi_sysfs: Fix q...
1062
  	return count;
4a84067db   Vasu Dev   [SCSI] add queue_...
1063
  }
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1064
1065
1066
  static DEVICE_ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR,
  		   sdev_show_queue_ramp_up_period,
  		   sdev_store_queue_ramp_up_period);
4a84067db   Vasu Dev   [SCSI] add queue_...
1067

276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1068
1069
  static umode_t scsi_sdev_attr_is_visible(struct kobject *kobj,
  					 struct attribute *attr, int i)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1070
  {
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1071
  	struct device *dev = container_of(kobj, struct device, kobj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1072
  	struct scsi_device *sdev = to_scsi_device(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1073

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1074

276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1075
1076
1077
  	if (attr == &dev_attr_queue_depth.attr &&
  	    !sdev->host->hostt->change_queue_depth)
  		return S_IRUGO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1078

276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1079
1080
1081
  	if (attr == &dev_attr_queue_ramp_up_period.attr &&
  	    !sdev->host->hostt->change_queue_depth)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1082

77c9df964   Hannes Reinecke   scsi: Add 'access...
1083
1084
1085
1086
1087
1088
1089
1090
  #ifdef CONFIG_SCSI_DH
  	if (attr == &dev_attr_access_state.attr &&
  	    !sdev->handler)
  		return 0;
  	if (attr == &dev_attr_preferred_path.attr &&
  	    !sdev->handler)
  		return 0;
  #endif
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1091
  	return attr->mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1092
  }
7e47976bc   Hannes Reinecke   scsi_sysfs: add '...
1093
1094
1095
1096
1097
1098
1099
1100
1101
  static umode_t scsi_sdev_bin_attr_is_visible(struct kobject *kobj,
  					     struct bin_attribute *attr, int i)
  {
  	struct device *dev = container_of(kobj, struct device, kobj);
  	struct scsi_device *sdev = to_scsi_device(dev);
  
  
  	if (attr == &dev_attr_vpd_pg80 && !sdev->vpd_pg80)
  		return 0;
688875826   Hannes Reinecke   scsi_sysfs: Fix t...
1102
  	if (attr == &dev_attr_vpd_pg83 && !sdev->vpd_pg83)
7e47976bc   Hannes Reinecke   scsi_sysfs: add '...
1103
1104
1105
1106
  		return 0;
  
  	return S_IRUGO;
  }
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
  /* Default template for device attributes.  May NOT be modified */
  static struct attribute *scsi_sdev_attrs[] = {
  	&dev_attr_device_blocked.attr,
  	&dev_attr_type.attr,
  	&dev_attr_scsi_level.attr,
  	&dev_attr_device_busy.attr,
  	&dev_attr_vendor.attr,
  	&dev_attr_model.attr,
  	&dev_attr_rev.attr,
  	&dev_attr_rescan.attr,
  	&dev_attr_delete.attr,
  	&dev_attr_state.attr,
  	&dev_attr_timeout.attr,
  	&dev_attr_eh_timeout.attr,
  	&dev_attr_iocounterbits.attr,
  	&dev_attr_iorequest_cnt.attr,
  	&dev_attr_iodone_cnt.attr,
  	&dev_attr_ioerr_cnt.attr,
  	&dev_attr_modalias.attr,
  	&dev_attr_queue_depth.attr,
  	&dev_attr_queue_type.attr,
248d4fe95   Hannes Reinecke   scsi: export 'wwi...
1128
  	&dev_attr_wwid.attr,
41f95dd2e   Hannes Reinecke   scsi_dh: move 'dh...
1129
1130
  #ifdef CONFIG_SCSI_DH
  	&dev_attr_dh_state.attr,
77c9df964   Hannes Reinecke   scsi: Add 'access...
1131
1132
  	&dev_attr_access_state.attr,
  	&dev_attr_preferred_path.attr,
41f95dd2e   Hannes Reinecke   scsi_dh: move 'dh...
1133
  #endif
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1134
1135
1136
1137
1138
1139
1140
1141
1142
  	&dev_attr_queue_ramp_up_period.attr,
  	REF_EVT(media_change),
  	REF_EVT(inquiry_change_reported),
  	REF_EVT(capacity_change_reported),
  	REF_EVT(soft_threshold_reached),
  	REF_EVT(mode_parameter_change_reported),
  	REF_EVT(lun_change_reported),
  	NULL
  };
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
1143
1144
1145
  static struct bin_attribute *scsi_sdev_bin_attrs[] = {
  	&dev_attr_vpd_pg83,
  	&dev_attr_vpd_pg80,
92e6246c8   Johannes Thumshirn   scsi: Export SCSI...
1146
  	&dev_attr_inquiry,
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
1147
1148
  	NULL
  };
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1149
1150
  static struct attribute_group scsi_sdev_attr_group = {
  	.attrs =	scsi_sdev_attrs,
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
1151
  	.bin_attrs =	scsi_sdev_bin_attrs,
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1152
  	.is_visible =	scsi_sdev_attr_is_visible,
7e47976bc   Hannes Reinecke   scsi_sysfs: add '...
1153
  	.is_bin_visible = scsi_sdev_bin_attr_is_visible,
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1154
1155
1156
1157
1158
1159
  };
  
  static const struct attribute_group *scsi_sdev_attr_groups[] = {
  	&scsi_sdev_attr_group,
  	NULL
  };
643eb2d93   James Bottomley   [SCSI] rework scs...
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
  static int scsi_target_add(struct scsi_target *starget)
  {
  	int error;
  
  	if (starget->state != STARGET_CREATED)
  		return 0;
  
  	error = device_add(&starget->dev);
  	if (error) {
  		dev_err(&starget->dev, "target device_add failed, error %d
  ", error);
643eb2d93   James Bottomley   [SCSI] rework scs...
1171
1172
1173
1174
  		return error;
  	}
  	transport_add_device(&starget->dev);
  	starget->state = STARGET_RUNNING;
bc4f24014   Alan Stern   [SCSI] implement ...
1175
1176
1177
  	pm_runtime_set_active(&starget->dev);
  	pm_runtime_enable(&starget->dev);
  	device_enable_async_suspend(&starget->dev);
643eb2d93   James Bottomley   [SCSI] rework scs...
1178
1179
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
  /**
   * scsi_sysfs_add_sdev - add scsi device to sysfs
   * @sdev:	scsi_device to add
   *
   * Return value:
   * 	0 on Success / non-zero on Failure
   **/
  int scsi_sysfs_add_sdev(struct scsi_device *sdev)
  {
  	int error, i;
80ed71ce1   James Bottomley   [SCSI] bsg: separ...
1190
  	struct request_queue *rq = sdev->request_queue;
643eb2d93   James Bottomley   [SCSI] rework scs...
1191
  	struct scsi_target *starget = sdev->sdev_target;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1192

ee37e09d8   Alan Stern   [SCSI] fix duplic...
1193
1194
  	error = scsi_device_set_state(sdev, SDEV_RUNNING);
  	if (error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195
  		return error;
643eb2d93   James Bottomley   [SCSI] rework scs...
1196
1197
1198
1199
1200
  	error = scsi_target_add(starget);
  	if (error)
  		return error;
  
  	transport_configure_device(&starget->dev);
bc4f24014   Alan Stern   [SCSI] implement ...
1201

4cb077d93   Rafael J. Wysocki   PM: Allow SCSI de...
1202
  	device_enable_async_suspend(&sdev->sdev_gendev);
bc4f24014   Alan Stern   [SCSI] implement ...
1203
1204
1205
1206
1207
  	scsi_autopm_get_target(starget);
  	pm_runtime_set_active(&sdev->sdev_gendev);
  	pm_runtime_forbid(&sdev->sdev_gendev);
  	pm_runtime_enable(&sdev->sdev_gendev);
  	scsi_autopm_put_target(starget);
bc4f24014   Alan Stern   [SCSI] implement ...
1208
  	scsi_autopm_get_device(sdev);
086b91d05   Christoph Hellwig   scsi_dh: integrat...
1209
  	error = scsi_dh_add_device(sdev);
221255aee   Hannes Reinecke   scsi: ignore erro...
1210
1211
1212
1213
  	if (error)
  		/*
  		 * device_handler is optional, so any error can be ignored
  		 */
086b91d05   Christoph Hellwig   scsi_dh: integrat...
1214
1215
1216
  		sdev_printk(KERN_INFO, sdev,
  				"failed to add device handler: %d
  ", error);
086b91d05   Christoph Hellwig   scsi_dh: integrat...
1217

4cd2459c0   Hannes Reinecke   scsi_sysfs: call ...
1218
1219
1220
1221
1222
1223
1224
1225
  	error = device_add(&sdev->sdev_gendev);
  	if (error) {
  		sdev_printk(KERN_INFO, sdev,
  				"failed to add device: %d
  ", error);
  		scsi_dh_remove_device(sdev);
  		return error;
  	}
4cb077d93   Rafael J. Wysocki   PM: Allow SCSI de...
1226
  	device_enable_async_suspend(&sdev->sdev_dev);
ee959b00c   Tony Jones   SCSI: convert str...
1227
  	error = device_add(&sdev->sdev_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228
  	if (error) {
73d8c34f3   Alan Stern   SCSI: improve two...
1229
1230
1231
  		sdev_printk(KERN_INFO, sdev,
  				"failed to add class device: %d
  ", error);
086b91d05   Christoph Hellwig   scsi_dh: integrat...
1232
  		scsi_dh_remove_device(sdev);
860dc7360   James Bottomley   [SCSI] fix async ...
1233
  		device_del(&sdev->sdev_gendev);
ee37e09d8   Alan Stern   [SCSI] fix duplic...
1234
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1235
  	}
860dc7360   James Bottomley   [SCSI] fix async ...
1236
1237
  	transport_add_device(&sdev->sdev_gendev);
  	sdev->is_visible = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1238

97f46ae45   FUJITA Tomonori   [SCSI] bsg: add r...
1239
  	error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL, NULL);
80ed71ce1   James Bottomley   [SCSI] bsg: separ...
1240
1241
  
  	if (error)
860dc7360   James Bottomley   [SCSI] fix async ...
1242
1243
  		/* we're treating error on bsg register as non-fatal,
  		 * so pretend nothing went wrong */
80ed71ce1   James Bottomley   [SCSI] bsg: separ...
1244
1245
1246
  		sdev_printk(KERN_INFO, sdev,
  			    "Failed to register bsg queue, errno=%d
  ", error);
bfd129445   Kay Sievers   [SCSI] switch sde...
1247
  	/* add additional host specific attributes */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1248
1249
  	if (sdev->host->hostt->sdev_attrs) {
  		for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) {
bfd129445   Kay Sievers   [SCSI] switch sde...
1250
  			error = device_create_file(&sdev->sdev_gendev,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1251
  					sdev->host->hostt->sdev_attrs[i]);
860dc7360   James Bottomley   [SCSI] fix async ...
1252
  			if (error)
ee37e09d8   Alan Stern   [SCSI] fix duplic...
1253
  				return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1254
1255
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1256

6fe8c1dbe   Subhash Jadavani   scsi: balance out...
1257
  	scsi_autopm_put_device(sdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1258
1259
  	return error;
  }
903f4fed8   Alan Stern   [SCSI] fix caller...
1260
  void __scsi_remove_device(struct scsi_device *sdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1261
  {
df133c212   James Bottomley   [SCSI] Fix transp...
1262
  	struct device *dev = &sdev->sdev_gendev;
be821fd8e   Vitaly Kuznetsov   scsi_sysfs: prote...
1263
1264
1265
1266
1267
1268
1269
  	/*
  	 * This cleanup path is not reentrant and while it is impossible
  	 * to get a new reference with scsi_device_get() someone can still
  	 * hold a previously acquired one.
  	 */
  	if (sdev->sdev_state == SDEV_DEL)
  		return;
860dc7360   James Bottomley   [SCSI] fix async ...
1270
1271
1272
  	if (sdev->is_visible) {
  		if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
  			return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1273

860dc7360   James Bottomley   [SCSI] fix async ...
1274
1275
1276
  		bsg_unregister_queue(sdev->request_queue);
  		device_unregister(&sdev->sdev_dev);
  		transport_remove_device(dev);
086b91d05   Christoph Hellwig   scsi_dh: integrat...
1277
  		scsi_dh_remove_device(sdev);
e619e6cbe   Bart Van Assche   Revert "scsi: Fix...
1278
1279
1280
  		device_del(dev);
  	} else
  		put_device(&sdev->sdev_dev);
b485462ac   Bart Van Assche   [SCSI] Stop accep...
1281
1282
1283
1284
1285
1286
  
  	/*
  	 * Stop accepting new requests and wait until all queuecommand() and
  	 * scsi_run_queue() invocations have finished before tearing down the
  	 * device.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1287
  	scsi_device_set_state(sdev, SDEV_DEL);
b485462ac   Bart Van Assche   [SCSI] Stop accep...
1288
1289
  	blk_cleanup_queue(sdev->request_queue);
  	cancel_work_sync(&sdev->requeue_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1290
1291
  	if (sdev->host->hostt->slave_destroy)
  		sdev->host->hostt->slave_destroy(sdev);
df133c212   James Bottomley   [SCSI] Fix transp...
1292
  	transport_destroy_device(dev);
86cbfb560   James Bottomley   [SCSI] put strict...
1293

e63ed0d7a   James Bottomley   [SCSI] fix our cu...
1294
1295
1296
1297
1298
1299
  	/*
  	 * Paired with the kref_get() in scsi_sysfs_initialize().  We have
  	 * remoed sysfs visibility from the device, so make the target
  	 * invisible if this was the last device underneath it.
  	 */
  	scsi_target_reap(scsi_target(sdev));
df133c212   James Bottomley   [SCSI] Fix transp...
1300
  	put_device(dev);
903f4fed8   Alan Stern   [SCSI] fix caller...
1301
1302
1303
1304
1305
1306
1307
1308
  }
  
  /**
   * scsi_remove_device - unregister a device from the scsi bus
   * @sdev:	scsi_device to unregister
   **/
  void scsi_remove_device(struct scsi_device *sdev)
  {
541950027   Alan Stern   [SCSI] fix use af...
1309
  	struct Scsi_Host *shost = sdev->host;
0b9506723   Arjan van de Ven   [SCSI] turn most ...
1310
  	mutex_lock(&shost->scan_mutex);
903f4fed8   Alan Stern   [SCSI] fix caller...
1311
  	__scsi_remove_device(sdev);
0b9506723   Arjan van de Ven   [SCSI] turn most ...
1312
  	mutex_unlock(&shost->scan_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1313
1314
  }
  EXPORT_SYMBOL(scsi_remove_device);
44818efba   Adrian Bunk   [SCSI] small clea...
1315
  static void __scsi_remove_target(struct scsi_target *starget)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1316
1317
1318
  {
  	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
  	unsigned long flags;
a64358db1   Alan Stern   [SCSI] SCSI scann...
1319
  	struct scsi_device *sdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1320
1321
  
  	spin_lock_irqsave(shost->host_lock, flags);
a64358db1   Alan Stern   [SCSI] SCSI scann...
1322
1323
   restart:
  	list_for_each_entry(sdev, &shost->__devices, siblings) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1324
  		if (sdev->channel != starget->channel ||
a64358db1   Alan Stern   [SCSI] SCSI scann...
1325
  		    sdev->id != starget->id ||
546ae796b   Christof Schmitt   [SCSI] Fix race w...
1326
  		    scsi_device_get(sdev))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1327
1328
1329
  			continue;
  		spin_unlock_irqrestore(shost->host_lock, flags);
  		scsi_remove_device(sdev);
546ae796b   Christof Schmitt   [SCSI] Fix race w...
1330
  		scsi_device_put(sdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1331
  		spin_lock_irqsave(shost->host_lock, flags);
a64358db1   Alan Stern   [SCSI] SCSI scann...
1332
  		goto restart;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1333
1334
  	}
  	spin_unlock_irqrestore(shost->host_lock, flags);
20b1e6742   Patrick Mochel   [PATCH] Use devic...
1335
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
  /**
   * scsi_remove_target - try to remove a target and all its devices
   * @dev: generic starget or parent of generic stargets to be removed
   *
   * Note: This is slightly racy.  It is possible that if the user
   * requests the addition of another device then the target won't be
   * removed.
   */
  void scsi_remove_target(struct device *dev)
  {
3b661a92e   Dan Williams   [SCSI] fix hot un...
1346
  	struct Scsi_Host *shost = dev_to_shost(dev->parent);
305c2e71b   Johannes Thumshirn   Revert "scsi: fix...
1347
  	struct scsi_target *starget;
3b661a92e   Dan Williams   [SCSI] fix hot un...
1348
  	unsigned long flags;
409981935   Christoph Hellwig   scsi: restart lis...
1349
  restart:
3b661a92e   Dan Williams   [SCSI] fix hot un...
1350
1351
  	spin_lock_irqsave(shost->host_lock, flags);
  	list_for_each_entry(starget, &shost->__targets, siblings) {
90a88d6ef   James Bottomley   scsi: fix soft lo...
1352
  		if (starget->state == STARGET_DEL ||
305c2e71b   Johannes Thumshirn   Revert "scsi: fix...
1353
  		    starget->state == STARGET_REMOVE)
3b661a92e   Dan Williams   [SCSI] fix hot un...
1354
1355
  			continue;
  		if (starget->dev.parent == dev || &starget->dev == dev) {
e63ed0d7a   James Bottomley   [SCSI] fix our cu...
1356
  			kref_get(&starget->reap_ref);
f05795d3d   Johannes Thumshirn   scsi: Add interme...
1357
  			starget->state = STARGET_REMOVE;
bc3f02a79   Dan Williams   [SCSI] scsi_remov...
1358
  			spin_unlock_irqrestore(shost->host_lock, flags);
bc3f02a79   Dan Williams   [SCSI] scsi_remov...
1359
  			__scsi_remove_target(starget);
409981935   Christoph Hellwig   scsi: restart lis...
1360
1361
  			scsi_target_reap(starget);
  			goto restart;
3b661a92e   Dan Williams   [SCSI] fix hot un...
1362
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1363
  	}
3b661a92e   Dan Williams   [SCSI] fix hot un...
1364
  	spin_unlock_irqrestore(shost->host_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
  }
  EXPORT_SYMBOL(scsi_remove_target);
  
  int scsi_register_driver(struct device_driver *drv)
  {
  	drv->bus = &scsi_bus_type;
  
  	return driver_register(drv);
  }
  EXPORT_SYMBOL(scsi_register_driver);
  
  int scsi_register_interface(struct class_interface *intf)
  {
  	intf->class = &sdev_class;
  
  	return class_interface_register(intf);
  }
  EXPORT_SYMBOL(scsi_register_interface);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1383
1384
1385
  /**
   * scsi_sysfs_add_host - add scsi host to subsystem
   * @shost:     scsi host struct to add to subsystem
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1386
1387
1388
1389
   **/
  int scsi_sysfs_add_host(struct Scsi_Host *shost)
  {
  	int error, i;
f7120a4f7   Hannes Reinecke   [SCSI] use defaul...
1390
  	/* add host specific attributes */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1391
1392
  	if (shost->hostt->shost_attrs) {
  		for (i = 0; shost->hostt->shost_attrs[i]; i++) {
ee959b00c   Tony Jones   SCSI: convert str...
1393
  			error = device_create_file(&shost->shost_dev,
f7120a4f7   Hannes Reinecke   [SCSI] use defaul...
1394
  					shost->hostt->shost_attrs[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1395
1396
1397
1398
1399
1400
  			if (error)
  				return error;
  		}
  	}
  
  	transport_register_device(&shost->shost_gendev);
d52b3815a   James Bottomley   [SCSI] add missin...
1401
  	transport_configure_device(&shost->shost_gendev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1402
1403
  	return 0;
  }
bfd129445   Kay Sievers   [SCSI] switch sde...
1404
1405
1406
1407
1408
  static struct device_type scsi_dev_type = {
  	.name =		"scsi_device",
  	.release =	scsi_device_dev_release,
  	.groups =	scsi_sdev_attr_groups,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1409
1410
1411
1412
1413
1414
1415
1416
  void scsi_sysfs_device_initialize(struct scsi_device *sdev)
  {
  	unsigned long flags;
  	struct Scsi_Host *shost = sdev->host;
  	struct scsi_target  *starget = sdev->sdev_target;
  
  	device_initialize(&sdev->sdev_gendev);
  	sdev->sdev_gendev.bus = &scsi_bus_type;
bfd129445   Kay Sievers   [SCSI] switch sde...
1417
  	sdev->sdev_gendev.type = &scsi_dev_type;
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
1418
  	dev_set_name(&sdev->sdev_gendev, "%d:%d:%d:%llu",
71610f55f   Kay Sievers   [SCSI] struct dev...
1419
  		     sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
ee959b00c   Tony Jones   SCSI: convert str...
1420
  	device_initialize(&sdev->sdev_dev);
37e6ba007   James Bottomley   [SCSI] fix memory...
1421
  	sdev->sdev_dev.parent = get_device(&sdev->sdev_gendev);
ee959b00c   Tony Jones   SCSI: convert str...
1422
  	sdev->sdev_dev.class = &sdev_class;
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
1423
  	dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%llu",
71610f55f   Kay Sievers   [SCSI] struct dev...
1424
  		     sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
50c4e9641   Alan Stern   scsi: don't store...
1425
1426
1427
1428
1429
1430
1431
  	/*
  	 * Get a default scsi_level from the target (derived from sibling
  	 * devices).  This is the best we can do for guessing how to set
  	 * sdev->lun_in_cdb for the initial INQUIRY command.  For LUN 0 the
  	 * setting doesn't matter, because all the bits are zero anyway.
  	 * But it does matter for higher LUNs.
  	 */
7c9d6f16f   Alan Stern   [SCSI] SCSI core:...
1432
  	sdev->scsi_level = starget->scsi_level;
50c4e9641   Alan Stern   scsi: don't store...
1433
1434
1435
1436
  	if (sdev->scsi_level <= SCSI_2 &&
  			sdev->scsi_level != SCSI_UNKNOWN &&
  			!shost->no_scsi2_lun_in_cdb)
  		sdev->lun_in_cdb = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1437
1438
1439
1440
1441
  	transport_setup_device(&sdev->sdev_gendev);
  	spin_lock_irqsave(shost->host_lock, flags);
  	list_add_tail(&sdev->same_target_siblings, &starget->devices);
  	list_add_tail(&sdev->siblings, &shost->__devices);
  	spin_unlock_irqrestore(shost->host_lock, flags);
e63ed0d7a   James Bottomley   [SCSI] fix our cu...
1442
1443
1444
1445
1446
1447
  	/*
  	 * device can now only be removed via __scsi_remove_device() so hold
  	 * the target.  Target will be held in CREATED state until something
  	 * beneath it becomes visible (in which case it moves to RUNNING)
  	 */
  	kref_get(&starget->reap_ref);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1448
1449
1450
1451
  }
  
  int scsi_is_sdev_device(const struct device *dev)
  {
13ba9bcbf   Kay Sievers   [SCSI] fix scsi_i...
1452
  	return dev->type == &scsi_dev_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1453
1454
1455
1456
1457
1458
  }
  EXPORT_SYMBOL(scsi_is_sdev_device);
  
  /* A blank transport template that is used in drivers that don't
   * yet implement Transport Attributes */
  struct scsi_transport_template blank_transport_template = { { { {NULL, }, }, }, };