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.c180
1 files changed, 95 insertions, 85 deletions
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index ede9986d349a..daed37df00b1 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -190,6 +190,46 @@ show_shost_state(struct class_device *class_dev, char *buf)
190 190
191static CLASS_DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state); 191static CLASS_DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state);
192 192
193static ssize_t
194show_shost_mode(unsigned int mode, char *buf)
195{
196 ssize_t len = 0;
197
198 if (mode & MODE_INITIATOR)
199 len = sprintf(buf, "%s", "Initiator");
200
201 if (mode & MODE_TARGET)
202 len += sprintf(buf + len, "%s%s", len ? ", " : "", "Target");
203
204 len += sprintf(buf + len, "\n");
205
206 return len;
207}
208
209static ssize_t show_shost_supported_mode(struct class_device *class_dev, char *buf)
210{
211 struct Scsi_Host *shost = class_to_shost(class_dev);
212
213 if (shost->hostt->supported_mode == MODE_UNKNOWN)
214 return snprintf(buf, 20, "unknown\n");
215 else
216 return show_shost_mode(shost->hostt->supported_mode, buf);
217}
218
219static CLASS_DEVICE_ATTR(supported_mode, S_IRUGO | S_IWUSR, show_shost_supported_mode, NULL);
220
221static ssize_t show_shost_active_mode(struct class_device *class_dev, char *buf)
222{
223 struct Scsi_Host *shost = class_to_shost(class_dev);
224
225 if (shost->active_mode == MODE_UNKNOWN)
226 return snprintf(buf, 20, "unknown\n");
227 else
228 return show_shost_mode(shost->active_mode, buf);
229}
230
231static CLASS_DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL);
232
193shost_rd_attr(unique_id, "%u\n"); 233shost_rd_attr(unique_id, "%u\n");
194shost_rd_attr(host_busy, "%hu\n"); 234shost_rd_attr(host_busy, "%hu\n");
195shost_rd_attr(cmd_per_lun, "%hd\n"); 235shost_rd_attr(cmd_per_lun, "%hd\n");
@@ -208,6 +248,8 @@ static struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
208 &class_device_attr_proc_name, 248 &class_device_attr_proc_name,
209 &class_device_attr_scan, 249 &class_device_attr_scan,
210 &class_device_attr_state, 250 &class_device_attr_state,
251 &class_device_attr_supported_mode,
252 &class_device_attr_active_mode,
211 NULL 253 NULL
212}; 254};
213 255
@@ -571,24 +613,31 @@ sdev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
571static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL); 613static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL);
572 614
573/* Default template for device attributes. May NOT be modified */ 615/* Default template for device attributes. May NOT be modified */
574static struct device_attribute *scsi_sysfs_sdev_attrs[] = { 616static struct attribute *scsi_sdev_attrs[] = {
575 &dev_attr_device_blocked, 617 &dev_attr_device_blocked.attr,
576 &dev_attr_queue_depth, 618 &dev_attr_type.attr,
577 &dev_attr_queue_type, 619 &dev_attr_scsi_level.attr,
578 &dev_attr_type, 620 &dev_attr_vendor.attr,
579 &dev_attr_scsi_level, 621 &dev_attr_model.attr,
580 &dev_attr_vendor, 622 &dev_attr_rev.attr,
581 &dev_attr_model, 623 &dev_attr_rescan.attr,
582 &dev_attr_rev, 624 &dev_attr_delete.attr,
583 &dev_attr_rescan, 625 &dev_attr_state.attr,
584 &dev_attr_delete, 626 &dev_attr_timeout.attr,
585 &dev_attr_state, 627 &dev_attr_iocounterbits.attr,
586 &dev_attr_timeout, 628 &dev_attr_iorequest_cnt.attr,
587 &dev_attr_iocounterbits, 629 &dev_attr_iodone_cnt.attr,
588 &dev_attr_iorequest_cnt, 630 &dev_attr_ioerr_cnt.attr,
589 &dev_attr_iodone_cnt, 631 &dev_attr_modalias.attr,
590 &dev_attr_ioerr_cnt, 632 NULL
591 &dev_attr_modalias, 633};
634
635static struct attribute_group scsi_sdev_attr_group = {
636 .attrs = scsi_sdev_attrs,
637};
638
639static struct attribute_group *scsi_sdev_attr_groups[] = {
640 &scsi_sdev_attr_group,
592 NULL 641 NULL
593}; 642};
594 643
@@ -650,56 +699,6 @@ static struct device_attribute sdev_attr_queue_type_rw =
650 __ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field, 699 __ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field,
651 sdev_store_queue_type_rw); 700 sdev_store_queue_type_rw);
652 701
653static struct device_attribute *attr_changed_internally(
654 struct Scsi_Host *shost,
655 struct device_attribute * attr)
656{
657 if (!strcmp("queue_depth", attr->attr.name)
658 && shost->hostt->change_queue_depth)
659 return &sdev_attr_queue_depth_rw;
660 else if (!strcmp("queue_type", attr->attr.name)
661 && shost->hostt->change_queue_type)
662 return &sdev_attr_queue_type_rw;
663 return attr;
664}
665
666
667static struct device_attribute *attr_overridden(
668 struct device_attribute **attrs,
669 struct device_attribute *attr)
670{
671 int i;
672
673 if (!attrs)
674 return NULL;
675 for (i = 0; attrs[i]; i++)
676 if (!strcmp(attrs[i]->attr.name, attr->attr.name))
677 return attrs[i];
678 return NULL;
679}
680
681static int attr_add(struct device *dev, struct device_attribute *attr)
682{
683 struct device_attribute *base_attr;
684
685 /*
686 * Spare the caller from having to copy things it's not interested in.
687 */
688 base_attr = attr_overridden(scsi_sysfs_sdev_attrs, attr);
689 if (base_attr) {
690 /* extend permissions */
691 attr->attr.mode |= base_attr->attr.mode;
692
693 /* override null show/store with default */
694 if (!attr->show)
695 attr->show = base_attr->show;
696 if (!attr->store)
697 attr->store = base_attr->store;
698 }
699
700 return device_create_file(dev, attr);
701}
702
703/** 702/**
704 * scsi_sysfs_add_sdev - add scsi device to sysfs 703 * scsi_sysfs_add_sdev - add scsi device to sysfs
705 * @sdev: scsi_device to add 704 * @sdev: scsi_device to add
@@ -731,6 +730,24 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
731 * released by the sdev_class .release */ 730 * released by the sdev_class .release */
732 get_device(&sdev->sdev_gendev); 731 get_device(&sdev->sdev_gendev);
733 732
733 /* create queue files, which may be writable, depending on the host */
734 if (sdev->host->hostt->change_queue_depth)
735 error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_depth_rw);
736 else
737 error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_depth);
738 if (error) {
739 __scsi_remove_device(sdev);
740 goto out;
741 }
742 if (sdev->host->hostt->change_queue_type)
743 error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_type_rw);
744 else
745 error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_type);
746 if (error) {
747 __scsi_remove_device(sdev);
748 goto out;
749 }
750
734 error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL); 751 error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL);
735 752
736 if (error) 753 if (error)
@@ -741,9 +758,10 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
741 * nothing went wrong */ 758 * nothing went wrong */
742 error = 0; 759 error = 0;
743 760
761 /* add additional host specific attributes */
744 if (sdev->host->hostt->sdev_attrs) { 762 if (sdev->host->hostt->sdev_attrs) {
745 for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) { 763 for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) {
746 error = attr_add(&sdev->sdev_gendev, 764 error = device_create_file(&sdev->sdev_gendev,
747 sdev->host->hostt->sdev_attrs[i]); 765 sdev->host->hostt->sdev_attrs[i]);
748 if (error) { 766 if (error) {
749 __scsi_remove_device(sdev); 767 __scsi_remove_device(sdev);
@@ -751,20 +769,6 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
751 } 769 }
752 } 770 }
753 } 771 }
754
755 for (i = 0; scsi_sysfs_sdev_attrs[i]; i++) {
756 if (!attr_overridden(sdev->host->hostt->sdev_attrs,
757 scsi_sysfs_sdev_attrs[i])) {
758 struct device_attribute * attr =
759 attr_changed_internally(sdev->host,
760 scsi_sysfs_sdev_attrs[i]);
761 error = device_create_file(&sdev->sdev_gendev, attr);
762 if (error) {
763 __scsi_remove_device(sdev);
764 goto out;
765 }
766 }
767 }
768 772
769 transport_add_device(&sdev->sdev_gendev); 773 transport_add_device(&sdev->sdev_gendev);
770 out: 774 out:
@@ -951,6 +955,12 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost)
951 return 0; 955 return 0;
952} 956}
953 957
958static struct device_type scsi_dev_type = {
959 .name = "scsi_device",
960 .release = scsi_device_dev_release,
961 .groups = scsi_sdev_attr_groups,
962};
963
954void scsi_sysfs_device_initialize(struct scsi_device *sdev) 964void scsi_sysfs_device_initialize(struct scsi_device *sdev)
955{ 965{
956 unsigned long flags; 966 unsigned long flags;
@@ -959,7 +969,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
959 969
960 device_initialize(&sdev->sdev_gendev); 970 device_initialize(&sdev->sdev_gendev);
961 sdev->sdev_gendev.bus = &scsi_bus_type; 971 sdev->sdev_gendev.bus = &scsi_bus_type;
962 sdev->sdev_gendev.release = scsi_device_dev_release; 972 sdev->sdev_gendev.type = &scsi_dev_type;
963 sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d", 973 sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d",
964 sdev->host->host_no, sdev->channel, sdev->id, 974 sdev->host->host_no, sdev->channel, sdev->id,
965 sdev->lun); 975 sdev->lun);
@@ -980,7 +990,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
980 990
981int scsi_is_sdev_device(const struct device *dev) 991int scsi_is_sdev_device(const struct device *dev)
982{ 992{
983 return dev->release == scsi_device_dev_release; 993 return dev->type == &scsi_dev_type;
984} 994}
985EXPORT_SYMBOL(scsi_is_sdev_device); 995EXPORT_SYMBOL(scsi_is_sdev_device);
986 996