Blame view

drivers/scsi/scsi_sysfs.c 39.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
  {
  	char *last;
3991e4605   Bart Van Assche   scsi: Convert a s...
108
  	if (strcmp(src, "-") == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
112
113
  		*val = SCAN_WILD_CARD;
  	} else {
  		/*
  		 * Doesn't check for int overflow
  		 */
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
114
  		*val = simple_strtoull(src, &last, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
116
117
118
119
120
121
122
  		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 ...
123
124
  	char s1[15], s2[15], s3[17], junk;
  	unsigned long long channel, id, lun;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
  	int res;
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
126
  	res = sscanf(str, "%10s %10s %16s %c", s1, s2, s3, &junk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
128
129
130
131
132
133
134
  	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...
135
136
137
  	if (shost->transportt->user_scan)
  		res = shost->transportt->user_scan(shost, channel, id, lun);
  	else
1d6450881   Hannes Reinecke   scsi: disable aut...
138
139
  		res = scsi_scan_host_selected(shost, channel, id, lun,
  					      SCSI_SCAN_MANUAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
143
144
145
146
147
148
  	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...
149
150
  show_##name (struct device *dev, struct device_attribute *attr, 	\
  	     char *buf)							\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
  {									\
ee959b00c   Tony Jones   SCSI: convert str...
152
  	struct Scsi_Host *shost = class_to_shost(dev);			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
156
157
158
159
160
161
  	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...
162
  static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
165
166
167
168
169
  
  #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...
170
171
172
  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
173
  {
ee959b00c   Tony Jones   SCSI: convert str...
174
  	struct Scsi_Host *shost = class_to_shost(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
177
178
179
180
181
  	int res;
  
  	res = scsi_scan(shost, buf);
  	if (res == 0)
  		res = count;
  	return res;
  };
ee959b00c   Tony Jones   SCSI: convert str...
182
  static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183

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

5dc2b89e1   FUJITA Tomonori   [SCSI] add suppor...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
  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...
240
241
242
  static ssize_t
  show_shost_supported_mode(struct device *dev, struct device_attribute *attr,
  			  char *buf)
5dc2b89e1   FUJITA Tomonori   [SCSI] add suppor...
243
  {
ee959b00c   Tony Jones   SCSI: convert str...
244
  	struct Scsi_Host *shost = class_to_shost(dev);
7a39ac3f2   James Bottomley   [SCSI] make suppo...
245
  	unsigned int supported_mode = shost->hostt->supported_mode;
5dc2b89e1   FUJITA Tomonori   [SCSI] add suppor...
246

7a39ac3f2   James Bottomley   [SCSI] make suppo...
247
248
249
250
251
  	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...
252
  }
ee959b00c   Tony Jones   SCSI: convert str...
253
  static DEVICE_ATTR(supported_mode, S_IRUGO | S_IWUSR, show_shost_supported_mode, NULL);
5dc2b89e1   FUJITA Tomonori   [SCSI] add suppor...
254

ee959b00c   Tony Jones   SCSI: convert str...
255
256
257
  static ssize_t
  show_shost_active_mode(struct device *dev,
  		       struct device_attribute *attr, char *buf)
5dc2b89e1   FUJITA Tomonori   [SCSI] add suppor...
258
  {
ee959b00c   Tony Jones   SCSI: convert str...
259
  	struct Scsi_Host *shost = class_to_shost(dev);
5dc2b89e1   FUJITA Tomonori   [SCSI] add suppor...
260
261
262
263
264
265
266
  
  	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...
267
  static DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL);
5dc2b89e1   FUJITA Tomonori   [SCSI] add suppor...
268

072f19b4b   Sasha Levin   [SCSI] prevent st...
269
  static int check_reset_type(const char *str)
294436914   Vikas Chaudhary   [SCSI] scsi: Adde...
270
  {
072f19b4b   Sasha Levin   [SCSI] prevent st...
271
  	if (sysfs_streq(str, "adapter"))
294436914   Vikas Chaudhary   [SCSI] scsi: Adde...
272
  		return SCSI_ADAPTER_RESET;
072f19b4b   Sasha Levin   [SCSI] prevent st...
273
  	else if (sysfs_streq(str, "firmware"))
294436914   Vikas Chaudhary   [SCSI] scsi: Adde...
274
275
276
277
278
279
280
281
282
283
284
285
  		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...
286
  	int type;
072f19b4b   Sasha Levin   [SCSI] prevent st...
287
  	type = check_reset_type(buf);
294436914   Vikas Chaudhary   [SCSI] scsi: Adde...
288
289
290
291
292
  	if (!type)
  		goto exit_store_host_reset;
  
  	if (sht->host_reset)
  		ret = sht->host_reset(shost, type);
92227b8d3   weiping zhang   scsi: scsi-sysfs:...
293
294
  	else
  		ret = -EOPNOTSUPP;
294436914   Vikas Chaudhary   [SCSI] scsi: Adde...
295
296
297
298
299
300
301
302
  
  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...
303
304
305
306
307
  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...
308
309
310
311
312
  	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...
313
314
315
316
317
318
319
320
  }
  
  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...
321
  	unsigned long deadline, flags;
b45620229   Hannes Reinecke   [SCSI] Add 'eh_de...
322

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

ccf1e0045   Bart Van Assche   scsi: Rework hand...
444
445
446
447
448
449
450
451
452
453
454
  	mutex_lock(&sdev->inquiry_mutex);
  	rcu_swap_protected(sdev->vpd_pg80, vpd_pg80,
  			   lockdep_is_held(&sdev->inquiry_mutex));
  	rcu_swap_protected(sdev->vpd_pg83, vpd_pg83,
  			   lockdep_is_held(&sdev->inquiry_mutex));
  	mutex_unlock(&sdev->inquiry_mutex);
  
  	if (vpd_pg83)
  		kfree_rcu(vpd_pg83, rcu);
  	if (vpd_pg80)
  		kfree_rcu(vpd_pg80, rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
456
457
458
459
460
  	kfree(sdev->inquiry);
  	kfree(sdev);
  
  	if (parent)
  		put_device(parent);
  }
65110b216   James Bottomley   [SCSI] fix wrong ...
461
462
  static void scsi_device_dev_release(struct device *dev)
  {
ffedb4522   James Bottomley   [SCSI] fix scsi p...
463
  	struct scsi_device *sdp = to_scsi_device(dev);
65f27f384   David Howells   WorkStruct: Pass ...
464
  	execute_in_process_context(scsi_device_dev_release_usercontext,
ffedb4522   James Bottomley   [SCSI] fix scsi p...
465
  				   &sdp->ew);
65110b216   James Bottomley   [SCSI] fix wrong ...
466
  }
52c1da395   Adrian Bunk   [PATCH] make vari...
467
  static struct class sdev_class = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
  	.name		= "scsi_device",
ee959b00c   Tony Jones   SCSI: convert str...
469
  	.dev_release	= scsi_device_cls_release,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
471
472
473
474
  };
  
  /* 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...
475
476
477
478
479
480
  	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
481
482
483
484
  	if (sdp->no_uld_attach)
  		return 0;
  	return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
  }
7eff2e7a8   Kay Sievers   Driver core: chan...
485
  static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
d7b8bcb0a   Michael Tokarev   [SCSI] modalias f...
486
  {
1f42ea7bc   James Bottomley   [SCSI] fix interm...
487
488
489
490
491
492
  	struct scsi_device *sdev;
  
  	if (dev->type != &scsi_dev_type)
  		return 0;
  
  	sdev = to_scsi_device(dev);
d7b8bcb0a   Michael Tokarev   [SCSI] modalias f...
493

7eff2e7a8   Kay Sievers   Driver core: chan...
494
  	add_uevent_var(env, "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type);
d7b8bcb0a   Michael Tokarev   [SCSI] modalias f...
495
496
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497
498
499
  struct bus_type scsi_bus_type = {
          .name		= "scsi",
          .match		= scsi_bus_match,
d7b8bcb0a   Michael Tokarev   [SCSI] modalias f...
500
  	.uevent		= scsi_bus_uevent,
aa3386015   Rafael J. Wysocki   PM: Remove CONFIG...
501
  #ifdef CONFIG_PM
db5bd1e0b   Alan Stern   [SCSI] convert to...
502
  	.pm		= &scsi_bus_pm_ops,
e6da54d84   Alan Stern   SCSI: remove fake...
503
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
  };
a6a8d9f87   Chandra Seetharaman   [SCSI] scsi_dh: a...
505
  EXPORT_SYMBOL_GPL(scsi_bus_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
  
  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...
533
534
  sdev_show_##field (struct device *dev, struct device_attribute *attr,	\
  		   char *buf)						\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
  {									\
  	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...
551
   * sdev_rw_attr: create a function and attribute variable for a
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
553
554
555
556
557
   * 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...
558
559
  sdev_store_##field (struct device *dev, struct device_attribute *attr,	\
  		    const char *buf, size_t count)			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
560
561
562
  {									\
  	struct scsi_device *sdev;					\
  	sdev = to_scsi_device(dev);					\
160e7f671   Tomohiro Kusumi   [SCSI] fix sdev_r...
563
  	sscanf (buf, format_string, &sdev->field);			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
  	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...
580
581
  sdev_store_##field (struct device *dev, struct device_attribute *attr,	\
  		    const char *buf, size_t count)			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
  {									\
  	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
616
617
618
619
620
621
622
623
624
625
  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...
626
627
628
629
630
631
632
633
634
  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...
635
636
637
638
639
640
641
642
643
  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...
644
645
646
  /*
   * TODO: can we make these symlinks to the block layer ones?
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
  static ssize_t
10523b3b8   Yani Ioannou   [PATCH] Driver Co...
648
  sdev_show_timeout (struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
650
651
  {
  	struct scsi_device *sdev;
  	sdev = to_scsi_device(dev);
242f9dcb8   Jens Axboe   block: unify requ...
652
653
  	return snprintf(buf, 20, "%d
  ", sdev->request_queue->rq_timeout / HZ);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
655
656
  }
  
  static ssize_t
ee959b00c   Tony Jones   SCSI: convert str...
657
658
  sdev_store_timeout (struct device *dev, struct device_attribute *attr,
  		    const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
661
662
663
664
  {
  	struct scsi_device *sdev;
  	int timeout;
  	sdev = to_scsi_device(dev);
  	sscanf (buf, "%d
  ", &timeout);
242f9dcb8   Jens Axboe   block: unify requ...
665
  	blk_queue_rq_timeout(sdev->request_queue, timeout * HZ);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
668
669
670
  	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...
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
  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...
701
702
  store_rescan_field (struct device *dev, struct device_attribute *attr,
  		    const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
704
705
706
707
  {
  	scsi_rescan_device(dev);
  	return count;
  }
  static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);
ee959b00c   Tony Jones   SCSI: convert str...
708
709
710
  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
711
  {
5b55b24ce   Bart Van Assche   scsi: core: Avoid...
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
  	struct kernfs_node *kn;
  
  	kn = sysfs_break_active_protection(&dev->kobj, &attr->attr);
  	WARN_ON_ONCE(!kn);
  	/*
  	 * Concurrent writes into the "delete" sysfs attribute may trigger
  	 * concurrent calls to device_remove_file() and scsi_remove_device().
  	 * device_remove_file() handles concurrent removal calls by
  	 * serializing these and by ignoring the second and later removal
  	 * attempts.  Concurrent calls of scsi_remove_device() are
  	 * serialized. The second and later calls of scsi_remove_device() are
  	 * ignored because the first call of that function changes the device
  	 * state into SDEV_DEL.
  	 */
  	device_remove_file(dev, attr);
  	scsi_remove_device(to_scsi_device(dev));
  	if (kn)
  		sysfs_unbreak_active_protection(kn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
730
731
732
733
734
  	return count;
  };
  static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
  
  static ssize_t
ee959b00c   Tony Jones   SCSI: convert str...
735
736
  store_state_field(struct device *dev, struct device_attribute *attr,
  		  const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
737
  {
0db6ca8a5   Bart Van Assche   scsi: Protect SCS...
738
  	int i, ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
740
  	struct scsi_device *sdev = to_scsi_device(dev);
  	enum scsi_device_state state = 0;
6391a1137   Tobias Klauser   [SCSI] drivers/sc...
741
  	for (i = 0; i < ARRAY_SIZE(sdev_states); i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
743
744
745
746
747
748
749
750
751
  		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;
0db6ca8a5   Bart Van Assche   scsi: Protect SCS...
752
753
754
755
756
  	mutex_lock(&sdev->state_mutex);
  	ret = scsi_device_set_state(sdev, state);
  	mutex_unlock(&sdev->state_mutex);
  
  	return ret == 0 ? count : -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
757
758
759
  }
  
  static ssize_t
10523b3b8   Yani Ioannou   [PATCH] Driver Co...
760
  show_state_field(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
761
762
763
764
765
766
767
768
769
770
771
772
773
774
  {
  	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...
775
776
  show_queue_type_field(struct device *dev, struct device_attribute *attr,
  		      char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777
778
779
  {
  	struct scsi_device *sdev = to_scsi_device(dev);
  	const char *name = "none";
609aa22f3   Christoph Hellwig   scsi: remove orde...
780
  	if (sdev->simple_tags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
781
782
783
784
785
  		name = "simple";
  
  	return snprintf(buf, 20, "%s
  ", name);
  }
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
786
787
788
789
790
  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...
791

efc3c1df5   Christoph Hellwig   scsi: remove ->ch...
792
  	if (!sdev->tagged_supported)
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
793
  		return -EINVAL;
efc3c1df5   Christoph Hellwig   scsi: remove ->ch...
794
795
796
  		
  	sdev_printk(KERN_INFO, sdev,
  		    "ignoring write to deprecated queue_type attribute");
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
797
798
799
800
801
  	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
802

b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
803
804
805
806
807
808
809
810
  #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);			\
ccf1e0045   Bart Van Assche   scsi: Rework hand...
811
812
813
  	struct scsi_vpd *vpd_page;					\
  	int ret = -EINVAL;						\
  									\
09e2b0b14   Hannes Reinecke   scsi: rescan VPD ...
814
  	rcu_read_lock();						\
ccf1e0045   Bart Van Assche   scsi: Rework hand...
815
816
817
818
  	vpd_page = rcu_dereference(sdev->vpd_##_page);			\
  	if (vpd_page)							\
  		ret = memory_read_from_buffer(buf, count, &off,		\
  				vpd_page->data, vpd_page->len);		\
09e2b0b14   Hannes Reinecke   scsi: rescan VPD ...
819
  	rcu_read_unlock();						\
ccf1e0045   Bart Van Assche   scsi: Rework hand...
820
  	return ret;							\
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
821
822
823
824
825
826
827
828
829
  }									\
  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
830

92e6246c8   Johannes Thumshirn   scsi: Export SCSI...
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
  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
853
  static ssize_t
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
854
855
  show_iostat_counterbits(struct device *dev, struct device_attribute *attr,
  			char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
857
858
859
860
861
862
863
864
  {
  	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...
865
866
  show_iostat_##field(struct device *dev, struct device_attribute *attr,	\
  		    char *buf)						\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867
868
869
870
871
872
873
874
875
876
877
  {									\
  	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...
878
879
880
881
882
883
884
885
886
  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
887

a341cd0f6   Jeff Garzik   SCSI: add asynchr...
888
889
890
  #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...
891
  		     char *buf)						\
a341cd0f6   Jeff Garzik   SCSI: add asynchr...
892
893
894
895
896
897
898
899
900
  {									\
  	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...
901
  sdev_store_evt_##name(struct device *dev, struct device_attribute *attr,\
a341cd0f6   Jeff Garzik   SCSI: add asynchr...
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
  		      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...
923
924
925
926
927
  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...
928

ee959b00c   Tony Jones   SCSI: convert str...
929
  static ssize_t
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
930
931
  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
932
933
934
935
936
937
938
939
940
  {
  	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...
941
  	if (depth < 1 || depth > sdev->host->can_queue)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
942
  		return -EINVAL;
db5ed4dfd   Christoph Hellwig   scsi: drop reason...
943
  	retval = sht->change_queue_depth(sdev, depth);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
944
945
  	if (retval < 0)
  		return retval;
4a84067db   Vasu Dev   [SCSI] add queue_...
946
  	sdev->max_queue_depth = sdev->queue_depth;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
947
948
  	return count;
  }
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
949
950
  sdev_show_function(queue_depth, "%d
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
951

276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
952
953
  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
954

248d4fe95   Hannes Reinecke   scsi: export 'wwi...
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
  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...
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
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
  #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...
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
  
  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...
1066
  #endif
ee959b00c   Tony Jones   SCSI: convert str...
1067
  static ssize_t
4a84067db   Vasu Dev   [SCSI] add queue_...
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
  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...
1085
  	unsigned int period;
4a84067db   Vasu Dev   [SCSI] add queue_...
1086

f7c65af51   Daniel Walter   drivers/scsi: rep...
1087
  	if (kstrtouint(buf, 10, &period))
4a84067db   Vasu Dev   [SCSI] add queue_...
1088
1089
1090
  		return -EINVAL;
  
  	sdev->queue_ramp_up_period = msecs_to_jiffies(period);
5cb9b40d6   Peter Oberparleiter   scsi_sysfs: Fix q...
1091
  	return count;
4a84067db   Vasu Dev   [SCSI] add queue_...
1092
  }
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1093
1094
1095
  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_...
1096

276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1097
1098
  static umode_t scsi_sdev_attr_is_visible(struct kobject *kobj,
  					 struct attribute *attr, int i)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1099
  {
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1100
  	struct device *dev = container_of(kobj, struct device, kobj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1101
  	struct scsi_device *sdev = to_scsi_device(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1102

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1103

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

276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1108
1109
1110
  	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
1111

77c9df964   Hannes Reinecke   scsi: Add 'access...
1112
1113
1114
1115
1116
1117
1118
1119
  #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...
1120
  	return attr->mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1121
  }
7e47976bc   Hannes Reinecke   scsi_sysfs: add '...
1122
1123
1124
1125
1126
1127
1128
1129
1130
  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...
1131
  	if (attr == &dev_attr_vpd_pg83 && !sdev->vpd_pg83)
7e47976bc   Hannes Reinecke   scsi_sysfs: add '...
1132
1133
1134
1135
  		return 0;
  
  	return S_IRUGO;
  }
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
  /* 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...
1157
  	&dev_attr_wwid.attr,
41f95dd2e   Hannes Reinecke   scsi_dh: move 'dh...
1158
1159
  #ifdef CONFIG_SCSI_DH
  	&dev_attr_dh_state.attr,
77c9df964   Hannes Reinecke   scsi: Add 'access...
1160
1161
  	&dev_attr_access_state.attr,
  	&dev_attr_preferred_path.attr,
41f95dd2e   Hannes Reinecke   scsi_dh: move 'dh...
1162
  #endif
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1163
1164
1165
1166
1167
1168
1169
1170
1171
  	&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...
1172
1173
1174
  static struct bin_attribute *scsi_sdev_bin_attrs[] = {
  	&dev_attr_vpd_pg83,
  	&dev_attr_vpd_pg80,
92e6246c8   Johannes Thumshirn   scsi: Export SCSI...
1175
  	&dev_attr_inquiry,
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
1176
1177
  	NULL
  };
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1178
1179
  static struct attribute_group scsi_sdev_attr_group = {
  	.attrs =	scsi_sdev_attrs,
b3ae8780b   Hannes Reinecke   [SCSI] Add EVPD p...
1180
  	.bin_attrs =	scsi_sdev_bin_attrs,
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1181
  	.is_visible =	scsi_sdev_attr_is_visible,
7e47976bc   Hannes Reinecke   scsi_sysfs: add '...
1182
  	.is_bin_visible = scsi_sdev_bin_attr_is_visible,
276b20d09   Hannes Reinecke   [SCSI] scsi_sysfs...
1183
1184
1185
1186
1187
1188
  };
  
  static const struct attribute_group *scsi_sdev_attr_groups[] = {
  	&scsi_sdev_attr_group,
  	NULL
  };
643eb2d93   James Bottomley   [SCSI] rework scs...
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
  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...
1200
1201
1202
1203
  		return error;
  	}
  	transport_add_device(&starget->dev);
  	starget->state = STARGET_RUNNING;
bc4f24014   Alan Stern   [SCSI] implement ...
1204
1205
1206
  	pm_runtime_set_active(&starget->dev);
  	pm_runtime_enable(&starget->dev);
  	device_enable_async_suspend(&starget->dev);
643eb2d93   James Bottomley   [SCSI] rework scs...
1207
1208
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
  /**
   * 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...
1219
  	struct request_queue *rq = sdev->request_queue;
643eb2d93   James Bottomley   [SCSI] rework scs...
1220
  	struct scsi_target *starget = sdev->sdev_target;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1221

643eb2d93   James Bottomley   [SCSI] rework scs...
1222
1223
1224
1225
1226
  	error = scsi_target_add(starget);
  	if (error)
  		return error;
  
  	transport_configure_device(&starget->dev);
bc4f24014   Alan Stern   [SCSI] implement ...
1227

4cb077d93   Rafael J. Wysocki   PM: Allow SCSI de...
1228
  	device_enable_async_suspend(&sdev->sdev_gendev);
bc4f24014   Alan Stern   [SCSI] implement ...
1229
1230
1231
1232
1233
  	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 ...
1234
  	scsi_autopm_get_device(sdev);
086b91d05   Christoph Hellwig   scsi_dh: integrat...
1235
  	error = scsi_dh_add_device(sdev);
221255aee   Hannes Reinecke   scsi: ignore erro...
1236
1237
1238
1239
  	if (error)
  		/*
  		 * device_handler is optional, so any error can be ignored
  		 */
086b91d05   Christoph Hellwig   scsi_dh: integrat...
1240
1241
1242
  		sdev_printk(KERN_INFO, sdev,
  				"failed to add device handler: %d
  ", error);
086b91d05   Christoph Hellwig   scsi_dh: integrat...
1243

4cd2459c0   Hannes Reinecke   scsi_sysfs: call ...
1244
1245
1246
1247
1248
1249
1250
1251
  	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...
1252
  	device_enable_async_suspend(&sdev->sdev_dev);
ee959b00c   Tony Jones   SCSI: convert str...
1253
  	error = device_add(&sdev->sdev_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1254
  	if (error) {
73d8c34f3   Alan Stern   SCSI: improve two...
1255
1256
1257
  		sdev_printk(KERN_INFO, sdev,
  				"failed to add class device: %d
  ", error);
086b91d05   Christoph Hellwig   scsi_dh: integrat...
1258
  		scsi_dh_remove_device(sdev);
860dc7360   James Bottomley   [SCSI] fix async ...
1259
  		device_del(&sdev->sdev_gendev);
ee37e09d8   Alan Stern   [SCSI] fix duplic...
1260
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1261
  	}
860dc7360   James Bottomley   [SCSI] fix async ...
1262
1263
  	transport_add_device(&sdev->sdev_gendev);
  	sdev->is_visible = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1264

97f46ae45   FUJITA Tomonori   [SCSI] bsg: add r...
1265
  	error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL, NULL);
80ed71ce1   James Bottomley   [SCSI] bsg: separ...
1266
1267
  
  	if (error)
860dc7360   James Bottomley   [SCSI] fix async ...
1268
1269
  		/* we're treating error on bsg register as non-fatal,
  		 * so pretend nothing went wrong */
80ed71ce1   James Bottomley   [SCSI] bsg: separ...
1270
1271
1272
  		sdev_printk(KERN_INFO, sdev,
  			    "Failed to register bsg queue, errno=%d
  ", error);
bfd129445   Kay Sievers   [SCSI] switch sde...
1273
  	/* add additional host specific attributes */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1274
1275
  	if (sdev->host->hostt->sdev_attrs) {
  		for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) {
bfd129445   Kay Sievers   [SCSI] switch sde...
1276
  			error = device_create_file(&sdev->sdev_gendev,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1277
  					sdev->host->hostt->sdev_attrs[i]);
860dc7360   James Bottomley   [SCSI] fix async ...
1278
  			if (error)
ee37e09d8   Alan Stern   [SCSI] fix duplic...
1279
  				return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1280
1281
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1282

6fe8c1dbe   Subhash Jadavani   scsi: balance out...
1283
  	scsi_autopm_put_device(sdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1284
1285
  	return error;
  }
903f4fed8   Alan Stern   [SCSI] fix caller...
1286
  void __scsi_remove_device(struct scsi_device *sdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1287
  {
df133c212   James Bottomley   [SCSI] Fix transp...
1288
  	struct device *dev = &sdev->sdev_gendev;
0db6ca8a5   Bart Van Assche   scsi: Protect SCS...
1289
  	int res;
df133c212   James Bottomley   [SCSI] Fix transp...
1290

be821fd8e   Vitaly Kuznetsov   scsi_sysfs: prote...
1291
1292
1293
1294
1295
1296
1297
  	/*
  	 * 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 ...
1298
  	if (sdev->is_visible) {
0db6ca8a5   Bart Van Assche   scsi: Protect SCS...
1299
1300
1301
1302
1303
  		/*
  		 * If scsi_internal_target_block() is running concurrently,
  		 * wait until it has finished before changing the device state.
  		 */
  		mutex_lock(&sdev->state_mutex);
255ee9320   Bart Van Assche   scsi: Make __scsi...
1304
1305
1306
1307
1308
  		/*
  		 * If blocked, we go straight to DEL and restart the queue so
  		 * any commands issued during driver shutdown (like sync
  		 * cache) are errored immediately.
  		 */
0db6ca8a5   Bart Van Assche   scsi: Protect SCS...
1309
  		res = scsi_device_set_state(sdev, SDEV_CANCEL);
255ee9320   Bart Van Assche   scsi: Make __scsi...
1310
1311
1312
1313
1314
  		if (res != 0) {
  			res = scsi_device_set_state(sdev, SDEV_DEL);
  			if (res == 0)
  				scsi_start_queue(sdev);
  		}
0db6ca8a5   Bart Van Assche   scsi: Protect SCS...
1315
1316
1317
  		mutex_unlock(&sdev->state_mutex);
  
  		if (res != 0)
860dc7360   James Bottomley   [SCSI] fix async ...
1318
  			return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1319

860dc7360   James Bottomley   [SCSI] fix async ...
1320
1321
1322
  		bsg_unregister_queue(sdev->request_queue);
  		device_unregister(&sdev->sdev_dev);
  		transport_remove_device(dev);
086b91d05   Christoph Hellwig   scsi_dh: integrat...
1323
  		scsi_dh_remove_device(sdev);
e619e6cbe   Bart Van Assche   Revert "scsi: Fix...
1324
1325
1326
  		device_del(dev);
  	} else
  		put_device(&sdev->sdev_dev);
b485462ac   Bart Van Assche   [SCSI] Stop accep...
1327
1328
1329
1330
1331
1332
  
  	/*
  	 * Stop accepting new requests and wait until all queuecommand() and
  	 * scsi_run_queue() invocations have finished before tearing down the
  	 * device.
  	 */
0db6ca8a5   Bart Van Assche   scsi: Protect SCS...
1333
  	mutex_lock(&sdev->state_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1334
  	scsi_device_set_state(sdev, SDEV_DEL);
0db6ca8a5   Bart Van Assche   scsi: Protect SCS...
1335
  	mutex_unlock(&sdev->state_mutex);
b485462ac   Bart Van Assche   [SCSI] Stop accep...
1336
1337
  	blk_cleanup_queue(sdev->request_queue);
  	cancel_work_sync(&sdev->requeue_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1338
1339
  	if (sdev->host->hostt->slave_destroy)
  		sdev->host->hostt->slave_destroy(sdev);
df133c212   James Bottomley   [SCSI] Fix transp...
1340
  	transport_destroy_device(dev);
86cbfb560   James Bottomley   [SCSI] put strict...
1341

e63ed0d7a   James Bottomley   [SCSI] fix our cu...
1342
1343
1344
1345
1346
1347
  	/*
  	 * 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...
1348
  	put_device(dev);
903f4fed8   Alan Stern   [SCSI] fix caller...
1349
1350
1351
1352
1353
1354
1355
1356
  }
  
  /**
   * 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...
1357
  	struct Scsi_Host *shost = sdev->host;
0b9506723   Arjan van de Ven   [SCSI] turn most ...
1358
  	mutex_lock(&shost->scan_mutex);
903f4fed8   Alan Stern   [SCSI] fix caller...
1359
  	__scsi_remove_device(sdev);
0b9506723   Arjan van de Ven   [SCSI] turn most ...
1360
  	mutex_unlock(&shost->scan_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1361
1362
  }
  EXPORT_SYMBOL(scsi_remove_device);
44818efba   Adrian Bunk   [SCSI] small clea...
1363
  static void __scsi_remove_target(struct scsi_target *starget)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1364
1365
1366
  {
  	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
  	unsigned long flags;
a64358db1   Alan Stern   [SCSI] SCSI scann...
1367
  	struct scsi_device *sdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1368
1369
  
  	spin_lock_irqsave(shost->host_lock, flags);
a64358db1   Alan Stern   [SCSI] SCSI scann...
1370
1371
   restart:
  	list_for_each_entry(sdev, &shost->__devices, siblings) {
fbce4d97f   Hannes Reinecke   scsi: fixup kerne...
1372
1373
1374
1375
1376
1377
  		/*
  		 * We cannot call scsi_device_get() here, as
  		 * we might've been called from rmmod() causing
  		 * scsi_device_get() to fail the module_is_live()
  		 * check.
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1378
  		if (sdev->channel != starget->channel ||
875758d79   Hannes Reinecke   scsi: core: check...
1379
1380
1381
1382
  		    sdev->id != starget->id)
  			continue;
  		if (sdev->sdev_state == SDEV_DEL ||
  		    sdev->sdev_state == SDEV_CANCEL ||
fbce4d97f   Hannes Reinecke   scsi: fixup kerne...
1383
  		    !get_device(&sdev->sdev_gendev))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1384
1385
1386
  			continue;
  		spin_unlock_irqrestore(shost->host_lock, flags);
  		scsi_remove_device(sdev);
fbce4d97f   Hannes Reinecke   scsi: fixup kerne...
1387
  		put_device(&sdev->sdev_gendev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1388
  		spin_lock_irqsave(shost->host_lock, flags);
a64358db1   Alan Stern   [SCSI] SCSI scann...
1389
  		goto restart;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1390
1391
  	}
  	spin_unlock_irqrestore(shost->host_lock, flags);
20b1e6742   Patrick Mochel   [PATCH] Use devic...
1392
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
  /**
   * 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...
1403
  	struct Scsi_Host *shost = dev_to_shost(dev->parent);
305c2e71b   Johannes Thumshirn   Revert "scsi: fix...
1404
  	struct scsi_target *starget;
3b661a92e   Dan Williams   [SCSI] fix hot un...
1405
  	unsigned long flags;
409981935   Christoph Hellwig   scsi: restart lis...
1406
  restart:
3b661a92e   Dan Williams   [SCSI] fix hot un...
1407
1408
  	spin_lock_irqsave(shost->host_lock, flags);
  	list_for_each_entry(starget, &shost->__targets, siblings) {
90a88d6ef   James Bottomley   scsi: fix soft lo...
1409
  		if (starget->state == STARGET_DEL ||
f9279c968   Ewan D. Milne   scsi: Add STARGET...
1410
1411
  		    starget->state == STARGET_REMOVE ||
  		    starget->state == STARGET_CREATED_REMOVE)
3b661a92e   Dan Williams   [SCSI] fix hot un...
1412
1413
  			continue;
  		if (starget->dev.parent == dev || &starget->dev == dev) {
e63ed0d7a   James Bottomley   [SCSI] fix our cu...
1414
  			kref_get(&starget->reap_ref);
f9279c968   Ewan D. Milne   scsi: Add STARGET...
1415
1416
1417
1418
  			if (starget->state == STARGET_CREATED)
  				starget->state = STARGET_CREATED_REMOVE;
  			else
  				starget->state = STARGET_REMOVE;
bc3f02a79   Dan Williams   [SCSI] scsi_remov...
1419
  			spin_unlock_irqrestore(shost->host_lock, flags);
bc3f02a79   Dan Williams   [SCSI] scsi_remov...
1420
  			__scsi_remove_target(starget);
409981935   Christoph Hellwig   scsi: restart lis...
1421
1422
  			scsi_target_reap(starget);
  			goto restart;
3b661a92e   Dan Williams   [SCSI] fix hot un...
1423
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1424
  	}
3b661a92e   Dan Williams   [SCSI] fix hot un...
1425
  	spin_unlock_irqrestore(shost->host_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
  }
  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
1444
1445
1446
  /**
   * 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
1447
1448
1449
1450
   **/
  int scsi_sysfs_add_host(struct Scsi_Host *shost)
  {
  	int error, i;
f7120a4f7   Hannes Reinecke   [SCSI] use defaul...
1451
  	/* add host specific attributes */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1452
1453
  	if (shost->hostt->shost_attrs) {
  		for (i = 0; shost->hostt->shost_attrs[i]; i++) {
ee959b00c   Tony Jones   SCSI: convert str...
1454
  			error = device_create_file(&shost->shost_dev,
f7120a4f7   Hannes Reinecke   [SCSI] use defaul...
1455
  					shost->hostt->shost_attrs[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1456
1457
1458
1459
1460
1461
  			if (error)
  				return error;
  		}
  	}
  
  	transport_register_device(&shost->shost_gendev);
d52b3815a   James Bottomley   [SCSI] add missin...
1462
  	transport_configure_device(&shost->shost_gendev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1463
1464
  	return 0;
  }
bfd129445   Kay Sievers   [SCSI] switch sde...
1465
1466
1467
1468
1469
  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
1470
1471
1472
1473
1474
1475
1476
1477
  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...
1478
  	sdev->sdev_gendev.type = &scsi_dev_type;
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
1479
  	dev_set_name(&sdev->sdev_gendev, "%d:%d:%d:%llu",
71610f55f   Kay Sievers   [SCSI] struct dev...
1480
  		     sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
ee959b00c   Tony Jones   SCSI: convert str...
1481
  	device_initialize(&sdev->sdev_dev);
37e6ba007   James Bottomley   [SCSI] fix memory...
1482
  	sdev->sdev_dev.parent = get_device(&sdev->sdev_gendev);
ee959b00c   Tony Jones   SCSI: convert str...
1483
  	sdev->sdev_dev.class = &sdev_class;
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
1484
  	dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%llu",
71610f55f   Kay Sievers   [SCSI] struct dev...
1485
  		     sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
50c4e9641   Alan Stern   scsi: don't store...
1486
1487
1488
1489
1490
1491
1492
  	/*
  	 * 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:...
1493
  	sdev->scsi_level = starget->scsi_level;
50c4e9641   Alan Stern   scsi: don't store...
1494
1495
1496
1497
  	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
1498
1499
1500
1501
1502
  	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...
1503
1504
1505
1506
1507
1508
  	/*
  	 * 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
1509
1510
1511
1512
  }
  
  int scsi_is_sdev_device(const struct device *dev)
  {
13ba9bcbf   Kay Sievers   [SCSI] fix scsi_i...
1513
  	return dev->type == &scsi_dev_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1514
1515
1516
1517
1518
1519
  }
  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, }, }, }, };