upgrade to linux 2.6.10-1.12_FC2
[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.h>
16 #include <scsi/scsi_device.h>
17 #include <scsi/scsi_host.h>
18 #include <scsi/scsi_transport.h>
19
20 #include "scsi_priv.h"
21 #include "scsi_logging.h"
22
23 static struct {
24         enum scsi_device_state  value;
25         char                    *name;
26 } sdev_states[] = {
27         { SDEV_CREATED, "created" },
28         { SDEV_RUNNING, "running" },
29         { SDEV_CANCEL, "cancel" },
30         { SDEV_DEL, "deleted" },
31         { SDEV_QUIESCE, "quiesce" },
32         { SDEV_OFFLINE, "offline" },
33         { SDEV_BLOCK,   "blocked" },
34 };
35
36 const char *scsi_device_state_name(enum scsi_device_state state)
37 {
38         int i;
39         char *name = NULL;
40
41         for (i = 0; i < sizeof(sdev_states)/sizeof(sdev_states[0]); i++) {
42                 if (sdev_states[i].value == state) {
43                         name = sdev_states[i].name;
44                         break;
45                 }
46         }
47         return name;
48 }
49
50 static int check_set(unsigned int *val, char *src)
51 {
52         char *last;
53
54         if (strncmp(src, "-", 20) == 0) {
55                 *val = SCAN_WILD_CARD;
56         } else {
57                 /*
58                  * Doesn't check for int overflow
59                  */
60                 *val = simple_strtoul(src, &last, 0);
61                 if (*last != '\0')
62                         return 1;
63         }
64         return 0;
65 }
66
67 static int scsi_scan(struct Scsi_Host *shost, const char *str)
68 {
69         char s1[15], s2[15], s3[15], junk;
70         unsigned int channel, id, lun;
71         int res;
72
73         res = sscanf(str, "%10s %10s %10s %c", s1, s2, s3, &junk);
74         if (res != 3)
75                 return -EINVAL;
76         if (check_set(&channel, s1))
77                 return -EINVAL;
78         if (check_set(&id, s2))
79                 return -EINVAL;
80         if (check_set(&lun, s3))
81                 return -EINVAL;
82         res = scsi_scan_host_selected(shost, channel, id, lun, 1);
83         return res;
84 }
85
86 /*
87  * shost_show_function: macro to create an attr function that can be used to
88  * show a non-bit field.
89  */
90 #define shost_show_function(name, field, format_string)                 \
91 static ssize_t                                                          \
92 show_##name (struct class_device *class_dev, char *buf)                 \
93 {                                                                       \
94         struct Scsi_Host *shost = class_to_shost(class_dev);            \
95         return snprintf (buf, 20, format_string, shost->field);         \
96 }
97
98 /*
99  * shost_rd_attr: macro to create a function and attribute variable for a
100  * read only field.
101  */
102 #define shost_rd_attr2(name, field, format_string)                      \
103         shost_show_function(name, field, format_string)                 \
104 static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
105
106 #define shost_rd_attr(field, format_string) \
107 shost_rd_attr2(field, field, format_string)
108
109 /*
110  * Create the actual show/store functions and data structures.
111  */
112
113 static ssize_t store_scan(struct class_device *class_dev, const char *buf,
114                           size_t count)
115 {
116         struct Scsi_Host *shost = class_to_shost(class_dev);
117         int res;
118
119         res = scsi_scan(shost, buf);
120         if (res == 0)
121                 res = count;
122         return res;
123 };
124 static CLASS_DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
125
126 shost_rd_attr(unique_id, "%u\n");
127 shost_rd_attr(host_busy, "%hu\n");
128 shost_rd_attr(cmd_per_lun, "%hd\n");
129 shost_rd_attr(sg_tablesize, "%hu\n");
130 shost_rd_attr(unchecked_isa_dma, "%d\n");
131 shost_rd_attr2(proc_name, hostt->proc_name, "%s\n");
132
133 static struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
134         &class_device_attr_unique_id,
135         &class_device_attr_host_busy,
136         &class_device_attr_cmd_per_lun,
137         &class_device_attr_sg_tablesize,
138         &class_device_attr_unchecked_isa_dma,
139         &class_device_attr_proc_name,
140         &class_device_attr_scan,
141         NULL
142 };
143
144 static void scsi_device_cls_release(struct class_device *class_dev)
145 {
146         struct scsi_device *sdev;
147
148         sdev = class_to_sdev(class_dev);
149         put_device(&sdev->sdev_gendev);
150 }
151
152 void scsi_device_dev_release(struct device *dev)
153 {
154         struct scsi_device *sdev;
155         struct device *parent;
156         unsigned long flags;
157         int delete;
158
159         parent = dev->parent;
160         sdev = to_scsi_device(dev);
161
162         spin_lock_irqsave(sdev->host->host_lock, flags);
163         /* If we're the last LUN on the target, destroy the target */
164         delete = list_empty(&sdev->same_target_siblings);
165         list_del(&sdev->siblings);
166         list_del(&sdev->same_target_siblings);
167         list_del(&sdev->starved_entry);
168         spin_unlock_irqrestore(sdev->host->host_lock, flags);
169
170         if (delete) {
171                 struct scsi_target *starget = to_scsi_target(parent);
172                 if (!starget->create) {
173                         device_del(parent);
174                         if (starget->transport_classdev.class)
175                                 class_device_unregister(&starget->transport_classdev);
176                 }
177                 put_device(parent);
178         }
179         if (sdev->request_queue)
180                 scsi_free_queue(sdev->request_queue);
181
182         kfree(sdev->inquiry);
183         kfree(sdev);
184
185         if (parent)
186                 put_device(parent);
187 }
188
189 struct class sdev_class = {
190         .name           = "scsi_device",
191         .release        = scsi_device_cls_release,
192 };
193
194 /* all probing is done in the individual ->probe routines */
195 static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
196 {
197         struct scsi_device *sdp = to_scsi_device(dev);
198         if (sdp->no_uld_attach)
199                 return 0;
200         return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
201 }
202
203 struct bus_type scsi_bus_type = {
204         .name           = "scsi",
205         .match          = scsi_bus_match,
206 };
207
208 int scsi_sysfs_register(void)
209 {
210         int error;
211
212         error = bus_register(&scsi_bus_type);
213         if (!error) {
214                 error = class_register(&sdev_class);
215                 if (error)
216                         bus_unregister(&scsi_bus_type);
217         }
218
219         return error;
220 }
221
222 void scsi_sysfs_unregister(void)
223 {
224         class_unregister(&sdev_class);
225         bus_unregister(&scsi_bus_type);
226 }
227
228 /*
229  * sdev_show_function: macro to create an attr function that can be used to
230  * show a non-bit field.
231  */
232 #define sdev_show_function(field, format_string)                                \
233 static ssize_t                                                          \
234 sdev_show_##field (struct device *dev, char *buf)                               \
235 {                                                                       \
236         struct scsi_device *sdev;                                       \
237         sdev = to_scsi_device(dev);                                     \
238         return snprintf (buf, 20, format_string, sdev->field);          \
239 }                                                                       \
240
241 /*
242  * sdev_rd_attr: macro to create a function and attribute variable for a
243  * read only field.
244  */
245 #define sdev_rd_attr(field, format_string)                              \
246         sdev_show_function(field, format_string)                        \
247 static DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL);
248
249
250 /*
251  * sdev_rd_attr: create a function and attribute variable for a
252  * read/write field.
253  */
254 #define sdev_rw_attr(field, format_string)                              \
255         sdev_show_function(field, format_string)                                \
256                                                                         \
257 static ssize_t                                                          \
258 sdev_store_##field (struct device *dev, const char *buf, size_t count)  \
259 {                                                                       \
260         struct scsi_device *sdev;                                       \
261         sdev = to_scsi_device(dev);                                     \
262         snscanf (buf, 20, format_string, &sdev->field);                 \
263         return count;                                                   \
264 }                                                                       \
265 static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field);
266
267 /* Currently we don't export bit fields, but we might in future,
268  * so leave this code in */
269 #if 0
270 /*
271  * sdev_rd_attr: create a function and attribute variable for a
272  * read/write bit field.
273  */
274 #define sdev_rw_attr_bit(field)                                         \
275         sdev_show_function(field, "%d\n")                                       \
276                                                                         \
277 static ssize_t                                                          \
278 sdev_store_##field (struct device *dev, const char *buf, size_t count)  \
279 {                                                                       \
280         int ret;                                                        \
281         struct scsi_device *sdev;                                       \
282         ret = scsi_sdev_check_buf_bit(buf);                             \
283         if (ret >= 0)   {                                               \
284                 sdev = to_scsi_device(dev);                             \
285                 sdev->field = ret;                                      \
286                 ret = count;                                            \
287         }                                                               \
288         return ret;                                                     \
289 }                                                                       \
290 static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field);
291
292 /*
293  * scsi_sdev_check_buf_bit: return 0 if buf is "0", return 1 if buf is "1",
294  * else return -EINVAL.
295  */
296 static int scsi_sdev_check_buf_bit(const char *buf)
297 {
298         if ((buf[1] == '\0') || ((buf[1] == '\n') && (buf[2] == '\0'))) {
299                 if (buf[0] == '1')
300                         return 1;
301                 else if (buf[0] == '0')
302                         return 0;
303                 else 
304                         return -EINVAL;
305         } else
306                 return -EINVAL;
307 }
308 #endif
309 /*
310  * Create the actual show/store functions and data structures.
311  */
312 sdev_rd_attr (device_blocked, "%d\n");
313 sdev_rd_attr (queue_depth, "%d\n");
314 sdev_rd_attr (type, "%d\n");
315 sdev_rd_attr (scsi_level, "%d\n");
316 sdev_rd_attr (vendor, "%.8s\n");
317 sdev_rd_attr (model, "%.16s\n");
318 sdev_rd_attr (rev, "%.4s\n");
319
320 static ssize_t
321 sdev_show_timeout (struct device *dev, char *buf)
322 {
323         struct scsi_device *sdev;
324         sdev = to_scsi_device(dev);
325         return snprintf (buf, 20, "%d\n", sdev->timeout / HZ);
326 }
327
328 static ssize_t
329 sdev_store_timeout (struct device *dev, const char *buf, size_t count)
330 {
331         struct scsi_device *sdev;
332         int timeout;
333         sdev = to_scsi_device(dev);
334         sscanf (buf, "%d\n", &timeout);
335         sdev->timeout = timeout * HZ;
336         return count;
337 }
338 static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout);
339
340 static ssize_t
341 store_rescan_field (struct device *dev, const char *buf, size_t count) 
342 {
343         scsi_rescan_device(dev);
344         return count;
345 }
346 static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);
347
348 static ssize_t sdev_store_delete(struct device *dev, const char *buf,
349                                  size_t count)
350 {
351         scsi_remove_device(to_scsi_device(dev));
352         return count;
353 };
354 static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
355
356 static ssize_t
357 store_state_field(struct device *dev, const char *buf, size_t count)
358 {
359         int i;
360         struct scsi_device *sdev = to_scsi_device(dev);
361         enum scsi_device_state state = 0;
362
363         for (i = 0; i < sizeof(sdev_states)/sizeof(sdev_states[0]); i++) {
364                 const int len = strlen(sdev_states[i].name);
365                 if (strncmp(sdev_states[i].name, buf, len) == 0 &&
366                    buf[len] == '\n') {
367                         state = sdev_states[i].value;
368                         break;
369                 }
370         }
371         if (!state)
372                 return -EINVAL;
373
374         if (scsi_device_set_state(sdev, state))
375                 return -EINVAL;
376         return count;
377 }
378
379 static ssize_t
380 show_state_field(struct device *dev, char *buf)
381 {
382         struct scsi_device *sdev = to_scsi_device(dev);
383         const char *name = scsi_device_state_name(sdev->sdev_state);
384
385         if (!name)
386                 return -EINVAL;
387
388         return snprintf(buf, 20, "%s\n", name);
389 }
390
391 DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_state_field, store_state_field);
392
393
394 /* Default template for device attributes.  May NOT be modified */
395 static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
396         &dev_attr_device_blocked,
397         &dev_attr_queue_depth,
398         &dev_attr_type,
399         &dev_attr_scsi_level,
400         &dev_attr_vendor,
401         &dev_attr_model,
402         &dev_attr_rev,
403         &dev_attr_rescan,
404         &dev_attr_delete,
405         &dev_attr_state,
406         &dev_attr_timeout,
407         NULL
408 };
409
410
411 static struct device_attribute *attr_overridden(
412                 struct device_attribute **attrs,
413                 struct device_attribute *attr)
414 {
415         int i;
416
417         if (!attrs)
418                 return NULL;
419         for (i = 0; attrs[i]; i++)
420                 if (!strcmp(attrs[i]->attr.name, attr->attr.name))
421                         return attrs[i];
422         return NULL;
423 }
424
425 static int attr_add(struct device *dev, struct device_attribute *attr)
426 {
427         struct device_attribute *base_attr;
428
429         /*
430          * Spare the caller from having to copy things it's not interested in.
431          */
432         base_attr = attr_overridden(scsi_sysfs_sdev_attrs, attr);
433         if (base_attr) {
434                 /* extend permissions */
435                 attr->attr.mode |= base_attr->attr.mode;
436
437                 /* override null show/store with default */
438                 if (!attr->show)
439                         attr->show = base_attr->show;
440                 if (!attr->store)
441                         attr->store = base_attr->store;
442         }
443
444         return device_create_file(dev, attr);
445 }
446
447 static void scsi_target_dev_release(struct device *dev)
448 {
449         struct scsi_target *starget = to_scsi_target(dev);
450         struct device *parent = dev->parent;
451         kfree(starget);
452         put_device(parent);
453 }
454
455 /**
456  * scsi_sysfs_add_sdev - add scsi device to sysfs
457  * @sdev:       scsi_device to add
458  *
459  * Return value:
460  *      0 on Success / non-zero on Failure
461  **/
462 int scsi_sysfs_add_sdev(struct scsi_device *sdev)
463 {
464         struct class_device_attribute **attrs;
465         struct scsi_target *starget = sdev->sdev_target;
466         struct Scsi_Host *shost = sdev->host;
467         int error, i, create;
468         unsigned long flags;
469
470         spin_lock_irqsave(shost->host_lock, flags);
471         create = starget->create;
472         starget->create = 0;
473         spin_unlock_irqrestore(shost->host_lock, flags);
474
475         if (create) {
476                 error = device_add(&starget->dev);
477                 if (error) {
478                         printk(KERN_ERR "Target device_add failed\n");
479                         return error;
480                 }
481                 if (starget->transport_classdev.class) {
482                         int i;
483                         struct class_device_attribute **attrs =
484                                 sdev->host->transportt->target_attrs;
485
486                         error = class_device_add(&starget->transport_classdev);
487                         if (error) {
488                                 dev_printk(KERN_ERR, &starget->dev,
489                                            "Target transport add failed\n");
490                                 return error;
491                         }
492
493                         /* take a reference for the transport_classdev; this
494                          * is released by the transport_class .release */
495                         get_device(&starget->dev);
496                         for (i = 0; attrs[i]; i++) {
497                                 error = class_device_create_file(&starget->transport_classdev,
498                                                                  attrs[i]);
499                                 if (error) {
500                                         dev_printk(KERN_ERR, &starget->dev,
501                                                    "Target transport attr add failed\n");
502                                         return error;
503                                 }
504                         }
505                 }
506         }
507
508         if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0)
509                 return error;
510
511         error = device_add(&sdev->sdev_gendev);
512         if (error) {
513                 put_device(sdev->sdev_gendev.parent);
514                 printk(KERN_INFO "error 1\n");
515                 return error;
516         }
517
518         error = class_device_add(&sdev->sdev_classdev);
519         if (error) {
520                 printk(KERN_INFO "error 2\n");
521                 goto clean_device;
522         }
523         /* take a reference for the sdev_classdev; this is
524          * released by the sdev_class .release */
525         get_device(&sdev->sdev_gendev);
526         if (sdev->transport_classdev.class) {
527                 error = class_device_add(&sdev->transport_classdev);
528                 if (error)
529                         goto clean_device2;
530                 /* take a reference for the transport_classdev; this
531                  * is released by the transport_class .release */
532                 get_device(&sdev->sdev_gendev);
533                 
534         }
535
536         if (sdev->host->hostt->sdev_attrs) {
537                 for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) {
538                         error = attr_add(&sdev->sdev_gendev,
539                                         sdev->host->hostt->sdev_attrs[i]);
540                         if (error) {
541                                 scsi_remove_device(sdev);
542                                 goto out;
543                         }
544                 }
545         }
546         
547         for (i = 0; scsi_sysfs_sdev_attrs[i]; i++) {
548                 if (!attr_overridden(sdev->host->hostt->sdev_attrs,
549                                         scsi_sysfs_sdev_attrs[i])) {
550                         error = device_create_file(&sdev->sdev_gendev,
551                                         scsi_sysfs_sdev_attrs[i]);
552                         if (error) {
553                                 scsi_remove_device(sdev);
554                                 goto out;
555                         }
556                 }
557         }
558
559         if (sdev->transport_classdev.class) {
560                 attrs = sdev->host->transportt->device_attrs;
561                 for (i = 0; attrs[i]; i++) {
562                         error = class_device_create_file(&sdev->transport_classdev,
563                                                          attrs[i]);
564                         if (error) {
565                                 scsi_remove_device(sdev);
566                                 goto out;
567                         }
568                 }
569         }
570
571  out:
572         return error;
573
574  clean_device2:
575         class_device_del(&sdev->sdev_classdev);
576  clean_device:
577         scsi_device_set_state(sdev, SDEV_CANCEL);
578
579         device_del(&sdev->sdev_gendev);
580         put_device(&sdev->sdev_gendev);
581
582         return error;
583 }
584
585 /**
586  * scsi_remove_device - unregister a device from the scsi bus
587  * @sdev:       scsi_device to unregister
588  **/
589 void scsi_remove_device(struct scsi_device *sdev)
590 {
591         struct Scsi_Host *shost = sdev->host;
592
593         down(&shost->scan_mutex);
594         if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
595                 goto out;
596
597         class_device_unregister(&sdev->sdev_classdev);
598         if (sdev->transport_classdev.class)
599                 class_device_unregister(&sdev->transport_classdev);
600         device_del(&sdev->sdev_gendev);
601         scsi_device_set_state(sdev, SDEV_DEL);
602         if (sdev->host->hostt->slave_destroy)
603                 sdev->host->hostt->slave_destroy(sdev);
604         put_device(&sdev->sdev_gendev);
605
606 out:
607         up(&shost->scan_mutex);
608 }
609
610 int scsi_register_driver(struct device_driver *drv)
611 {
612         drv->bus = &scsi_bus_type;
613
614         return driver_register(drv);
615 }
616
617 int scsi_register_interface(struct class_interface *intf)
618 {
619         intf->class = &sdev_class;
620
621         return class_interface_register(intf);
622 }
623
624
625 static struct class_device_attribute *class_attr_overridden(
626                 struct class_device_attribute **attrs,
627                 struct class_device_attribute *attr)
628 {
629         int i;
630
631         if (!attrs)
632                 return NULL;
633         for (i = 0; attrs[i]; i++)
634                 if (!strcmp(attrs[i]->attr.name, attr->attr.name))
635                         return attrs[i];
636         return NULL;
637 }
638
639 static int class_attr_add(struct class_device *classdev,
640                 struct class_device_attribute *attr)
641 {
642         struct class_device_attribute *base_attr;
643
644         /*
645          * Spare the caller from having to copy things it's not interested in.
646          */
647         base_attr = class_attr_overridden(scsi_sysfs_shost_attrs, attr);
648         if (base_attr) {
649                 /* extend permissions */
650                 attr->attr.mode |= base_attr->attr.mode;
651
652                 /* override null show/store with default */
653                 if (!attr->show)
654                         attr->show = base_attr->show;
655                 if (!attr->store)
656                         attr->store = base_attr->store;
657         }
658
659         return class_device_create_file(classdev, attr);
660 }
661
662 /**
663  * scsi_sysfs_add_host - add scsi host to subsystem
664  * @shost:     scsi host struct to add to subsystem
665  * @dev:       parent struct device pointer
666  **/
667 int scsi_sysfs_add_host(struct Scsi_Host *shost)
668 {
669         int error, i;
670
671         if (shost->hostt->shost_attrs) {
672                 for (i = 0; shost->hostt->shost_attrs[i]; i++) {
673                         error = class_attr_add(&shost->shost_classdev,
674                                         shost->hostt->shost_attrs[i]);
675                         if (error)
676                                 return error;
677                 }
678         }
679
680         for (i = 0; scsi_sysfs_shost_attrs[i]; i++) {
681                 if (!class_attr_overridden(shost->hostt->shost_attrs,
682                                         scsi_sysfs_shost_attrs[i])) {
683                         error = class_device_create_file(&shost->shost_classdev,
684                                         scsi_sysfs_shost_attrs[i]);
685                         if (error)
686                                 return error;
687                 }
688         }
689
690         class_device_initialize(&shost->transport_classdev);
691         shost->transport_classdev.class = shost->transportt->host_class;
692         shost->transport_classdev.dev = &shost->shost_gendev;
693         snprintf(shost->transport_classdev.class_id, BUS_ID_SIZE,
694                  "host%d", shost->host_no);
695
696         if (shost->transport_classdev.class) {
697                 struct class_device_attribute **attrs =
698                         shost->transportt->host_attrs;
699                 error = class_device_add(&shost->transport_classdev);
700                 if (error)
701                         return error;
702                 /* take a reference for the transport_classdev; this
703                  * is released by the transport_class .release */
704                 get_device(&shost->shost_gendev);
705                 for (i = 0; attrs[i]; i++) {
706                         error = class_device_create_file(&shost->transport_classdev,
707                                                          attrs[i]);
708                         if (error)
709                                 return error;
710                 }
711         }
712
713         return 0;
714 }
715
716 int scsi_sysfs_device_initialize(struct scsi_device *sdev)
717 {
718         device_initialize(&sdev->sdev_gendev);
719         sdev->sdev_gendev.bus = &scsi_bus_type;
720         sdev->sdev_gendev.release = scsi_device_dev_release;
721         sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d",
722                 sdev->host->host_no, sdev->channel, sdev->id,
723                 sdev->lun);
724         
725         class_device_initialize(&sdev->sdev_classdev);
726         sdev->sdev_classdev.dev = &sdev->sdev_gendev;
727         sdev->sdev_classdev.class = &sdev_class;
728         snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE,
729                  "%d:%d:%d:%d", sdev->host->host_no,
730                  sdev->channel, sdev->id, sdev->lun);
731
732         class_device_initialize(&sdev->transport_classdev);
733         sdev->transport_classdev.dev = &sdev->sdev_gendev;
734         sdev->transport_classdev.class = sdev->host->transportt->device_class;
735         snprintf(sdev->transport_classdev.class_id, BUS_ID_SIZE,
736                  "%d:%d:%d:%d", sdev->host->host_no,
737                  sdev->channel, sdev->id, sdev->lun);
738         return 0;
739 }
740
741 int scsi_sysfs_target_initialize(struct scsi_device *sdev)
742 {
743         struct scsi_target *starget = NULL;
744         struct Scsi_Host *shost = sdev->host;
745         struct scsi_device *device;
746         struct device *dev = NULL;
747         unsigned long flags;
748         int create = 0;
749
750         spin_lock_irqsave(shost->host_lock, flags);
751         /*
752          * Search for an existing target for this sdev.
753          */
754         list_for_each_entry(device, &shost->__devices, siblings) {
755                 if (device->id == sdev->id &&
756                     device->channel == sdev->channel) {
757                         list_add_tail(&sdev->same_target_siblings,
758                                       &device->same_target_siblings);
759                         sdev->scsi_level = device->scsi_level;
760                         starget = device->sdev_target;
761                         break;
762                 }
763         }
764                         
765         if (!starget) {
766                 const int size = sizeof(*starget) +
767                         shost->transportt->target_size;
768                 starget = kmalloc(size, GFP_ATOMIC);
769                 if (!starget) {
770                         printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
771                         spin_unlock_irqrestore(shost->host_lock,
772                                                flags);
773                         return -ENOMEM;
774                 }
775                 memset(starget, 0, size);
776                 dev = &starget->dev;
777                 device_initialize(dev);
778                 dev->parent = get_device(&shost->shost_gendev);
779                 dev->release = scsi_target_dev_release;
780                 sprintf(dev->bus_id, "target%d:%d:%d",
781                         shost->host_no, sdev->channel, sdev->id);
782                 class_device_initialize(&starget->transport_classdev);
783                 starget->transport_classdev.dev = &starget->dev;
784                 starget->transport_classdev.class = shost->transportt->target_class;
785                 snprintf(starget->transport_classdev.class_id, BUS_ID_SIZE,
786                          "target%d:%d:%d",
787                          shost->host_no, sdev->channel, sdev->id);
788                 starget->id = sdev->id;
789                 starget->channel = sdev->channel;
790                 create = starget->create = 1;
791                 /*
792                  * If there wasn't another lun already configured at
793                  * this target, then default this device to SCSI_2
794                  * until we know better
795                  */
796                 sdev->scsi_level = SCSI_2;
797         }
798         get_device(&starget->dev);
799         sdev->sdev_gendev.parent = &starget->dev;
800         sdev->sdev_target = starget;
801         list_add_tail(&sdev->siblings, &shost->__devices);
802         spin_unlock_irqrestore(shost->host_lock, flags);
803         if (create && shost->transportt->target_setup)
804                 shost->transportt->target_setup(starget);
805         return 0;
806 }
807
808 /* A blank transport template that is used in drivers that don't
809  * yet implement Transport Attributes */
810 struct scsi_transport_template blank_transport_template = { NULL, };