diff options
-rw-r--r-- | drivers/scsi/scsi_sysfs.c | 136 |
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) | |||
618 | static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL); | 618 | static 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 */ |
621 | static struct device_attribute *scsi_sysfs_sdev_attrs[] = { | 621 | static 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 | |||
640 | static struct attribute_group scsi_sdev_attr_group = { | ||
641 | .attrs = scsi_sdev_attrs, | ||
642 | }; | ||
643 | |||
644 | static 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 | ||
700 | static 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 | |||
714 | static 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 | |||
728 | static 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 | ||
963 | static struct device_type scsi_dev_type = { | ||
964 | .name = "scsi_device", | ||
965 | .release = scsi_device_dev_release, | ||
966 | .groups = scsi_sdev_attr_groups, | ||
967 | }; | ||
968 | |||
1001 | void scsi_sysfs_device_initialize(struct scsi_device *sdev) | 969 | void 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); |