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.c136
1 files changed, 52 insertions, 84 deletions
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index a3d227f3f520..0088c4dd7c6a 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -618,24 +618,31 @@ sdev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
618static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL); 618static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL);
619 619
620/* Default template for device attributes. May NOT be modified */ 620/* Default template for device attributes. May NOT be modified */
621static struct device_attribute *scsi_sysfs_sdev_attrs[] = { 621static struct attribute *scsi_sdev_attrs[] = {
622 &dev_attr_device_blocked, 622 &dev_attr_device_blocked.attr,
623 &dev_attr_queue_depth, 623 &dev_attr_type.attr,
624 &dev_attr_queue_type, 624 &dev_attr_scsi_level.attr,
625 &dev_attr_type, 625 &dev_attr_vendor.attr,
626 &dev_attr_scsi_level, 626 &dev_attr_model.attr,
627 &dev_attr_vendor, 627 &dev_attr_rev.attr,
628 &dev_attr_model, 628 &dev_attr_rescan.attr,
629 &dev_attr_rev, 629 &dev_attr_delete.attr,
630 &dev_attr_rescan, 630 &dev_attr_state.attr,
631 &dev_attr_delete, 631 &dev_attr_timeout.attr,
632 &dev_attr_state, 632 &dev_attr_iocounterbits.attr,
633 &dev_attr_timeout, 633 &dev_attr_iorequest_cnt.attr,
634 &dev_attr_iocounterbits, 634 &dev_attr_iodone_cnt.attr,
635 &dev_attr_iorequest_cnt, 635 &dev_attr_ioerr_cnt.attr,
636 &dev_attr_iodone_cnt, 636 &dev_attr_modalias.attr,
637 &dev_attr_ioerr_cnt, 637 NULL
638 &dev_attr_modalias, 638};
639
640static struct attribute_group scsi_sdev_attr_group = {
641 .attrs = scsi_sdev_attrs,
642};
643
644static struct attribute_group *scsi_sdev_attr_groups[] = {
645 &scsi_sdev_attr_group,
639 NULL 646 NULL
640}; 647};
641 648
@@ -697,56 +704,6 @@ static struct device_attribute sdev_attr_queue_type_rw =
697 __ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field, 704 __ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field,
698 sdev_store_queue_type_rw); 705 sdev_store_queue_type_rw);
699 706
700static struct device_attribute *attr_changed_internally(
701 struct Scsi_Host *shost,
702 struct device_attribute * attr)
703{
704 if (!strcmp("queue_depth", attr->attr.name)
705 && shost->hostt->change_queue_depth)
706 return &sdev_attr_queue_depth_rw;
707 else if (!strcmp("queue_type", attr->attr.name)
708 && shost->hostt->change_queue_type)
709 return &sdev_attr_queue_type_rw;
710 return attr;
711}
712
713
714static struct device_attribute *attr_overridden(
715 struct device_attribute **attrs,
716 struct device_attribute *attr)
717{
718 int i;
719
720 if (!attrs)
721 return NULL;
722 for (i = 0; attrs[i]; i++)
723 if (!strcmp(attrs[i]->attr.name, attr->attr.name))
724 return attrs[i];
725 return NULL;
726}
727
728static int attr_add(struct device *dev, struct device_attribute *attr)
729{
730 struct device_attribute *base_attr;
731
732 /*
733 * Spare the caller from having to copy things it's not interested in.
734 */
735 base_attr = attr_overridden(scsi_sysfs_sdev_attrs, attr);
736 if (base_attr) {
737 /* extend permissions */
738 attr->attr.mode |= base_attr->attr.mode;
739
740 /* override null show/store with default */
741 if (!attr->show)
742 attr->show = base_attr->show;
743 if (!attr->store)
744 attr->store = base_attr->store;
745 }
746
747 return device_create_file(dev, attr);
748}
749
750/** 707/**
751 * scsi_sysfs_add_sdev - add scsi device to sysfs 708 * scsi_sysfs_add_sdev - add scsi device to sysfs
752 * @sdev: scsi_device to add 709 * @sdev: scsi_device to add
@@ -778,6 +735,24 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
778 * released by the sdev_class .release */ 735 * released by the sdev_class .release */
779 get_device(&sdev->sdev_gendev); 736 get_device(&sdev->sdev_gendev);
780 737
738 /* create queue files, which may be writable, depending on the host */
739 if (sdev->host->hostt->change_queue_depth)
740 error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_depth_rw);
741 else
742 error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_depth);
743 if (error) {
744 __scsi_remove_device(sdev);
745 goto out;
746 }
747 if (sdev->host->hostt->change_queue_type)
748 error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_type_rw);
749 else
750 error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_type);
751 if (error) {
752 __scsi_remove_device(sdev);
753 goto out;
754 }
755
781 error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL); 756 error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL);
782 757
783 if (error) 758 if (error)
@@ -788,9 +763,10 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
788 * nothing went wrong */ 763 * nothing went wrong */
789 error = 0; 764 error = 0;
790 765
766 /* add additional host specific attributes */
791 if (sdev->host->hostt->sdev_attrs) { 767 if (sdev->host->hostt->sdev_attrs) {
792 for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) { 768 for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) {
793 error = attr_add(&sdev->sdev_gendev, 769 error = device_create_file(&sdev->sdev_gendev,
794 sdev->host->hostt->sdev_attrs[i]); 770 sdev->host->hostt->sdev_attrs[i]);
795 if (error) { 771 if (error) {
796 __scsi_remove_device(sdev); 772 __scsi_remove_device(sdev);
@@ -798,20 +774,6 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
798 } 774 }
799 } 775 }
800 } 776 }
801
802 for (i = 0; scsi_sysfs_sdev_attrs[i]; i++) {
803 if (!attr_overridden(sdev->host->hostt->sdev_attrs,
804 scsi_sysfs_sdev_attrs[i])) {
805 struct device_attribute * attr =
806 attr_changed_internally(sdev->host,
807 scsi_sysfs_sdev_attrs[i]);
808 error = device_create_file(&sdev->sdev_gendev, attr);
809 if (error) {
810 __scsi_remove_device(sdev);
811 goto out;
812 }
813 }
814 }
815 777
816 transport_add_device(&sdev->sdev_gendev); 778 transport_add_device(&sdev->sdev_gendev);
817 out: 779 out:
@@ -998,6 +960,12 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost)
998 return 0; 960 return 0;
999} 961}
1000 962
963static struct device_type scsi_dev_type = {
964 .name = "scsi_device",
965 .release = scsi_device_dev_release,
966 .groups = scsi_sdev_attr_groups,
967};
968
1001void scsi_sysfs_device_initialize(struct scsi_device *sdev) 969void scsi_sysfs_device_initialize(struct scsi_device *sdev)
1002{ 970{
1003 unsigned long flags; 971 unsigned long flags;
@@ -1006,7 +974,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
1006 974
1007 device_initialize(&sdev->sdev_gendev); 975 device_initialize(&sdev->sdev_gendev);
1008 sdev->sdev_gendev.bus = &scsi_bus_type; 976 sdev->sdev_gendev.bus = &scsi_bus_type;
1009 sdev->sdev_gendev.release = scsi_device_dev_release; 977 sdev->sdev_gendev.type = &scsi_dev_type;
1010 sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d", 978 sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d",
1011 sdev->host->host_no, sdev->channel, sdev->id, 979 sdev->host->host_no, sdev->channel, sdev->id,
1012 sdev->lun); 980 sdev->lun);