Start separating SATA specific code from libata-scsi.c: * un-static ata_scsi_find_dev() * move following code to libata-sata.c: - SATA only sysfs device attributes handling - __ata_change_queue_depth() - ata_scsi_change_queue_depth() * cover with CONFIG_SATA_HOST ifdef SATA only sysfs device attributes handling code and ATA_SHT_NCQ() macro in <linux/libata.h> Code size savings on m68k arch using (modified) atari_defconfig: text data bss dec hex filename before: 20702 105 576 21383 5387 drivers/ata/libata-scsi.o after: 19137 23 576 19736 4d18 drivers/ata/libata-scsi.o
Unified · Split
| @@ -8,6 +8,7 @@ · 7 unmodified lines | |||
| 8 | 8 | ||
| 9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include <scsi/scsi_device.h> | ||
| 11 | #include <linux/libata.h> | 12 | #include <linux/libata.h> |
| 12 | 13 | ||
| 13 | #include "libata.h" | 14 | #include "libata.h" |
| @@ -764,3 +765,300 @@ bool sata_lpm_ignore_phy_events(struct ata_link *link) · 750 unmodified lines | |||
| 764 | return false; | 765 | return false; |
| 765 | } | 766 | } |
| 766 | EXPORT_SYMBOL_GPL(sata_lpm_ignore_phy_events); | 767 | EXPORT_SYMBOL_GPL(sata_lpm_ignore_phy_events); |
| 768 | |||
| 769 | static const char *ata_lpm_policy_names[] = { | ||
| 770 | [ATA_LPM_UNKNOWN] = "max_performance", | ||
| 771 | [ATA_LPM_MAX_POWER] = "max_performance", | ||
| 772 | [ATA_LPM_MED_POWER] = "medium_power", | ||
| 773 | [ATA_LPM_MED_POWER_WITH_DIPM] = "med_power_with_dipm", | ||
| 774 | [ATA_LPM_MIN_POWER_WITH_PARTIAL] = "min_power_with_partial", | ||
| 775 | [ATA_LPM_MIN_POWER] = "min_power", | ||
| 776 | }; | ||
| 777 | |||
| 778 | static ssize_t ata_scsi_lpm_store(struct device *device, | ||
| 779 | struct device_attribute *attr, | ||
| 780 | const char *buf, size_t count) | ||
| 781 | { | ||
| 782 | struct Scsi_Host *shost = class_to_shost(device); | ||
| 783 | struct ata_port *ap = ata_shost_to_port(shost); | ||
| 784 | struct ata_link *link; | ||
| 785 | struct ata_device *dev; | ||
| 786 | enum ata_lpm_policy policy; | ||
| 787 | unsigned long flags; | ||
| 788 | |||
| 789 | /* UNKNOWN is internal state, iterate from MAX_POWER */ | ||
| 790 | for (policy = ATA_LPM_MAX_POWER; | ||
| 791 | policy < ARRAY_SIZE(ata_lpm_policy_names); policy++) { | ||
| 792 | const char *name = ata_lpm_policy_names[policy]; | ||
| 793 | |||
| 794 | if (strncmp(name, buf, strlen(name)) == 0) | ||
| 795 | break; | ||
| 796 | } | ||
| 797 | if (policy == ARRAY_SIZE(ata_lpm_policy_names)) | ||
| 798 | return -EINVAL; | ||
| 799 | |||
| 800 | spin_lock_irqsave(ap->lock, flags); | ||
| 801 | |||
| 802 | ata_for_each_link(link, ap, EDGE) { | ||
| 803 | ata_for_each_dev(dev, &ap->link, ENABLED) { | ||
| 804 | if (dev->horkage & ATA_HORKAGE_NOLPM) { | ||
| 805 | count = -EOPNOTSUPP; | ||
| 806 | goto out_unlock; | ||
| 807 | } | ||
| 808 | } | ||
| 809 | } | ||
| 810 | |||
| 811 | ap->target_lpm_policy = policy; | ||
| 812 | ata_port_schedule_eh(ap); | ||
| 813 | out_unlock: | ||
| 814 | spin_unlock_irqrestore(ap->lock, flags); | ||
| 815 | return count; | ||
| 816 | } | ||
| 817 | |||
| 818 | static ssize_t ata_scsi_lpm_show(struct device *dev, | ||
| 819 | struct device_attribute *attr, char *buf) | ||
| 820 | { | ||
| 821 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 822 | struct ata_port *ap = ata_shost_to_port(shost); | ||
| 823 | |||
| 824 | if (ap->target_lpm_policy >= ARRAY_SIZE(ata_lpm_policy_names)) | ||
| 825 | return -EINVAL; | ||
| 826 | |||
| 827 | return snprintf(buf, PAGE_SIZE, "%s\n", | ||
| 828 | ata_lpm_policy_names[ap->target_lpm_policy]); | ||
| 829 | } | ||
| 830 | DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR, | ||
| 831 | ata_scsi_lpm_show, ata_scsi_lpm_store); | ||
| 832 | EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy); | ||
| 833 | |||
| 834 | static ssize_t ata_ncq_prio_enable_show(struct device *device, | ||
| 835 | struct device_attribute *attr, | ||
| 836 | char *buf) | ||
| 837 | { | ||
| 838 | struct scsi_device *sdev = to_scsi_device(device); | ||
| 839 | struct ata_port *ap; | ||
| 840 | struct ata_device *dev; | ||
| 841 | bool ncq_prio_enable; | ||
| 842 | int rc = 0; | ||
| 843 | |||
| 844 | ap = ata_shost_to_port(sdev->host); | ||
| 845 | |||
| 846 | spin_lock_irq(ap->lock); | ||
| 847 | dev = ata_scsi_find_dev(ap, sdev); | ||
| 848 | if (!dev) { | ||
| 849 | rc = -ENODEV; | ||
| 850 | goto unlock; | ||
| 851 | } | ||
| 852 | |||
| 853 | ncq_prio_enable = dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLE; | ||
| 854 | |||
| 855 | unlock: | ||
| 856 | spin_unlock_irq(ap->lock); | ||
| 857 | |||
| 858 | return rc ? rc : snprintf(buf, 20, "%u\n", ncq_prio_enable); | ||
| 859 | } | ||
| 860 | |||
| 861 | static ssize_t ata_ncq_prio_enable_store(struct device *device, | ||
| 862 | struct device_attribute *attr, | ||
| 863 | const char *buf, size_t len) | ||
| 864 | { | ||
| 865 | struct scsi_device *sdev = to_scsi_device(device); | ||
| 866 | struct ata_port *ap; | ||
| 867 | struct ata_device *dev; | ||
| 868 | long int input; | ||
| 869 | int rc; | ||
| 870 | |||
| 871 | rc = kstrtol(buf, 10, &input); | ||
| 872 | if (rc) | ||
| 873 | return rc; | ||
| 874 | if ((input < 0) || (input > 1)) | ||
| 875 | return -EINVAL; | ||
| 876 | |||
| 877 | ap = ata_shost_to_port(sdev->host); | ||
| 878 | dev = ata_scsi_find_dev(ap, sdev); | ||
| 879 | if (unlikely(!dev)) | ||
| 880 | return -ENODEV; | ||
| 881 | |||
| 882 | spin_lock_irq(ap->lock); | ||
| 883 | if (input) | ||
| 884 | dev->flags |= ATA_DFLAG_NCQ_PRIO_ENABLE; | ||
| 885 | else | ||
| 886 | dev->flags &= ~ATA_DFLAG_NCQ_PRIO_ENABLE; | ||
| 887 | |||
| 888 | dev->link->eh_info.action |= ATA_EH_REVALIDATE; | ||
| 889 | dev->link->eh_info.flags |= ATA_EHI_QUIET; | ||
| 890 | ata_port_schedule_eh(ap); | ||
| 891 | spin_unlock_irq(ap->lock); | ||
| 892 | |||
| 893 | ata_port_wait_eh(ap); | ||
| 894 | |||
| 895 | if (input) { | ||
| 896 | spin_lock_irq(ap->lock); | ||
| 897 | if (!(dev->flags & ATA_DFLAG_NCQ_PRIO)) { | ||
| 898 | dev->flags &= ~ATA_DFLAG_NCQ_PRIO_ENABLE; | ||
| 899 | rc = -EIO; | ||
| 900 | } | ||
| 901 | spin_unlock_irq(ap->lock); | ||
| 902 | } | ||
| 903 | |||
| 904 | return rc ? rc : len; | ||
| 905 | } | ||
| 906 | |||
| 907 | DEVICE_ATTR(ncq_prio_enable, S_IRUGO | S_IWUSR, | ||
| 908 | ata_ncq_prio_enable_show, ata_ncq_prio_enable_store); | ||
| 909 | EXPORT_SYMBOL_GPL(dev_attr_ncq_prio_enable); | ||
| 910 | |||
| 911 | struct device_attribute *ata_ncq_sdev_attrs[] = { | ||
| 912 | &dev_attr_unload_heads, | ||
| 913 | &dev_attr_ncq_prio_enable, | ||
| 914 | NULL | ||
| 915 | }; | ||
| 916 | EXPORT_SYMBOL_GPL(ata_ncq_sdev_attrs); | ||
| 917 | |||
| 918 | static ssize_t | ||
| 919 | ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr, | ||
| 920 | const char *buf, size_t count) | ||
| 921 | { | ||
| 922 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 923 | struct ata_port *ap = ata_shost_to_port(shost); | ||
| 924 | if (ap->ops->em_store && (ap->flags & ATA_FLAG_EM)) | ||
| 925 | return ap->ops->em_store(ap, buf, count); | ||
| 926 | return -EINVAL; | ||
| 927 | } | ||
| 928 | |||
| 929 | static ssize_t | ||
| 930 | ata_scsi_em_message_show(struct device *dev, struct device_attribute *attr, | ||
| 931 | char *buf) | ||
| 932 | { | ||
| 933 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 934 | struct ata_port *ap = ata_shost_to_port(shost); | ||
| 935 | |||
| 936 | if (ap->ops->em_show && (ap->flags & ATA_FLAG_EM)) | ||
| 937 | return ap->ops->em_show(ap, buf); | ||
| 938 | return -EINVAL; | ||
| 939 | } | ||
| 940 | DEVICE_ATTR(em_message, S_IRUGO | S_IWUSR, | ||
| 941 | ata_scsi_em_message_show, ata_scsi_em_message_store); | ||
| 942 | EXPORT_SYMBOL_GPL(dev_attr_em_message); | ||
| 943 | |||
| 944 | static ssize_t | ||
| 945 | ata_scsi_em_message_type_show(struct device *dev, struct device_attribute *attr, | ||
| 946 | char *buf) | ||
| 947 | { | ||
| 948 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 949 | struct ata_port *ap = ata_shost_to_port(shost); | ||
| 950 | |||
| 951 | return snprintf(buf, 23, "%d\n", ap->em_message_type); | ||
| 952 | } | ||
| 953 | DEVICE_ATTR(em_message_type, S_IRUGO, | ||
| 954 | ata_scsi_em_message_type_show, NULL); | ||
| 955 | EXPORT_SYMBOL_GPL(dev_attr_em_message_type); | ||
| 956 | |||
| 957 | static ssize_t | ||
| 958 | ata_scsi_activity_show(struct device *dev, struct device_attribute *attr, | ||
| 959 | char *buf) | ||
| 960 | { | ||
| 961 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 962 | struct ata_port *ap = ata_shost_to_port(sdev->host); | ||
| 963 | struct ata_device *atadev = ata_scsi_find_dev(ap, sdev); | ||
| 964 | |||
| 965 | if (atadev && ap->ops->sw_activity_show && | ||
| 966 | (ap->flags & ATA_FLAG_SW_ACTIVITY)) | ||
| 967 | return ap->ops->sw_activity_show(atadev, buf); | ||
| 968 | return -EINVAL; | ||
| 969 | } | ||
| 970 | |||
| 971 | static ssize_t | ||
| 972 | ata_scsi_activity_store(struct device *dev, struct device_attribute *attr, | ||
| 973 | const char *buf, size_t count) | ||
| 974 | { | ||
| 975 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 976 | struct ata_port *ap = ata_shost_to_port(sdev->host); | ||
| 977 | struct ata_device *atadev = ata_scsi_find_dev(ap, sdev); | ||
| 978 | enum sw_activity val; | ||
| 979 | int rc; | ||
| 980 | |||
| 981 | if (atadev && ap->ops->sw_activity_store && | ||
| 982 | (ap->flags & ATA_FLAG_SW_ACTIVITY)) { | ||
| 983 | val = simple_strtoul(buf, NULL, 0); | ||
| 984 | switch (val) { | ||
| 985 | case OFF: case BLINK_ON: case BLINK_OFF: | ||
| 986 | rc = ap->ops->sw_activity_store(atadev, val); | ||
| 987 | if (!rc) | ||
| 988 | return count; | ||
| 989 | else | ||
| 990 | return rc; | ||
| 991 | } | ||
| 992 | } | ||
| 993 | return -EINVAL; | ||
| 994 | } | ||
| 995 | DEVICE_ATTR(sw_activity, S_IWUSR | S_IRUGO, ata_scsi_activity_show, | ||
| 996 | ata_scsi_activity_store); | ||
| 997 | EXPORT_SYMBOL_GPL(dev_attr_sw_activity); | ||
| 998 | |||
| 999 | /** | ||
| 1000 | * __ata_change_queue_depth - helper for ata_scsi_change_queue_depth | ||
| 1001 | * @ap: ATA port to which the device change the queue depth | ||
| 1002 | * @sdev: SCSI device to configure queue depth for | ||
| 1003 | * @queue_depth: new queue depth | ||
| 1004 | * | ||
| 1005 | * libsas and libata have different approaches for associating a sdev to | ||
| 1006 | * its ata_port. | ||
| 1007 | * | ||
| 1008 | */ | ||
| 1009 | int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev, | ||
| 1010 | int queue_depth) | ||
| 1011 | { | ||
| 1012 | struct ata_device *dev; | ||
| 1013 | unsigned long flags; | ||
| 1014 | |||
| 1015 | if (queue_depth < 1 || queue_depth == sdev->queue_depth) | ||
| 1016 | return sdev->queue_depth; | ||
| 1017 | |||
| 1018 | dev = ata_scsi_find_dev(ap, sdev); | ||
| 1019 | if (!dev || !ata_dev_enabled(dev)) | ||
| 1020 | return sdev->queue_depth; | ||
| 1021 | |||
| 1022 | /* NCQ enabled? */ | ||
| 1023 | spin_lock_irqsave(ap->lock, flags); | ||
| 1024 | dev->flags &= ~ATA_DFLAG_NCQ_OFF; | ||
| 1025 | if (queue_depth == 1 || !ata_ncq_enabled(dev)) { | ||
| 1026 | dev->flags |= ATA_DFLAG_NCQ_OFF; | ||
| 1027 | queue_depth = 1; | ||
| 1028 | } | ||
| 1029 | spin_unlock_irqrestore(ap->lock, flags); | ||
| 1030 | |||
| 1031 | /* limit and apply queue depth */ | ||
| 1032 | queue_depth = min(queue_depth, sdev->host->can_queue); | ||
| 1033 | queue_depth = min(queue_depth, ata_id_queue_depth(dev->id)); | ||
| 1034 | queue_depth = min(queue_depth, ATA_MAX_QUEUE); | ||
| 1035 | |||
| 1036 | if (sdev->queue_depth == queue_depth) | ||
| 1037 | return -EINVAL; | ||
| 1038 | |||
| 1039 | return scsi_change_queue_depth(sdev, queue_depth); | ||
| 1040 | } | ||
| 1041 | EXPORT_SYMBOL_GPL(__ata_change_queue_depth); | ||
| 1042 | |||
| 1043 | /** | ||
| 1044 | * ata_scsi_change_queue_depth - SCSI callback for queue depth config | ||
| 1045 | * @sdev: SCSI device to configure queue depth for | ||
| 1046 | * @queue_depth: new queue depth | ||
| 1047 | * | ||
| 1048 | * This is libata standard hostt->change_queue_depth callback. | ||
| 1049 | * SCSI will call into this callback when user tries to set queue | ||
| 1050 | * depth via sysfs. | ||
| 1051 | * | ||
| 1052 | * LOCKING: | ||
| 1053 | * SCSI layer (we don't care) | ||
| 1054 | * | ||
| 1055 | * RETURNS: | ||
| 1056 | * Newly configured queue depth. | ||
| 1057 | */ | ||
| 1058 | int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth) | ||
| 1059 | { | ||
| 1060 | struct ata_port *ap = ata_shost_to_port(sdev->host); | ||
| 1061 | |||
| 1062 | return __ata_change_queue_depth(ap, sdev, queue_depth); | ||
| 1063 | } | ||
| 1064 | EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth); | ||
| @@ -46,8 +46,6 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc); · 45 unmodified lines | |||
| 46 | 46 | ||
| 47 | static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap, | 47 | static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap, |
| 48 | const struct scsi_device *scsidev); | 48 | const struct scsi_device *scsidev); |
| 49 | static struct ata_device *ata_scsi_find_dev(struct ata_port *ap, | ||
| 50 | const struct scsi_device *scsidev); | ||
| 51 | 49 | ||
| 52 | #define RW_RECOVERY_MPAGE 0x1 | 50 | #define RW_RECOVERY_MPAGE 0x1 |
| 53 | #define RW_RECOVERY_MPAGE_LEN 12 | 51 | #define RW_RECOVERY_MPAGE_LEN 12 |
| @@ -87,71 +85,6 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = { · 33 unmodified lines | |||
| 87 | 0, 30 /* extended self test time, see 05-359r1 */ | 85 | 0, 30 /* extended self test time, see 05-359r1 */ |
| 88 | }; | 86 | }; |
| 89 | 87 | ||
| 90 | static const char *ata_lpm_policy_names[] = { | ||
| 91 | [ATA_LPM_UNKNOWN] = "max_performance", | ||
| 92 | [ATA_LPM_MAX_POWER] = "max_performance", | ||
| 93 | [ATA_LPM_MED_POWER] = "medium_power", | ||
| 94 | [ATA_LPM_MED_POWER_WITH_DIPM] = "med_power_with_dipm", | ||
| 95 | [ATA_LPM_MIN_POWER_WITH_PARTIAL] = "min_power_with_partial", | ||
| 96 | [ATA_LPM_MIN_POWER] = "min_power", | ||
| 97 | }; | ||
| 98 | |||
| 99 | static ssize_t ata_scsi_lpm_store(struct device *device, | ||
| 100 | struct device_attribute *attr, | ||
| 101 | const char *buf, size_t count) | ||
| 102 | { | ||
| 103 | struct Scsi_Host *shost = class_to_shost(device); | ||
| 104 | struct ata_port *ap = ata_shost_to_port(shost); | ||
| 105 | struct ata_link *link; | ||
| 106 | struct ata_device *dev; | ||
| 107 | enum ata_lpm_policy policy; | ||
| 108 | unsigned long flags; | ||
| 109 | |||
| 110 | /* UNKNOWN is internal state, iterate from MAX_POWER */ | ||
| 111 | for (policy = ATA_LPM_MAX_POWER; | ||
| 112 | policy < ARRAY_SIZE(ata_lpm_policy_names); policy++) { | ||
| 113 | const char *name = ata_lpm_policy_names[policy]; | ||
| 114 | |||
| 115 | if (strncmp(name, buf, strlen(name)) == 0) | ||
| 116 | break; | ||
| 117 | } | ||
| 118 | if (policy == ARRAY_SIZE(ata_lpm_policy_names)) | ||
| 119 | return -EINVAL; | ||
| 120 | |||
| 121 | spin_lock_irqsave(ap->lock, flags); | ||
| 122 | |||
| 123 | ata_for_each_link(link, ap, EDGE) { | ||
| 124 | ata_for_each_dev(dev, &ap->link, ENABLED) { | ||
| 125 | if (dev->horkage & ATA_HORKAGE_NOLPM) { | ||
| 126 | count = -EOPNOTSUPP; | ||
| 127 | goto out_unlock; | ||
| 128 | } | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | ap->target_lpm_policy = policy; | ||
| 133 | ata_port_schedule_eh(ap); | ||
| 134 | out_unlock: | ||
| 135 | spin_unlock_irqrestore(ap->lock, flags); | ||
| 136 | return count; | ||
| 137 | } | ||
| 138 | |||
| 139 | static ssize_t ata_scsi_lpm_show(struct device *dev, | ||
| 140 | struct device_attribute *attr, char *buf) | ||
| 141 | { | ||
| 142 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 143 | struct ata_port *ap = ata_shost_to_port(shost); | ||
| 144 | |||
| 145 | if (ap->target_lpm_policy >= ARRAY_SIZE(ata_lpm_policy_names)) | ||
| 146 | return -EINVAL; | ||
| 147 | |||
| 148 | return snprintf(buf, PAGE_SIZE, "%s\n", | ||
| 149 | ata_lpm_policy_names[ap->target_lpm_policy]); | ||
| 150 | } | ||
| 151 | DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR, | ||
| 152 | ata_scsi_lpm_show, ata_scsi_lpm_store); | ||
| 153 | EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy); | ||
| 154 | |||
| 155 | static ssize_t ata_scsi_park_show(struct device *device, | 88 | static ssize_t ata_scsi_park_show(struct device *device, |
| 156 | struct device_attribute *attr, char *buf) | 89 | struct device_attribute *attr, char *buf) |
| 157 | { | 90 | { |
| @@ -255,83 +188,6 @@ DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR, · 97 unmodified lines | |||
| 255 | ata_scsi_park_show, ata_scsi_park_store); | 188 | ata_scsi_park_show, ata_scsi_park_store); |
| 256 | EXPORT_SYMBOL_GPL(dev_attr_unload_heads); | 189 | EXPORT_SYMBOL_GPL(dev_attr_unload_heads); |
| 257 | 190 | ||
| 258 | static ssize_t ata_ncq_prio_enable_show(struct device *device, | ||
| 259 | struct device_attribute *attr, | ||
| 260 | char *buf) | ||
| 261 | { | ||
| 262 | struct scsi_device *sdev = to_scsi_device(device); | ||
| 263 | struct ata_port *ap; | ||
| 264 | struct ata_device *dev; | ||
| 265 | bool ncq_prio_enable; | ||
| 266 | int rc = 0; | ||
| 267 | |||
| 268 | ap = ata_shost_to_port(sdev->host); | ||
| 269 | |||
| 270 | spin_lock_irq(ap->lock); | ||
| 271 | dev = ata_scsi_find_dev(ap, sdev); | ||
| 272 | if (!dev) { | ||
| 273 | rc = -ENODEV; | ||
| 274 | goto unlock; | ||
| 275 | } | ||
| 276 | |||
| 277 | ncq_prio_enable = dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLE; | ||
| 278 | |||
| 279 | unlock: | ||
| 280 | spin_unlock_irq(ap->lock); | ||
| 281 | |||
| 282 | return rc ? rc : snprintf(buf, 20, "%u\n", ncq_prio_enable); | ||
| 283 | } | ||
| 284 | |||
| 285 | static ssize_t ata_ncq_prio_enable_store(struct device *device, | ||
| 286 | struct device_attribute *attr, | ||
| 287 | const char *buf, size_t len) | ||
| 288 | { | ||
| 289 | struct scsi_device *sdev = to_scsi_device(device); | ||
| 290 | struct ata_port *ap; | ||
| 291 | struct ata_device *dev; | ||
| 292 | long int input; | ||
| 293 | int rc; | ||
| 294 | |||
| 295 | rc = kstrtol(buf, 10, &input); | ||
| 296 | if (rc) | ||
| 297 | return rc; | ||
| 298 | if ((input < 0) || (input > 1)) | ||
| 299 | return -EINVAL; | ||
| 300 | |||
| 301 | ap = ata_shost_to_port(sdev->host); | ||
| 302 | dev = ata_scsi_find_dev(ap, sdev); | ||
| 303 | if (unlikely(!dev)) | ||
| 304 | return -ENODEV; | ||
| 305 | |||
| 306 | spin_lock_irq(ap->lock); | ||
| 307 | if (input) | ||
| 308 | dev->flags |= ATA_DFLAG_NCQ_PRIO_ENABLE; | ||
| 309 | else | ||
| 310 | dev->flags &= ~ATA_DFLAG_NCQ_PRIO_ENABLE; | ||
| 311 | |||
| 312 | dev->link->eh_info.action |= ATA_EH_REVALIDATE; | ||
| 313 | dev->link->eh_info.flags |= ATA_EHI_QUIET; | ||
| 314 | ata_port_schedule_eh(ap); | ||
| 315 | spin_unlock_irq(ap->lock); | ||
| 316 | |||
| 317 | ata_port_wait_eh(ap); | ||
| 318 | |||
| 319 | if (input) { | ||
| 320 | spin_lock_irq(ap->lock); | ||
| 321 | if (!(dev->flags & ATA_DFLAG_NCQ_PRIO)) { | ||
| 322 | dev->flags &= ~ATA_DFLAG_NCQ_PRIO_ENABLE; | ||
| 323 | rc = -EIO; | ||
| 324 | } | ||
| 325 | spin_unlock_irq(ap->lock); | ||
| 326 | } | ||
| 327 | |||
| 328 | return rc ? rc : len; | ||
| 329 | } | ||
| 330 | |||
| 331 | DEVICE_ATTR(ncq_prio_enable, S_IRUGO | S_IWUSR, | ||
| 332 | ata_ncq_prio_enable_show, ata_ncq_prio_enable_store); | ||
| 333 | EXPORT_SYMBOL_GPL(dev_attr_ncq_prio_enable); | ||
| 334 | |||
| 335 | void ata_scsi_set_sense(struct ata_device *dev, struct scsi_cmnd *cmd, | 191 | void ata_scsi_set_sense(struct ata_device *dev, struct scsi_cmnd *cmd, |
| 336 | u8 sk, u8 asc, u8 ascq) | 192 | u8 sk, u8 asc, u8 ascq) |
| 337 | { | 193 | { |
| @@ -380,100 +236,12 @@ static void ata_scsi_set_invalid_parameter(struct ata_device *dev, · 42 unmodified lines | |||
| 380 | field, 0xff, 0); | 236 | field, 0xff, 0); |
| 381 | } | 237 | } |
| 382 | 238 | ||
| 383 | static ssize_t | ||
| 384 | ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr, | ||
| 385 | const char *buf, size_t count) | ||
| 386 | { | ||
| 387 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 388 | struct ata_port *ap = ata_shost_to_port(shost); | ||
| 389 | if (ap->ops->em_store && (ap->flags & ATA_FLAG_EM)) | ||
| 390 | return ap->ops->em_store(ap, buf, count); | ||
| 391 | return -EINVAL; | ||
| 392 | } | ||
| 393 | |||
| 394 | static ssize_t | ||
| 395 | ata_scsi_em_message_show(struct device *dev, struct device_attribute *attr, | ||
| 396 | char *buf) | ||
| 397 | { | ||
| 398 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 399 | struct ata_port *ap = ata_shost_to_port(shost); | ||
| 400 | |||
| 401 | if (ap->ops->em_show && (ap->flags & ATA_FLAG_EM)) | ||
| 402 | return ap->ops->em_show(ap, buf); | ||
| 403 | return -EINVAL; | ||
| 404 | } | ||
| 405 | DEVICE_ATTR(em_message, S_IRUGO | S_IWUSR, | ||
| 406 | ata_scsi_em_message_show, ata_scsi_em_message_store); | ||
| 407 | EXPORT_SYMBOL_GPL(dev_attr_em_message); | ||
| 408 | |||
| 409 | static ssize_t | ||
| 410 | ata_scsi_em_message_type_show(struct device *dev, struct device_attribute *attr, | ||
| 411 | char *buf) | ||
| 412 | { | ||
| 413 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 414 | struct ata_port *ap = ata_shost_to_port(shost); | ||
| 415 | |||
| 416 | return snprintf(buf, 23, "%d\n", ap->em_message_type); | ||
| 417 | } | ||
| 418 | DEVICE_ATTR(em_message_type, S_IRUGO, | ||
| 419 | ata_scsi_em_message_type_show, NULL); | ||
| 420 | EXPORT_SYMBOL_GPL(dev_attr_em_message_type); | ||
| 421 | |||
| 422 | static ssize_t | ||
| 423 | ata_scsi_activity_show(struct device *dev, struct device_attribute *attr, | ||
| 424 | char *buf) | ||
| 425 | { | ||
| 426 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 427 | struct ata_port *ap = ata_shost_to_port(sdev->host); | ||
| 428 | struct ata_device *atadev = ata_scsi_find_dev(ap, sdev); | ||
| 429 | |||
| 430 | if (atadev && ap->ops->sw_activity_show && | ||
| 431 | (ap->flags & ATA_FLAG_SW_ACTIVITY)) | ||
| 432 | return ap->ops->sw_activity_show(atadev, buf); | ||
| 433 | return -EINVAL; | ||
| 434 | } | ||
| 435 | |||
| 436 | static ssize_t | ||
| 437 | ata_scsi_activity_store(struct device *dev, struct device_attribute *attr, | ||
| 438 | const char *buf, size_t count) | ||
| 439 | { | ||
| 440 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 441 | struct ata_port *ap = ata_shost_to_port(sdev->host); | ||
| 442 | struct ata_device *atadev = ata_scsi_find_dev(ap, sdev); | ||
| 443 | enum sw_activity val; | ||
| 444 | int rc; | ||
| 445 | |||
| 446 | if (atadev && ap->ops->sw_activity_store && | ||
| 447 | (ap->flags & ATA_FLAG_SW_ACTIVITY)) { | ||
| 448 | val = simple_strtoul(buf, NULL, 0); | ||
| 449 | switch (val) { | ||
| 450 | case OFF: case BLINK_ON: case BLINK_OFF: | ||
| 451 | rc = ap->ops->sw_activity_store(atadev, val); | ||
| 452 | if (!rc) | ||
| 453 | return count; | ||
| 454 | else | ||
| 455 | return rc; | ||
| 456 | } | ||
| 457 | } | ||
| 458 | return -EINVAL; | ||
| 459 | } | ||
| 460 | DEVICE_ATTR(sw_activity, S_IWUSR | S_IRUGO, ata_scsi_activity_show, | ||
| 461 | ata_scsi_activity_store); | ||
| 462 | EXPORT_SYMBOL_GPL(dev_attr_sw_activity); | ||
| 463 | |||
| 464 | struct device_attribute *ata_common_sdev_attrs[] = { | 239 | struct device_attribute *ata_common_sdev_attrs[] = { |
| 465 | &dev_attr_unload_heads, | 240 | &dev_attr_unload_heads, |
| 466 | NULL | 241 | NULL |
| 467 | }; | 242 | }; |
| 468 | EXPORT_SYMBOL_GPL(ata_common_sdev_attrs); | 243 | EXPORT_SYMBOL_GPL(ata_common_sdev_attrs); |
| 469 | 244 | ||
| 470 | struct device_attribute *ata_ncq_sdev_attrs[] = { | ||
| 471 | &dev_attr_unload_heads, | ||
| 472 | &dev_attr_ncq_prio_enable, | ||
| 473 | NULL | ||
| 474 | }; | ||
| 475 | EXPORT_SYMBOL_GPL(ata_ncq_sdev_attrs); | ||
| 476 | |||
| 477 | /** | 245 | /** |
| 478 | * ata_std_bios_param - generic bios head/sector/cylinder calculator used by sd. | 246 | * ata_std_bios_param - generic bios head/sector/cylinder calculator used by sd. |
| 479 | * @sdev: SCSI device for which BIOS geometry is to be determined | 247 | * @sdev: SCSI device for which BIOS geometry is to be determined |
| @@ -1391,73 +1159,6 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev) · 911 unmodified lines | |||
| 1391 | } | 1159 | } |
| 1392 | EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy); | 1160 | EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy); |
| 1393 | 1161 | ||
| 1394 | /** | ||
| 1395 | * __ata_change_queue_depth - helper for ata_scsi_change_queue_depth | ||
| 1396 | * @ap: ATA port to which the device change the queue depth | ||
| 1397 | * @sdev: SCSI device to configure queue depth for | ||
| 1398 | * @queue_depth: new queue depth | ||
| 1399 | * | ||
| 1400 | * libsas and libata have different approaches for associating a sdev to | ||
| 1401 | * its ata_port. | ||
| 1402 | * | ||
| 1403 | */ | ||
| 1404 | int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev, | ||
| 1405 | int queue_depth) | ||
| 1406 | { | ||
| 1407 | struct ata_device *dev; | ||
| 1408 | unsigned long flags; | ||
| 1409 | |||
| 1410 | if (queue_depth < 1 || queue_depth == sdev->queue_depth) | ||
| 1411 | return sdev->queue_depth; | ||
| 1412 | |||
| 1413 | dev = ata_scsi_find_dev(ap, sdev); | ||
| 1414 | if (!dev || !ata_dev_enabled(dev)) | ||
| 1415 | return sdev->queue_depth; | ||
| 1416 | |||
| 1417 | /* NCQ enabled? */ | ||
| 1418 | spin_lock_irqsave(ap->lock, flags); | ||
| 1419 | dev->flags &= ~ATA_DFLAG_NCQ_OFF; | ||
| 1420 | if (queue_depth == 1 || !ata_ncq_enabled(dev)) { | ||
| 1421 | dev->flags |= ATA_DFLAG_NCQ_OFF; | ||
| 1422 | queue_depth = 1; | ||
| 1423 | } | ||
| 1424 | spin_unlock_irqrestore(ap->lock, flags); | ||
| 1425 | |||
| 1426 | /* limit and apply queue depth */ | ||
| 1427 | queue_depth = min(queue_depth, sdev->host->can_queue); | ||
| 1428 | queue_depth = min(queue_depth, ata_id_queue_depth(dev->id)); | ||
| 1429 | queue_depth = min(queue_depth, ATA_MAX_QUEUE); | ||
| 1430 | |||
| 1431 | if (sdev->queue_depth == queue_depth) | ||
| 1432 | return -EINVAL; | ||
| 1433 | |||
| 1434 | return scsi_change_queue_depth(sdev, queue_depth); | ||
| 1435 | } | ||
| 1436 | EXPORT_SYMBOL_GPL(__ata_change_queue_depth); | ||
| 1437 | |||
| 1438 | /** | ||
| 1439 | * ata_scsi_change_queue_depth - SCSI callback for queue depth config | ||
| 1440 | * @sdev: SCSI device to configure queue depth for | ||
| 1441 | * @queue_depth: new queue depth | ||
| 1442 | * | ||
| 1443 | * This is libata standard hostt->change_queue_depth callback. | ||
| 1444 | * SCSI will call into this callback when user tries to set queue | ||
| 1445 | * depth via sysfs. | ||
| 1446 | * | ||
| 1447 | * LOCKING: | ||
| 1448 | * SCSI layer (we don't care) | ||
| 1449 | * | ||
| 1450 | * RETURNS: | ||
| 1451 | * Newly configured queue depth. | ||
| 1452 | */ | ||
| 1453 | int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth) | ||
| 1454 | { | ||
| 1455 | struct ata_port *ap = ata_shost_to_port(sdev->host); | ||
| 1456 | |||
| 1457 | return __ata_change_queue_depth(ap, sdev, queue_depth); | ||
| 1458 | } | ||
| 1459 | EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth); | ||
| 1460 | |||
| 1461 | /** | 1162 | /** |
| 1462 | * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command | 1163 | * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command |
| 1463 | * @qc: Storage for translated ATA taskfile | 1164 | * @qc: Storage for translated ATA taskfile |
| @@ -3094,7 +2795,7 @@ static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap, · 1630 unmodified lines | |||
| 3094 | * RETURNS: | 2795 | * RETURNS: |
| 3095 | * Associated ATA device, or %NULL if not found. | 2796 | * Associated ATA device, or %NULL if not found. |
| 3096 | */ | 2797 | */ |
| 3097 | static struct ata_device * | 2798 | struct ata_device * |
| 3098 | ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev) | 2799 | ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev) |
| 3099 | { | 2800 | { |
| 3100 | struct ata_device *dev = __ata_scsi_find_dev(ap, scsidev); | 2801 | struct ata_device *dev = __ata_scsi_find_dev(ap, scsidev); |
| @@ -112,6 +112,8 @@ static inline void ata_acpi_bind_dev(struct ata_device *dev) {} · 111 unmodified lines | |||
| 112 | #endif | 112 | #endif |
| 113 | 113 | ||
| 114 | /* libata-scsi.c */ | 114 | /* libata-scsi.c */ |
| 115 | extern struct ata_device *ata_scsi_find_dev(struct ata_port *ap, | ||
| 116 | const struct scsi_device *scsidev); | ||
| 115 | extern int ata_scsi_add_hosts(struct ata_host *host, | 117 | extern int ata_scsi_add_hosts(struct ata_host *host, |
| 116 | struct scsi_host_template *sht); | 118 | struct scsi_host_template *sht); |
| 117 | extern void ata_scsi_scan_host(struct ata_port *ap, int sync); | 119 | extern void ata_scsi_scan_host(struct ata_port *ap, int sync); |
| @@ -530,12 +530,14 @@ typedef int (*ata_reset_fn_t)(struct ata_link *link, unsigned int *classes, · 529 unmodified lines | |||
| 530 | unsigned long deadline); | 530 | unsigned long deadline); |
| 531 | typedef void (*ata_postreset_fn_t)(struct ata_link *link, unsigned int *classes); | 531 | typedef void (*ata_postreset_fn_t)(struct ata_link *link, unsigned int *classes); |
| 532 | 532 | ||
| 533 | extern struct device_attribute dev_attr_link_power_management_policy; | ||
| 534 | extern struct device_attribute dev_attr_unload_heads; | 533 | extern struct device_attribute dev_attr_unload_heads; |
| 534 | #ifdef CONFIG_SATA_HOST | ||
| 535 | extern struct device_attribute dev_attr_link_power_management_policy; | ||
| 535 | extern struct device_attribute dev_attr_ncq_prio_enable; | 536 | extern struct device_attribute dev_attr_ncq_prio_enable; |
| 536 | extern struct device_attribute dev_attr_em_message_type; | 537 | extern struct device_attribute dev_attr_em_message_type; |
| 537 | extern struct device_attribute dev_attr_em_message; | 538 | extern struct device_attribute dev_attr_em_message; |
| 538 | extern struct device_attribute dev_attr_sw_activity; | 539 | extern struct device_attribute dev_attr_sw_activity; |
| 540 | #endif | ||
| 539 | 541 | ||
| 540 | enum sw_activity { | 542 | enum sw_activity { |
| 541 | OFF, | 543 | OFF, |
| @@ -1371,7 +1373,6 @@ extern int ata_link_nr_enabled(struct ata_link *link); · 829 unmodified lines | |||
| 1371 | extern const struct ata_port_operations ata_base_port_ops; | 1373 | extern const struct ata_port_operations ata_base_port_ops; |
| 1372 | extern const struct ata_port_operations sata_port_ops; | 1374 | extern const struct ata_port_operations sata_port_ops; |
| 1373 | extern struct device_attribute *ata_common_sdev_attrs[]; | 1375 | extern struct device_attribute *ata_common_sdev_attrs[]; |
| 1374 | extern struct device_attribute *ata_ncq_sdev_attrs[]; | ||
| 1375 | 1376 | ||
| 1376 | /* | 1377 | /* |
| 1377 | * All sht initializers (BASE, PIO, BMDMA, NCQ) must be instantiated | 1378 | * All sht initializers (BASE, PIO, BMDMA, NCQ) must be instantiated |
| @@ -1399,10 +1400,14 @@ extern struct device_attribute *ata_ncq_sdev_attrs[]; · 21 unmodified lines | |||
| 1399 | __ATA_BASE_SHT(drv_name), \ | 1400 | __ATA_BASE_SHT(drv_name), \ |
| 1400 | .sdev_attrs = ata_common_sdev_attrs | 1401 | .sdev_attrs = ata_common_sdev_attrs |
| 1401 | 1402 | ||
| 1403 | #ifdef CONFIG_SATA_HOST | ||
| 1404 | extern struct device_attribute *ata_ncq_sdev_attrs[]; | ||
| 1405 | |||
| 1402 | #define ATA_NCQ_SHT(drv_name) \ | 1406 | #define ATA_NCQ_SHT(drv_name) \ |
| 1403 | __ATA_BASE_SHT(drv_name), \ | 1407 | __ATA_BASE_SHT(drv_name), \ |
| 1404 | .sdev_attrs = ata_ncq_sdev_attrs, \ | 1408 | .sdev_attrs = ata_ncq_sdev_attrs, \ |
| 1405 | .change_queue_depth = ata_scsi_change_queue_depth | 1409 | .change_queue_depth = ata_scsi_change_queue_depth |
| 1410 | #endif | ||
| 1406 | 1411 | ||
| 1407 | /* | 1412 | /* |
| 1408 | * PMP helpers | 1413 | * PMP helpers |