aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_sysfs.c')
-rw-r--r--drivers/scsi/scsi_sysfs.c142
1 files changed, 75 insertions, 67 deletions
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 67bb20ed45d2..049103f1d16f 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -21,6 +21,8 @@
21#include "scsi_priv.h" 21#include "scsi_priv.h"
22#include "scsi_logging.h" 22#include "scsi_logging.h"
23 23
24static struct device_type scsi_dev_type;
25
24static const struct { 26static const struct {
25 enum scsi_device_state value; 27 enum scsi_device_state value;
26 char *name; 28 char *name;
@@ -249,18 +251,27 @@ shost_rd_attr(sg_tablesize, "%hu\n");
249shost_rd_attr(unchecked_isa_dma, "%d\n"); 251shost_rd_attr(unchecked_isa_dma, "%d\n");
250shost_rd_attr2(proc_name, hostt->proc_name, "%s\n"); 252shost_rd_attr2(proc_name, hostt->proc_name, "%s\n");
251 253
252static struct device_attribute *scsi_sysfs_shost_attrs[] = { 254static struct attribute *scsi_sysfs_shost_attrs[] = {
253 &dev_attr_unique_id, 255 &dev_attr_unique_id.attr,
254 &dev_attr_host_busy, 256 &dev_attr_host_busy.attr,
255 &dev_attr_cmd_per_lun, 257 &dev_attr_cmd_per_lun.attr,
256 &dev_attr_can_queue, 258 &dev_attr_can_queue.attr,
257 &dev_attr_sg_tablesize, 259 &dev_attr_sg_tablesize.attr,
258 &dev_attr_unchecked_isa_dma, 260 &dev_attr_unchecked_isa_dma.attr,
259 &dev_attr_proc_name, 261 &dev_attr_proc_name.attr,
260 &dev_attr_scan, 262 &dev_attr_scan.attr,
261 &dev_attr_hstate, 263 &dev_attr_hstate.attr,
262 &dev_attr_supported_mode, 264 &dev_attr_supported_mode.attr,
263 &dev_attr_active_mode, 265 &dev_attr_active_mode.attr,
266 NULL
267};
268
269struct attribute_group scsi_shost_attr_group = {
270 .attrs = scsi_sysfs_shost_attrs,
271};
272
273struct attribute_group *scsi_sysfs_shost_attr_groups[] = {
274 &scsi_shost_attr_group,
264 NULL 275 NULL
265}; 276};
266 277
@@ -335,7 +346,12 @@ static struct class sdev_class = {
335/* all probing is done in the individual ->probe routines */ 346/* all probing is done in the individual ->probe routines */
336static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) 347static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
337{ 348{
338 struct scsi_device *sdp = to_scsi_device(dev); 349 struct scsi_device *sdp;
350
351 if (dev->type != &scsi_dev_type)
352 return 0;
353
354 sdp = to_scsi_device(dev);
339 if (sdp->no_uld_attach) 355 if (sdp->no_uld_attach)
340 return 0; 356 return 0;
341 return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; 357 return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
@@ -351,10 +367,16 @@ static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
351 367
352static int scsi_bus_suspend(struct device * dev, pm_message_t state) 368static int scsi_bus_suspend(struct device * dev, pm_message_t state)
353{ 369{
354 struct device_driver *drv = dev->driver; 370 struct device_driver *drv;
355 struct scsi_device *sdev = to_scsi_device(dev); 371 struct scsi_device *sdev;
356 int err; 372 int err;
357 373
374 if (dev->type != &scsi_dev_type)
375 return 0;
376
377 drv = dev->driver;
378 sdev = to_scsi_device(dev);
379
358 err = scsi_device_quiesce(sdev); 380 err = scsi_device_quiesce(sdev);
359 if (err) 381 if (err)
360 return err; 382 return err;
@@ -370,10 +392,16 @@ static int scsi_bus_suspend(struct device * dev, pm_message_t state)
370 392
371static int scsi_bus_resume(struct device * dev) 393static int scsi_bus_resume(struct device * dev)
372{ 394{
373 struct device_driver *drv = dev->driver; 395 struct device_driver *drv;
374 struct scsi_device *sdev = to_scsi_device(dev); 396 struct scsi_device *sdev;
375 int err = 0; 397 int err = 0;
376 398
399 if (dev->type != &scsi_dev_type)
400 return 0;
401
402 drv = dev->driver;
403 sdev = to_scsi_device(dev);
404
377 if (drv && drv->resume) 405 if (drv && drv->resume)
378 err = drv->resume(dev); 406 err = drv->resume(dev);
379 407
@@ -781,6 +809,27 @@ sdev_store_queue_type_rw(struct device *dev, struct device_attribute *attr,
781 return count; 809 return count;
782} 810}
783 811
812static int scsi_target_add(struct scsi_target *starget)
813{
814 int error;
815
816 if (starget->state != STARGET_CREATED)
817 return 0;
818
819 error = device_add(&starget->dev);
820 if (error) {
821 dev_err(&starget->dev, "target device_add failed, error %d\n", error);
822 get_device(&starget->dev);
823 scsi_target_reap(starget);
824 put_device(&starget->dev);
825 return error;
826 }
827 transport_add_device(&starget->dev);
828 starget->state = STARGET_RUNNING;
829
830 return 0;
831}
832
784static struct device_attribute sdev_attr_queue_type_rw = 833static struct device_attribute sdev_attr_queue_type_rw =
785 __ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field, 834 __ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field,
786 sdev_store_queue_type_rw); 835 sdev_store_queue_type_rw);
@@ -796,10 +845,16 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
796{ 845{
797 int error, i; 846 int error, i;
798 struct request_queue *rq = sdev->request_queue; 847 struct request_queue *rq = sdev->request_queue;
848 struct scsi_target *starget = sdev->sdev_target;
799 849
800 if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0) 850 if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0)
801 return error; 851 return error;
802 852
853 error = scsi_target_add(starget);
854 if (error)
855 return error;
856
857 transport_configure_device(&starget->dev);
803 error = device_add(&sdev->sdev_gendev); 858 error = device_add(&sdev->sdev_gendev);
804 if (error) { 859 if (error) {
805 put_device(sdev->sdev_gendev.parent); 860 put_device(sdev->sdev_gendev.parent);
@@ -834,7 +889,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
834 goto out; 889 goto out;
835 } 890 }
836 891
837 error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL); 892 error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL, NULL);
838 893
839 if (error) 894 if (error)
840 sdev_printk(KERN_INFO, sdev, 895 sdev_printk(KERN_INFO, sdev,
@@ -971,44 +1026,6 @@ int scsi_register_interface(struct class_interface *intf)
971} 1026}
972EXPORT_SYMBOL(scsi_register_interface); 1027EXPORT_SYMBOL(scsi_register_interface);
973 1028
974
975static struct device_attribute *class_attr_overridden(
976 struct device_attribute **attrs,
977 struct device_attribute *attr)
978{
979 int i;
980
981 if (!attrs)
982 return NULL;
983 for (i = 0; attrs[i]; i++)
984 if (!strcmp(attrs[i]->attr.name, attr->attr.name))
985 return attrs[i];
986 return NULL;
987}
988
989static int class_attr_add(struct device *classdev,
990 struct device_attribute *attr)
991{
992 struct device_attribute *base_attr;
993
994 /*
995 * Spare the caller from having to copy things it's not interested in.
996 */
997 base_attr = class_attr_overridden(scsi_sysfs_shost_attrs, attr);
998 if (base_attr) {
999 /* extend permissions */
1000 attr->attr.mode |= base_attr->attr.mode;
1001
1002 /* override null show/store with default */
1003 if (!attr->show)
1004 attr->show = base_attr->show;
1005 if (!attr->store)
1006 attr->store = base_attr->store;
1007 }
1008
1009 return device_create_file(classdev, attr);
1010}
1011
1012/** 1029/**
1013 * scsi_sysfs_add_host - add scsi host to subsystem 1030 * scsi_sysfs_add_host - add scsi host to subsystem
1014 * @shost: scsi host struct to add to subsystem 1031 * @shost: scsi host struct to add to subsystem
@@ -1018,20 +1035,11 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost)
1018{ 1035{
1019 int error, i; 1036 int error, i;
1020 1037
1038 /* add host specific attributes */
1021 if (shost->hostt->shost_attrs) { 1039 if (shost->hostt->shost_attrs) {
1022 for (i = 0; shost->hostt->shost_attrs[i]; i++) { 1040 for (i = 0; shost->hostt->shost_attrs[i]; i++) {
1023 error = class_attr_add(&shost->shost_dev,
1024 shost->hostt->shost_attrs[i]);
1025 if (error)
1026 return error;
1027 }
1028 }
1029
1030 for (i = 0; scsi_sysfs_shost_attrs[i]; i++) {
1031 if (!class_attr_overridden(shost->hostt->shost_attrs,
1032 scsi_sysfs_shost_attrs[i])) {
1033 error = device_create_file(&shost->shost_dev, 1041 error = device_create_file(&shost->shost_dev,
1034 scsi_sysfs_shost_attrs[i]); 1042 shost->hostt->shost_attrs[i]);
1035 if (error) 1043 if (error)
1036 return error; 1044 return error;
1037 } 1045 }