ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[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         return 1;
185 }
186
187 struct bus_type scsi_bus_type = {
188         .name           = "scsi",
189         .match          = scsi_bus_match,
190 };
191
192 int scsi_sysfs_register(void)
193 {
194         int error;
195
196         error = bus_register(&scsi_bus_type);
197         if (!error) {
198                 error = class_register(&sdev_class);
199                 if (error)
200                         bus_unregister(&scsi_bus_type);
201         }
202
203         return error;
204 }
205
206 void scsi_sysfs_unregister(void)
207 {
208         class_unregister(&sdev_class);
209         bus_unregister(&scsi_bus_type);
210 }
211
212 /*
213  * sdev_show_function: macro to create an attr function that can be used to
214  * show a non-bit field.
215  */
216 #define sdev_show_function(field, format_string)                                \
217 static ssize_t                                                          \
218 sdev_show_##field (struct device *dev, char *buf)                               \
219 {                                                                       \
220         struct scsi_device *sdev;                                       \
221         sdev = to_scsi_device(dev);                                     \
222         return snprintf (buf, 20, format_string, sdev->field);          \
223 }                                                                       \
224
225 /*
226  * sdev_rd_attr: macro to create a function and attribute variable for a
227  * read only field.
228  */
229 #define sdev_rd_attr(field, format_string)                              \
230         sdev_show_function(field, format_string)                                \
231 static DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL)
232
233
234 /*
235  * sdev_rd_attr: create a function and attribute variable for a
236  * read/write field.
237  */
238 #define sdev_rw_attr(field, format_string)                              \
239         sdev_show_function(field, format_string)                                \
240                                                                         \
241 static ssize_t                                                          \
242 sdev_store_##field (struct device *dev, const char *buf, size_t count)  \
243 {                                                                       \
244         struct scsi_device *sdev;                                       \
245         sdev = to_scsi_device(dev);                                     \
246         snscanf (buf, 20, format_string, &sdev->field);                 \
247         return count;                                                   \
248 }                                                                       \
249 static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field)
250
251 /* Currently we don't export bit fields, but we might in future,
252  * so leave this code in */
253 #if 0
254 /*
255  * sdev_rd_attr: create a function and attribute variable for a
256  * read/write bit field.
257  */
258 #define sdev_rw_attr_bit(field)                                         \
259         sdev_show_function(field, "%d\n")                                       \
260                                                                         \
261 static ssize_t                                                          \
262 sdev_store_##field (struct device *dev, const char *buf, size_t count)  \
263 {                                                                       \
264         int ret;                                                        \
265         struct scsi_device *sdev;                                       \
266         ret = scsi_sdev_check_buf_bit(buf);                             \
267         if (ret >= 0)   {                                               \
268                 sdev = to_scsi_device(dev);                             \
269                 sdev->field = ret;                                      \
270                 ret = count;                                            \
271         }                                                               \
272         return ret;                                                     \
273 }                                                                       \
274 static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field)
275
276 /*
277  * scsi_sdev_check_buf_bit: return 0 if buf is "0", return 1 if buf is "1",
278  * else return -EINVAL.
279  */
280 static int scsi_sdev_check_buf_bit(const char *buf)
281 {
282         if ((buf[1] == '\0') || ((buf[1] == '\n') && (buf[2] == '\0'))) {
283                 if (buf[0] == '1')
284                         return 1;
285                 else if (buf[0] == '0')
286                         return 0;
287                 else 
288                         return -EINVAL;
289         } else
290                 return -EINVAL;
291 }
292 #endif
293 /*
294  * Create the actual show/store functions and data structures.
295  */
296 sdev_rd_attr (device_blocked, "%d\n");
297 sdev_rd_attr (queue_depth, "%d\n");
298 sdev_rd_attr (type, "%d\n");
299 sdev_rd_attr (scsi_level, "%d\n");
300 sdev_rd_attr (vendor, "%.8s\n");
301 sdev_rd_attr (model, "%.16s\n");
302 sdev_rd_attr (rev, "%.4s\n");
303
304 static ssize_t
305 store_rescan_field (struct device *dev, const char *buf, size_t count) 
306 {
307         scsi_rescan_device(dev);
308         return count;
309 }
310 static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field)
311
312 static ssize_t sdev_store_delete(struct device *dev, const char *buf,
313                                  size_t count)
314 {
315         scsi_remove_device(to_scsi_device(dev));
316         return count;
317 };
318 static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
319
320 static ssize_t
321 store_state_field(struct device *dev, const char *buf, size_t count)
322 {
323         int i;
324         struct scsi_device *sdev = to_scsi_device(dev);
325         enum scsi_device_state state = 0;
326
327         for (i = 0; i < sizeof(sdev_states)/sizeof(sdev_states[0]); i++) {
328                 const int len = strlen(sdev_states[i].name);
329                 if (strncmp(sdev_states[i].name, buf, len) == 0 &&
330                    buf[len] == '\n') {
331                         state = sdev_states[i].value;
332                         break;
333                 }
334         }
335         if (!state)
336                 return -EINVAL;
337
338         if (scsi_device_set_state(sdev, state))
339                 return -EINVAL;
340         return count;
341 }
342
343 static ssize_t
344 show_state_field(struct device *dev, char *buf)
345 {
346         struct scsi_device *sdev = to_scsi_device(dev);
347         const char *name = scsi_device_state_name(sdev->sdev_state);
348
349         if (!name)
350                 return -EINVAL;
351
352         return snprintf(buf, 20, "%s\n", name);
353 }
354
355 DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_state_field, store_state_field);
356
357
358 /* Default template for device attributes.  May NOT be modified */
359 static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
360         &dev_attr_device_blocked,
361         &dev_attr_queue_depth,
362         &dev_attr_type,
363         &dev_attr_scsi_level,
364         &dev_attr_vendor,
365         &dev_attr_model,
366         &dev_attr_rev,
367         &dev_attr_rescan,
368         &dev_attr_delete,
369         &dev_attr_state,
370         NULL
371 };
372
373
374 static struct device_attribute *attr_overridden(
375                 struct device_attribute **attrs,
376                 struct device_attribute *attr)
377 {
378         int i;
379
380         if (!attrs)
381                 return NULL;
382         for (i = 0; attrs[i]; i++)
383                 if (!strcmp(attrs[i]->attr.name, attr->attr.name))
384                         return attrs[i];
385         return NULL;
386 }
387
388 static int attr_add(struct device *dev, struct device_attribute *attr)
389 {
390         struct device_attribute *base_attr;
391
392         /*
393          * Spare the caller from having to copy things it's not interested in.
394          */
395         base_attr = attr_overridden(scsi_sysfs_sdev_attrs, attr);
396         if (base_attr) {
397                 /* extend permissions */
398                 attr->attr.mode |= base_attr->attr.mode;
399
400                 /* override null show/store with default */
401                 if (!attr->show)
402                         attr->show = base_attr->show;
403                 if (!attr->store)
404                         attr->store = base_attr->store;
405         }
406
407         return device_create_file(dev, attr);
408 }
409
410 /**
411  * scsi_sysfs_add_sdev - add scsi device to sysfs
412  * @sdev:       scsi_device to add
413  *
414  * Return value:
415  *      0 on Success / non-zero on Failure
416  **/
417 int scsi_sysfs_add_sdev(struct scsi_device *sdev)
418 {
419         struct class_device_attribute **attrs;
420         int error, i;
421
422         if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0)
423                 return error;
424
425         error = device_add(&sdev->sdev_gendev);
426         if (error) {
427                 printk(KERN_INFO "error 1\n");
428                 return error;
429         }
430
431         error = class_device_add(&sdev->sdev_classdev);
432         if (error) {
433                 printk(KERN_INFO "error 2\n");
434                 goto clean_device;
435         }
436         /* take a reference for the sdev_classdev; this is
437          * released by the sdev_class .release */
438         get_device(&sdev->sdev_gendev);
439
440         if (sdev->transport_classdev.class) {
441                 error = class_device_add(&sdev->transport_classdev);
442                 if (error)
443                         goto clean_device2;
444                 /* take a reference for the transport_classdev; this
445                  * is released by the transport_class .release */
446                 get_device(&sdev->sdev_gendev);
447                 
448         }
449
450         if (sdev->host->hostt->sdev_attrs) {
451                 for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) {
452                         error = attr_add(&sdev->sdev_gendev,
453                                         sdev->host->hostt->sdev_attrs[i]);
454                         if (error) {
455                                 scsi_remove_device(sdev);
456                                 goto out;
457                         }
458                 }
459         }
460         
461         for (i = 0; scsi_sysfs_sdev_attrs[i]; i++) {
462                 if (!attr_overridden(sdev->host->hostt->sdev_attrs,
463                                         scsi_sysfs_sdev_attrs[i])) {
464                         error = device_create_file(&sdev->sdev_gendev,
465                                         scsi_sysfs_sdev_attrs[i]);
466                         if (error) {
467                                 scsi_remove_device(sdev);
468                                 goto out;
469                         }
470                 }
471         }
472
473         if (sdev->transport_classdev.class) {
474                 attrs = sdev->host->transportt->attrs;
475                 for (i = 0; attrs[i]; i++) {
476                         error = class_device_create_file(&sdev->transport_classdev,
477                                                          attrs[i]);
478                         if (error) {
479                                 scsi_remove_device(sdev);
480                                 goto out;
481                         }
482                 }
483         }
484
485  out:
486         return error;
487
488  clean_device2:
489         class_device_del(&sdev->sdev_classdev);
490  clean_device:
491         scsi_device_set_state(sdev, SDEV_CANCEL);
492
493         device_del(&sdev->sdev_gendev);
494         put_device(&sdev->sdev_gendev);
495
496         return error;
497 }
498
499 /**
500  * scsi_remove_device - unregister a device from the scsi bus
501  * @sdev:       scsi_device to unregister
502  **/
503 void scsi_remove_device(struct scsi_device *sdev)
504 {
505         if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
506                 return;
507
508         class_device_unregister(&sdev->sdev_classdev);
509         if (sdev->transport_classdev.class)
510                 class_device_unregister(&sdev->transport_classdev);
511         device_del(&sdev->sdev_gendev);
512         scsi_device_set_state(sdev, SDEV_DEL);
513         if (sdev->host->hostt->slave_destroy)
514                 sdev->host->hostt->slave_destroy(sdev);
515         if (sdev->host->transportt->cleanup)
516                 sdev->host->transportt->cleanup(sdev);
517         put_device(&sdev->sdev_gendev);
518 }
519
520 int scsi_register_driver(struct device_driver *drv)
521 {
522         drv->bus = &scsi_bus_type;
523
524         return driver_register(drv);
525 }
526
527 int scsi_register_interface(struct class_interface *intf)
528 {
529         intf->class = &sdev_class;
530
531         return class_interface_register(intf);
532 }
533
534
535 static struct class_device_attribute *class_attr_overridden(
536                 struct class_device_attribute **attrs,
537                 struct class_device_attribute *attr)
538 {
539         int i;
540
541         if (!attrs)
542                 return NULL;
543         for (i = 0; attrs[i]; i++)
544                 if (!strcmp(attrs[i]->attr.name, attr->attr.name))
545                         return attrs[i];
546         return NULL;
547 }
548
549 static int class_attr_add(struct class_device *classdev,
550                 struct class_device_attribute *attr)
551 {
552         struct class_device_attribute *base_attr;
553
554         /*
555          * Spare the caller from having to copy things it's not interested in.
556          */
557         base_attr = class_attr_overridden(scsi_sysfs_shost_attrs, attr);
558         if (base_attr) {
559                 /* extend permissions */
560                 attr->attr.mode |= base_attr->attr.mode;
561
562                 /* override null show/store with default */
563                 if (!attr->show)
564                         attr->show = base_attr->show;
565                 if (!attr->store)
566                         attr->store = base_attr->store;
567         }
568
569         return class_device_create_file(classdev, attr);
570 }
571
572 /**
573  * scsi_sysfs_add_host - add scsi host to subsystem
574  * @shost:     scsi host struct to add to subsystem
575  * @dev:       parent struct device pointer
576  **/
577 int scsi_sysfs_add_host(struct Scsi_Host *shost)
578 {
579         int error, i;
580
581         if (shost->hostt->shost_attrs) {
582                 for (i = 0; shost->hostt->shost_attrs[i]; i++) {
583                         error = class_attr_add(&shost->shost_classdev,
584                                         shost->hostt->shost_attrs[i]);
585                         if (error)
586                                 return error;
587                 }
588         }
589
590         for (i = 0; scsi_sysfs_shost_attrs[i]; i++) {
591                 if (!class_attr_overridden(shost->hostt->shost_attrs,
592                                         scsi_sysfs_shost_attrs[i])) {
593                         error = class_device_create_file(&shost->shost_classdev,
594                                         scsi_sysfs_shost_attrs[i]);
595                         if (error)
596                                 return error;
597                 }
598         }
599
600         return 0;
601 }
602
603 /* A blank transport template that is used in drivers that don't
604  * yet implement Transport Attributes */
605 struct scsi_transport_template blank_transport_template = { 0, };