patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / scsi / scsi_sysfs.c
1 /*
2  * scsi_sysfs.c
3  *
4  * SCSI sysfs interface routines.
5  *
6  * Created to pull SCSI mid layer sysfs routines into one file.
7  */
8
9 #include <linux/config.h>
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/blkdev.h>
13 #include <linux/device.h>
14
15 #include <scsi/scsi_host.h>
16 #include <scsi/scsi_transport.h>
17 #include "scsi.h"
18
19 #include "scsi_priv.h"
20 #include "scsi_logging.h"
21
22 static struct {
23         enum scsi_device_state  value;
24         char                    *name;
25 } sdev_states[] = {
26         { SDEV_CREATED, "created" },
27         { SDEV_RUNNING, "running" },
28         { SDEV_CANCEL, "cancel" },
29         { SDEV_DEL, "deleted" },
30         { SDEV_QUIESCE, "quiesce" },
31         { SDEV_OFFLINE, "offline" },
32 };
33
34 const char *scsi_device_state_name(enum scsi_device_state state)
35 {
36         int i;
37         char *name = NULL;
38
39         for (i = 0; i < sizeof(sdev_states)/sizeof(sdev_states[0]); i++) {
40                 if (sdev_states[i].value == state) {
41                         name = sdev_states[i].name;
42                         break;
43                 }
44         }
45         return name;
46 }
47
48 static int check_set(unsigned int *val, char *src)
49 {
50         char *last;
51
52         if (strncmp(src, "-", 20) == 0) {
53                 *val = SCAN_WILD_CARD;
54         } else {
55                 /*
56                  * Doesn't check for int overflow
57                  */
58                 *val = simple_strtoul(src, &last, 0);
59                 if (*last != '\0')
60                         return 1;
61         }
62         return 0;
63 }
64
65 static int scsi_scan(struct Scsi_Host *shost, const char *str)
66 {
67         char s1[15], s2[15], s3[15], junk;
68         unsigned int channel, id, lun;
69         int res;
70
71         res = sscanf(str, "%10s %10s %10s %c", s1, s2, s3, &junk);
72         if (res != 3)
73                 return -EINVAL;
74         if (check_set(&channel, s1))
75                 return -EINVAL;
76         if (check_set(&id, s2))
77                 return -EINVAL;
78         if (check_set(&lun, s3))
79                 return -EINVAL;
80         res = scsi_scan_host_selected(shost, channel, id, lun, 1);
81         return res;
82 }
83
84 /*
85  * shost_show_function: macro to create an attr function that can be used to
86  * show a non-bit field.
87  */
88 #define shost_show_function(name, field, format_string)                 \
89 static ssize_t                                                          \
90 show_##name (struct class_device *class_dev, char *buf)                 \
91 {                                                                       \
92         struct Scsi_Host *shost = class_to_shost(class_dev);            \
93         return snprintf (buf, 20, format_string, shost->field);         \
94 }
95
96 /*
97  * shost_rd_attr: macro to create a function and attribute variable for a
98  * read only field.
99  */
100 #define shost_rd_attr2(name, field, format_string)                      \
101         shost_show_function(name, field, format_string)                 \
102 static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
103
104 #define shost_rd_attr(field, format_string) \
105 shost_rd_attr2(field, field, format_string)
106
107 /*
108  * Create the actual show/store functions and data structures.
109  */
110
111 static ssize_t store_scan(struct class_device *class_dev, const char *buf,
112                           size_t count)
113 {
114         struct Scsi_Host *shost = class_to_shost(class_dev);
115         int res;
116
117         res = scsi_scan(shost, buf);
118         if (res == 0)
119                 res = count;
120         return res;
121 };
122 static CLASS_DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
123
124 shost_rd_attr(unique_id, "%u\n");
125 shost_rd_attr(host_busy, "%hu\n");
126 shost_rd_attr(cmd_per_lun, "%hd\n");
127 shost_rd_attr(sg_tablesize, "%hu\n");
128 shost_rd_attr(unchecked_isa_dma, "%d\n");
129 shost_rd_attr2(proc_name, hostt->proc_name, "%s\n");
130
131 static struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
132         &class_device_attr_unique_id,
133         &class_device_attr_host_busy,
134         &class_device_attr_cmd_per_lun,
135         &class_device_attr_sg_tablesize,
136         &class_device_attr_unchecked_isa_dma,
137         &class_device_attr_proc_name,
138         &class_device_attr_scan,
139         NULL
140 };
141
142 static void scsi_device_cls_release(struct class_device *class_dev)
143 {
144         struct scsi_device *sdev;
145
146         sdev = class_to_sdev(class_dev);
147         put_device(&sdev->sdev_gendev);
148 }
149
150 void scsi_device_dev_release(struct device *dev)
151 {
152         struct scsi_device *sdev;
153         struct device *parent;
154         unsigned long flags;
155
156         parent = dev->parent;
157         sdev = to_scsi_device(dev);
158
159         spin_lock_irqsave(sdev->host->host_lock, flags);
160         list_del(&sdev->siblings);
161         list_del(&sdev->same_target_siblings);
162         list_del(&sdev->starved_entry);
163         if (sdev->single_lun && --sdev->sdev_target->starget_refcnt == 0)
164                 kfree(sdev->sdev_target);
165         spin_unlock_irqrestore(sdev->host->host_lock, flags);
166
167         if (sdev->request_queue)
168                 scsi_free_queue(sdev->request_queue);
169
170         kfree(sdev->inquiry);
171         kfree(sdev);
172
173         put_device(parent);
174 }
175
176 struct class sdev_class = {
177         .name           = "scsi_device",
178         .release        = scsi_device_cls_release,
179 };
180
181 /* all probing is done in the individual ->probe routines */
182 static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
183 {
184         struct scsi_device *sdp = to_scsi_device(dev);
185         return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
186 }
187
188 struct bus_type scsi_bus_type = {
189         .name           = "scsi",
190         .match          = scsi_bus_match,
191 };
192
193 int scsi_sysfs_register(void)
194 {
195         int error;
196
197         error = bus_register(&scsi_bus_type);
198         if (!error) {
199                 error = class_register(&sdev_class);
200                 if (error)
201                         bus_unregister(&scsi_bus_type);
202         }
203
204         return error;
205 }
206
207 void scsi_sysfs_unregister(void)
208 {
209         class_unregister(&sdev_class);
210         bus_unregister(&scsi_bus_type);
211 }
212
213 /*
214  * sdev_show_function: macro to create an attr function that can be used to
215  * show a non-bit field.
216  */
217 #define sdev_show_function(field, format_string)                                \
218 static ssize_t                                                          \
219 sdev_show_##field (struct device *dev, char *buf)                               \
220 {                                                                       \
221         struct scsi_device *sdev;                                       \
222         sdev = to_scsi_device(dev);                                     \
223         return snprintf (buf, 20, format_string, sdev->field);          \
224 }                                                                       \
225
226 /*
227  * sdev_rd_attr: macro to create a function and attribute variable for a
228  * read only field.
229  */
230 #define sdev_rd_attr(field, format_string)                              \
231         sdev_show_function(field, format_string)                                \
232 static DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL)
233
234
235 /*
236  * sdev_rd_attr: create a function and attribute variable for a
237  * read/write field.
238  */
239 #define sdev_rw_attr(field, format_string)                              \
240         sdev_show_function(field, format_string)                                \
241                                                                         \
242 static ssize_t                                                          \
243 sdev_store_##field (struct device *dev, const char *buf, size_t count)  \
244 {                                                                       \
245         struct scsi_device *sdev;                                       \
246         sdev = to_scsi_device(dev);                                     \
247         snscanf (buf, 20, format_string, &sdev->field);                 \
248         return count;                                                   \
249 }                                                                       \
250 static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field)
251
252 /* Currently we don't export bit fields, but we might in future,
253  * so leave this code in */
254 #if 0
255 /*
256  * sdev_rd_attr: create a function and attribute variable for a
257  * read/write bit field.
258  */
259 #define sdev_rw_attr_bit(field)                                         \
260         sdev_show_function(field, "%d\n")                                       \
261                                                                         \
262 static ssize_t                                                          \
263 sdev_store_##field (struct device *dev, const char *buf, size_t count)  \
264 {                                                                       \
265         int ret;                                                        \
266         struct scsi_device *sdev;                                       \
267         ret = scsi_sdev_check_buf_bit(buf);                             \
268         if (ret >= 0)   {                                               \
269                 sdev = to_scsi_device(dev);                             \
270                 sdev->field = ret;                                      \
271                 ret = count;                                            \
272         }                                                               \
273         return ret;                                                     \
274 }                                                                       \
275 static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field)
276
277 /*
278  * scsi_sdev_check_buf_bit: return 0 if buf is "0", return 1 if buf is "1",
279  * else return -EINVAL.
280  */
281 static int scsi_sdev_check_buf_bit(const char *buf)
282 {
283         if ((buf[1] == '\0') || ((buf[1] == '\n') && (buf[2] == '\0'))) {
284                 if (buf[0] == '1')
285                         return 1;
286                 else if (buf[0] == '0')
287                         return 0;
288                 else 
289                         return -EINVAL;
290         } else
291                 return -EINVAL;
292 }
293 #endif
294 /*
295  * Create the actual show/store functions and data structures.
296  */
297 sdev_rd_attr (device_blocked, "%d\n");
298 sdev_rd_attr (queue_depth, "%d\n");
299 sdev_rd_attr (type, "%d\n");
300 sdev_rd_attr (scsi_level, "%d\n");
301 sdev_rd_attr (vendor, "%.8s\n");
302 sdev_rd_attr (model, "%.16s\n");
303 sdev_rd_attr (rev, "%.4s\n");
304
305 static ssize_t
306 sdev_show_timeout (struct device *dev, char *buf)
307 {
308         struct scsi_device *sdev;
309         sdev = to_scsi_device(dev);
310         return snprintf (buf, 20, "%d\n", sdev->timeout / HZ);
311 }
312
313 static ssize_t
314 sdev_store_timeout (struct device *dev, const char *buf, size_t count)
315 {
316         struct scsi_device *sdev;
317         int timeout;
318         sdev = to_scsi_device(dev);
319         sscanf (buf, "%d\n", &timeout);
320         sdev->timeout = timeout * HZ;
321         return count;
322 }
323 static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout)
324
325 static ssize_t
326 store_rescan_field (struct device *dev, const char *buf, size_t count) 
327 {
328         scsi_rescan_device(dev);
329         return count;
330 }
331 static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field)
332
333 static ssize_t sdev_store_delete(struct device *dev, const char *buf,
334                                  size_t count)
335 {
336         scsi_remove_device(to_scsi_device(dev));
337         return count;
338 };
339 static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
340
341 static ssize_t
342 store_state_field(struct device *dev, const char *buf, size_t count)
343 {
344         int i;
345         struct scsi_device *sdev = to_scsi_device(dev);
346         enum scsi_device_state state = 0;
347
348         for (i = 0; i < sizeof(sdev_states)/sizeof(sdev_states[0]); i++) {
349                 const int len = strlen(sdev_states[i].name);
350                 if (strncmp(sdev_states[i].name, buf, len) == 0 &&
351                    buf[len] == '\n') {
352                         state = sdev_states[i].value;
353                         break;
354                 }
355         }
356         if (!state)
357                 return -EINVAL;
358
359         if (scsi_device_set_state(sdev, state))
360                 return -EINVAL;
361         return count;
362 }
363
364 static ssize_t
365 show_state_field(struct device *dev, char *buf)
366 {
367         struct scsi_device *sdev = to_scsi_device(dev);
368         const char *name = scsi_device_state_name(sdev->sdev_state);
369
370         if (!name)
371                 return -EINVAL;
372
373         return snprintf(buf, 20, "%s\n", name);
374 }
375
376 DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_state_field, store_state_field);
377
378
379 /* Default template for device attributes.  May NOT be modified */
380 static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
381         &dev_attr_device_blocked,
382         &dev_attr_queue_depth,
383         &dev_attr_type,
384         &dev_attr_scsi_level,
385         &dev_attr_vendor,
386         &dev_attr_model,
387         &dev_attr_rev,
388         &dev_attr_rescan,
389         &dev_attr_delete,
390         &dev_attr_state,
391         &dev_attr_timeout,
392         NULL
393 };
394
395
396 static struct device_attribute *attr_overridden(
397                 struct device_attribute **attrs,
398                 struct device_attribute *attr)
399 {
400         int i;
401
402         if (!attrs)
403                 return NULL;
404         for (i = 0; attrs[i]; i++)
405                 if (!strcmp(attrs[i]->attr.name, attr->attr.name))
406                         return attrs[i];
407         return NULL;
408 }
409
410 static int attr_add(struct device *dev, struct device_attribute *attr)
411 {
412         struct device_attribute *base_attr;
413
414         /*
415          * Spare the caller from having to copy things it's not interested in.
416          */
417         base_attr = attr_overridden(scsi_sysfs_sdev_attrs, attr);
418         if (base_attr) {
419                 /* extend permissions */
420                 attr->attr.mode |= base_attr->attr.mode;
421
422                 /* override null show/store with default */
423                 if (!attr->show)
424                         attr->show = base_attr->show;
425                 if (!attr->store)
426                         attr->store = base_attr->store;
427         }
428
429         return device_create_file(dev, attr);
430 }
431
432 /**
433  * scsi_sysfs_add_sdev - add scsi device to sysfs
434  * @sdev:       scsi_device to add
435  *
436  * Return value:
437  *      0 on Success / non-zero on Failure
438  **/
439 int scsi_sysfs_add_sdev(struct scsi_device *sdev)
440 {
441         struct class_device_attribute **attrs;
442         int error, i;
443
444         if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0)
445                 return error;
446
447         error = device_add(&sdev->sdev_gendev);
448         if (error) {
449                 printk(KERN_INFO "error 1\n");
450                 return error;
451         }
452
453         error = class_device_add(&sdev->sdev_classdev);
454         if (error) {
455                 printk(KERN_INFO "error 2\n");
456                 goto clean_device;
457         }
458         /* take a reference for the sdev_classdev; this is
459          * released by the sdev_class .release */
460         get_device(&sdev->sdev_gendev);
461
462         if (sdev->transport_classdev.class) {
463                 error = class_device_add(&sdev->transport_classdev);
464                 if (error)
465                         goto clean_device2;
466                 /* take a reference for the transport_classdev; this
467                  * is released by the transport_class .release */
468                 get_device(&sdev->sdev_gendev);
469                 
470         }
471
472         if (sdev->host->hostt->sdev_attrs) {
473                 for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) {
474                         error = attr_add(&sdev->sdev_gendev,
475                                         sdev->host->hostt->sdev_attrs[i]);
476                         if (error) {
477                                 scsi_remove_device(sdev);
478                                 goto out;
479                         }
480                 }
481         }
482         
483         for (i = 0; scsi_sysfs_sdev_attrs[i]; i++) {
484                 if (!attr_overridden(sdev->host->hostt->sdev_attrs,
485                                         scsi_sysfs_sdev_attrs[i])) {
486                         error = device_create_file(&sdev->sdev_gendev,
487                                         scsi_sysfs_sdev_attrs[i]);
488                         if (error) {
489                                 scsi_remove_device(sdev);
490                                 goto out;
491                         }
492                 }
493         }
494
495         if (sdev->transport_classdev.class) {
496                 attrs = sdev->host->transportt->attrs;
497                 for (i = 0; attrs[i]; i++) {
498                         error = class_device_create_file(&sdev->transport_classdev,
499                                                          attrs[i]);
500                         if (error) {
501                                 scsi_remove_device(sdev);
502                                 goto out;
503                         }
504                 }
505         }
506
507  out:
508         return error;
509
510  clean_device2:
511         class_device_del(&sdev->sdev_classdev);
512  clean_device:
513         scsi_device_set_state(sdev, SDEV_CANCEL);
514
515         device_del(&sdev->sdev_gendev);
516         put_device(&sdev->sdev_gendev);
517
518         return error;
519 }
520
521 /**
522  * scsi_remove_device - unregister a device from the scsi bus
523  * @sdev:       scsi_device to unregister
524  **/
525 void scsi_remove_device(struct scsi_device *sdev)
526 {
527         if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
528                 return;
529
530         class_device_unregister(&sdev->sdev_classdev);
531         if (sdev->transport_classdev.class)
532                 class_device_unregister(&sdev->transport_classdev);
533         device_del(&sdev->sdev_gendev);
534         scsi_device_set_state(sdev, SDEV_DEL);
535         if (sdev->host->hostt->slave_destroy)
536                 sdev->host->hostt->slave_destroy(sdev);
537         if (sdev->host->transportt->cleanup)
538                 sdev->host->transportt->cleanup(sdev);
539         put_device(&sdev->sdev_gendev);
540 }
541
542 int scsi_register_driver(struct device_driver *drv)
543 {
544         drv->bus = &scsi_bus_type;
545
546         return driver_register(drv);
547 }
548
549 int scsi_register_interface(struct class_interface *intf)
550 {
551         intf->class = &sdev_class;
552
553         return class_interface_register(intf);
554 }
555
556
557 static struct class_device_attribute *class_attr_overridden(
558                 struct class_device_attribute **attrs,
559                 struct class_device_attribute *attr)
560 {
561         int i;
562
563         if (!attrs)
564                 return NULL;
565         for (i = 0; attrs[i]; i++)
566                 if (!strcmp(attrs[i]->attr.name, attr->attr.name))
567                         return attrs[i];
568         return NULL;
569 }
570
571 static int class_attr_add(struct class_device *classdev,
572                 struct class_device_attribute *attr)
573 {
574         struct class_device_attribute *base_attr;
575
576         /*
577          * Spare the caller from having to copy things it's not interested in.
578          */
579         base_attr = class_attr_overridden(scsi_sysfs_shost_attrs, attr);
580         if (base_attr) {
581                 /* extend permissions */
582                 attr->attr.mode |= base_attr->attr.mode;
583
584                 /* override null show/store with default */
585                 if (!attr->show)
586                         attr->show = base_attr->show;
587                 if (!attr->store)
588                         attr->store = base_attr->store;
589         }
590
591         return class_device_create_file(classdev, attr);
592 }
593
594 /**
595  * scsi_sysfs_add_host - add scsi host to subsystem
596  * @shost:     scsi host struct to add to subsystem
597  * @dev:       parent struct device pointer
598  **/
599 int scsi_sysfs_add_host(struct Scsi_Host *shost)
600 {
601         int error, i;
602
603         if (shost->hostt->shost_attrs) {
604                 for (i = 0; shost->hostt->shost_attrs[i]; i++) {
605                         error = class_attr_add(&shost->shost_classdev,
606                                         shost->hostt->shost_attrs[i]);
607                         if (error)
608                                 return error;
609                 }
610         }
611
612         for (i = 0; scsi_sysfs_shost_attrs[i]; i++) {
613                 if (!class_attr_overridden(shost->hostt->shost_attrs,
614                                         scsi_sysfs_shost_attrs[i])) {
615                         error = class_device_create_file(&shost->shost_classdev,
616                                         scsi_sysfs_shost_attrs[i]);
617                         if (error)
618                                 return error;
619                 }
620         }
621
622         return 0;
623 }
624
625 /* A blank transport template that is used in drivers that don't
626  * yet implement Transport Attributes */
627 struct scsi_transport_template blank_transport_template = { 0, };