diff options
Diffstat (limited to 'drivers/s390/block/dasd_eckd.c')
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 692 |
1 files changed, 207 insertions, 485 deletions
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index e37bc1620d1..6e835c9fdfc 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * File...........: linux/drivers/s390/block/dasd_eckd.c | ||
2 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> | 3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> |
3 | * Horst Hummel <Horst.Hummel@de.ibm.com> | 4 | * Horst Hummel <Horst.Hummel@de.ibm.com> |
4 | * Carsten Otte <Cotte@de.ibm.com> | 5 | * Carsten Otte <Cotte@de.ibm.com> |
@@ -17,13 +18,12 @@ | |||
17 | #include <linux/hdreg.h> /* HDIO_GETGEO */ | 18 | #include <linux/hdreg.h> /* HDIO_GETGEO */ |
18 | #include <linux/bio.h> | 19 | #include <linux/bio.h> |
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
20 | #include <linux/compat.h> | ||
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | 22 | ||
23 | #include <asm/css_chars.h> | ||
24 | #include <asm/debug.h> | 23 | #include <asm/debug.h> |
25 | #include <asm/idals.h> | 24 | #include <asm/idals.h> |
26 | #include <asm/ebcdic.h> | 25 | #include <asm/ebcdic.h> |
26 | #include <asm/compat.h> | ||
27 | #include <asm/io.h> | 27 | #include <asm/io.h> |
28 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
29 | #include <asm/cio.h> | 29 | #include <asm/cio.h> |
@@ -32,6 +32,8 @@ | |||
32 | 32 | ||
33 | #include "dasd_int.h" | 33 | #include "dasd_int.h" |
34 | #include "dasd_eckd.h" | 34 | #include "dasd_eckd.h" |
35 | #include "../cio/chsc.h" | ||
36 | |||
35 | 37 | ||
36 | #ifdef PRINTK_HEADER | 38 | #ifdef PRINTK_HEADER |
37 | #undef PRINTK_HEADER | 39 | #undef PRINTK_HEADER |
@@ -139,10 +141,6 @@ dasd_eckd_set_online(struct ccw_device *cdev) | |||
139 | static const int sizes_trk0[] = { 28, 148, 84 }; | 141 | static const int sizes_trk0[] = { 28, 148, 84 }; |
140 | #define LABEL_SIZE 140 | 142 | #define LABEL_SIZE 140 |
141 | 143 | ||
142 | /* head and record addresses of count_area read in analysis ccw */ | ||
143 | static const int count_area_head[] = { 0, 0, 0, 0, 2 }; | ||
144 | static const int count_area_rec[] = { 1, 2, 3, 4, 1 }; | ||
145 | |||
146 | static inline unsigned int | 144 | static inline unsigned int |
147 | round_up_multiple(unsigned int no, unsigned int mult) | 145 | round_up_multiple(unsigned int no, unsigned int mult) |
148 | { | 146 | { |
@@ -215,7 +213,7 @@ check_XRC (struct ccw1 *de_ccw, | |||
215 | 213 | ||
216 | rc = get_sync_clock(&data->ep_sys_time); | 214 | rc = get_sync_clock(&data->ep_sys_time); |
217 | /* Ignore return code if sync clock is switched off. */ | 215 | /* Ignore return code if sync clock is switched off. */ |
218 | if (rc == -EOPNOTSUPP || rc == -EACCES) | 216 | if (rc == -ENOSYS || rc == -EACCES) |
219 | rc = 0; | 217 | rc = 0; |
220 | 218 | ||
221 | de_ccw->count = sizeof(struct DE_eckd_data); | 219 | de_ccw->count = sizeof(struct DE_eckd_data); |
@@ -326,7 +324,7 @@ static int check_XRC_on_prefix(struct PFX_eckd_data *pfxdata, | |||
326 | 324 | ||
327 | rc = get_sync_clock(&pfxdata->define_extent.ep_sys_time); | 325 | rc = get_sync_clock(&pfxdata->define_extent.ep_sys_time); |
328 | /* Ignore return code if sync clock is switched off. */ | 326 | /* Ignore return code if sync clock is switched off. */ |
329 | if (rc == -EOPNOTSUPP || rc == -EACCES) | 327 | if (rc == -ENOSYS || rc == -EACCES) |
330 | rc = 0; | 328 | rc = 0; |
331 | return rc; | 329 | return rc; |
332 | } | 330 | } |
@@ -754,13 +752,24 @@ dasd_eckd_cdl_reclen(int recid) | |||
754 | return sizes_trk0[recid]; | 752 | return sizes_trk0[recid]; |
755 | return LABEL_SIZE; | 753 | return LABEL_SIZE; |
756 | } | 754 | } |
757 | /* create unique id from private structure. */ | 755 | |
758 | static void create_uid(struct dasd_eckd_private *private) | 756 | /* |
757 | * Generate device unique id that specifies the physical device. | ||
758 | */ | ||
759 | static int dasd_eckd_generate_uid(struct dasd_device *device) | ||
759 | { | 760 | { |
760 | int count; | 761 | struct dasd_eckd_private *private; |
761 | struct dasd_uid *uid; | 762 | struct dasd_uid *uid; |
763 | int count; | ||
764 | unsigned long flags; | ||
762 | 765 | ||
766 | private = (struct dasd_eckd_private *) device->private; | ||
767 | if (!private) | ||
768 | return -ENODEV; | ||
769 | if (!private->ned || !private->gneq) | ||
770 | return -ENODEV; | ||
763 | uid = &private->uid; | 771 | uid = &private->uid; |
772 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
764 | memset(uid, 0, sizeof(struct dasd_uid)); | 773 | memset(uid, 0, sizeof(struct dasd_uid)); |
765 | memcpy(uid->vendor, private->ned->HDA_manufacturer, | 774 | memcpy(uid->vendor, private->ned->HDA_manufacturer, |
766 | sizeof(uid->vendor) - 1); | 775 | sizeof(uid->vendor) - 1); |
@@ -783,23 +792,6 @@ static void create_uid(struct dasd_eckd_private *private) | |||
783 | private->vdsneq->uit[count]); | 792 | private->vdsneq->uit[count]); |
784 | } | 793 | } |
785 | } | 794 | } |
786 | } | ||
787 | |||
788 | /* | ||
789 | * Generate device unique id that specifies the physical device. | ||
790 | */ | ||
791 | static int dasd_eckd_generate_uid(struct dasd_device *device) | ||
792 | { | ||
793 | struct dasd_eckd_private *private; | ||
794 | unsigned long flags; | ||
795 | |||
796 | private = (struct dasd_eckd_private *) device->private; | ||
797 | if (!private) | ||
798 | return -ENODEV; | ||
799 | if (!private->ned || !private->gneq) | ||
800 | return -ENODEV; | ||
801 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
802 | create_uid(private); | ||
803 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | 795 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); |
804 | return 0; | 796 | return 0; |
805 | } | 797 | } |
@@ -819,21 +811,6 @@ static int dasd_eckd_get_uid(struct dasd_device *device, struct dasd_uid *uid) | |||
819 | return -EINVAL; | 811 | return -EINVAL; |
820 | } | 812 | } |
821 | 813 | ||
822 | /* | ||
823 | * compare device UID with data of a given dasd_eckd_private structure | ||
824 | * return 0 for match | ||
825 | */ | ||
826 | static int dasd_eckd_compare_path_uid(struct dasd_device *device, | ||
827 | struct dasd_eckd_private *private) | ||
828 | { | ||
829 | struct dasd_uid device_uid; | ||
830 | |||
831 | create_uid(private); | ||
832 | dasd_eckd_get_uid(device, &device_uid); | ||
833 | |||
834 | return memcmp(&device_uid, &private->uid, sizeof(struct dasd_uid)); | ||
835 | } | ||
836 | |||
837 | static void dasd_eckd_fill_rcd_cqr(struct dasd_device *device, | 814 | static void dasd_eckd_fill_rcd_cqr(struct dasd_device *device, |
838 | struct dasd_ccw_req *cqr, | 815 | struct dasd_ccw_req *cqr, |
839 | __u8 *rcd_buffer, | 816 | __u8 *rcd_buffer, |
@@ -867,30 +844,6 @@ static void dasd_eckd_fill_rcd_cqr(struct dasd_device *device, | |||
867 | set_bit(DASD_CQR_VERIFY_PATH, &cqr->flags); | 844 | set_bit(DASD_CQR_VERIFY_PATH, &cqr->flags); |
868 | } | 845 | } |
869 | 846 | ||
870 | /* | ||
871 | * Wakeup helper for read_conf | ||
872 | * if the cqr is not done and needs some error recovery | ||
873 | * the buffer has to be re-initialized with the EBCDIC "V1.0" | ||
874 | * to show support for virtual device SNEQ | ||
875 | */ | ||
876 | static void read_conf_cb(struct dasd_ccw_req *cqr, void *data) | ||
877 | { | ||
878 | struct ccw1 *ccw; | ||
879 | __u8 *rcd_buffer; | ||
880 | |||
881 | if (cqr->status != DASD_CQR_DONE) { | ||
882 | ccw = cqr->cpaddr; | ||
883 | rcd_buffer = (__u8 *)((addr_t) ccw->cda); | ||
884 | memset(rcd_buffer, 0, sizeof(*rcd_buffer)); | ||
885 | |||
886 | rcd_buffer[0] = 0xE5; | ||
887 | rcd_buffer[1] = 0xF1; | ||
888 | rcd_buffer[2] = 0x4B; | ||
889 | rcd_buffer[3] = 0xF0; | ||
890 | } | ||
891 | dasd_wakeup_cb(cqr, data); | ||
892 | } | ||
893 | |||
894 | static int dasd_eckd_read_conf_immediately(struct dasd_device *device, | 847 | static int dasd_eckd_read_conf_immediately(struct dasd_device *device, |
895 | struct dasd_ccw_req *cqr, | 848 | struct dasd_ccw_req *cqr, |
896 | __u8 *rcd_buffer, | 849 | __u8 *rcd_buffer, |
@@ -910,7 +863,6 @@ static int dasd_eckd_read_conf_immediately(struct dasd_device *device, | |||
910 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); | 863 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); |
911 | set_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags); | 864 | set_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags); |
912 | cqr->retries = 5; | 865 | cqr->retries = 5; |
913 | cqr->callback = read_conf_cb; | ||
914 | rc = dasd_sleep_on_immediatly(cqr); | 866 | rc = dasd_sleep_on_immediatly(cqr); |
915 | return rc; | 867 | return rc; |
916 | } | 868 | } |
@@ -948,7 +900,6 @@ static int dasd_eckd_read_conf_lpm(struct dasd_device *device, | |||
948 | goto out_error; | 900 | goto out_error; |
949 | } | 901 | } |
950 | dasd_eckd_fill_rcd_cqr(device, cqr, rcd_buf, lpm); | 902 | dasd_eckd_fill_rcd_cqr(device, cqr, rcd_buf, lpm); |
951 | cqr->callback = read_conf_cb; | ||
952 | ret = dasd_sleep_on(cqr); | 903 | ret = dasd_sleep_on(cqr); |
953 | /* | 904 | /* |
954 | * on success we update the user input parms | 905 | * on success we update the user input parms |
@@ -1026,125 +977,62 @@ static int dasd_eckd_read_conf(struct dasd_device *device) | |||
1026 | { | 977 | { |
1027 | void *conf_data; | 978 | void *conf_data; |
1028 | int conf_len, conf_data_saved; | 979 | int conf_len, conf_data_saved; |
1029 | int rc, path_err; | 980 | int rc; |
1030 | __u8 lpm, opm; | 981 | __u8 lpm, opm; |
1031 | struct dasd_eckd_private *private, path_private; | 982 | struct dasd_eckd_private *private; |
1032 | struct dasd_path *path_data; | 983 | struct dasd_path *path_data; |
1033 | struct dasd_uid *uid; | ||
1034 | char print_path_uid[60], print_device_uid[60]; | ||
1035 | 984 | ||
1036 | private = (struct dasd_eckd_private *) device->private; | 985 | private = (struct dasd_eckd_private *) device->private; |
1037 | path_data = &device->path_data; | 986 | path_data = &device->path_data; |
1038 | opm = ccw_device_get_path_mask(device->cdev); | 987 | opm = ccw_device_get_path_mask(device->cdev); |
988 | lpm = 0x80; | ||
1039 | conf_data_saved = 0; | 989 | conf_data_saved = 0; |
1040 | path_err = 0; | ||
1041 | /* get configuration data per operational path */ | 990 | /* get configuration data per operational path */ |
1042 | for (lpm = 0x80; lpm; lpm>>= 1) { | 991 | for (lpm = 0x80; lpm; lpm>>= 1) { |
1043 | if (!(lpm & opm)) | 992 | if (lpm & opm) { |
1044 | continue; | 993 | rc = dasd_eckd_read_conf_lpm(device, &conf_data, |
1045 | rc = dasd_eckd_read_conf_lpm(device, &conf_data, | 994 | &conf_len, lpm); |
1046 | &conf_len, lpm); | 995 | if (rc && rc != -EOPNOTSUPP) { /* -EOPNOTSUPP is ok */ |
1047 | if (rc && rc != -EOPNOTSUPP) { /* -EOPNOTSUPP is ok */ | 996 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, |
1048 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, | 997 | "Read configuration data returned " |
1049 | "Read configuration data returned " | 998 | "error %d", rc); |
1050 | "error %d", rc); | 999 | return rc; |
1051 | return rc; | ||
1052 | } | ||
1053 | if (conf_data == NULL) { | ||
1054 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", | ||
1055 | "No configuration data " | ||
1056 | "retrieved"); | ||
1057 | /* no further analysis possible */ | ||
1058 | path_data->opm |= lpm; | ||
1059 | continue; /* no error */ | ||
1060 | } | ||
1061 | /* save first valid configuration data */ | ||
1062 | if (!conf_data_saved) { | ||
1063 | kfree(private->conf_data); | ||
1064 | private->conf_data = conf_data; | ||
1065 | private->conf_len = conf_len; | ||
1066 | if (dasd_eckd_identify_conf_parts(private)) { | ||
1067 | private->conf_data = NULL; | ||
1068 | private->conf_len = 0; | ||
1069 | kfree(conf_data); | ||
1070 | continue; | ||
1071 | } | 1000 | } |
1072 | /* | 1001 | if (conf_data == NULL) { |
1073 | * build device UID that other path data | 1002 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", |
1074 | * can be compared to it | 1003 | "No configuration data " |
1075 | */ | 1004 | "retrieved"); |
1076 | dasd_eckd_generate_uid(device); | 1005 | /* no further analysis possible */ |
1077 | conf_data_saved++; | 1006 | path_data->opm |= lpm; |
1078 | } else { | 1007 | continue; /* no error */ |
1079 | path_private.conf_data = conf_data; | ||
1080 | path_private.conf_len = DASD_ECKD_RCD_DATA_SIZE; | ||
1081 | if (dasd_eckd_identify_conf_parts( | ||
1082 | &path_private)) { | ||
1083 | path_private.conf_data = NULL; | ||
1084 | path_private.conf_len = 0; | ||
1085 | kfree(conf_data); | ||
1086 | continue; | ||
1087 | } | 1008 | } |
1088 | 1009 | /* save first valid configuration data */ | |
1089 | if (dasd_eckd_compare_path_uid( | 1010 | if (!conf_data_saved) { |
1090 | device, &path_private)) { | 1011 | kfree(private->conf_data); |
1091 | uid = &path_private.uid; | 1012 | private->conf_data = conf_data; |
1092 | if (strlen(uid->vduit) > 0) | 1013 | private->conf_len = conf_len; |
1093 | snprintf(print_path_uid, | 1014 | if (dasd_eckd_identify_conf_parts(private)) { |
1094 | sizeof(print_path_uid), | 1015 | private->conf_data = NULL; |
1095 | "%s.%s.%04x.%02x.%s", | 1016 | private->conf_len = 0; |
1096 | uid->vendor, uid->serial, | 1017 | kfree(conf_data); |
1097 | uid->ssid, uid->real_unit_addr, | 1018 | continue; |
1098 | uid->vduit); | 1019 | } |
1099 | else | 1020 | conf_data_saved++; |
1100 | snprintf(print_path_uid, | ||
1101 | sizeof(print_path_uid), | ||
1102 | "%s.%s.%04x.%02x", | ||
1103 | uid->vendor, uid->serial, | ||
1104 | uid->ssid, | ||
1105 | uid->real_unit_addr); | ||
1106 | uid = &private->uid; | ||
1107 | if (strlen(uid->vduit) > 0) | ||
1108 | snprintf(print_device_uid, | ||
1109 | sizeof(print_device_uid), | ||
1110 | "%s.%s.%04x.%02x.%s", | ||
1111 | uid->vendor, uid->serial, | ||
1112 | uid->ssid, uid->real_unit_addr, | ||
1113 | uid->vduit); | ||
1114 | else | ||
1115 | snprintf(print_device_uid, | ||
1116 | sizeof(print_device_uid), | ||
1117 | "%s.%s.%04x.%02x", | ||
1118 | uid->vendor, uid->serial, | ||
1119 | uid->ssid, | ||
1120 | uid->real_unit_addr); | ||
1121 | dev_err(&device->cdev->dev, | ||
1122 | "Not all channel paths lead to " | ||
1123 | "the same device, path %02X leads to " | ||
1124 | "device %s instead of %s\n", lpm, | ||
1125 | print_path_uid, print_device_uid); | ||
1126 | path_err = -EINVAL; | ||
1127 | continue; | ||
1128 | } | 1021 | } |
1129 | 1022 | switch (dasd_eckd_path_access(conf_data, conf_len)) { | |
1130 | path_private.conf_data = NULL; | 1023 | case 0x02: |
1131 | path_private.conf_len = 0; | 1024 | path_data->npm |= lpm; |
1132 | } | 1025 | break; |
1133 | switch (dasd_eckd_path_access(conf_data, conf_len)) { | 1026 | case 0x03: |
1134 | case 0x02: | 1027 | path_data->ppm |= lpm; |
1135 | path_data->npm |= lpm; | 1028 | break; |
1136 | break; | 1029 | } |
1137 | case 0x03: | 1030 | path_data->opm |= lpm; |
1138 | path_data->ppm |= lpm; | 1031 | if (conf_data != private->conf_data) |
1139 | break; | 1032 | kfree(conf_data); |
1140 | } | 1033 | } |
1141 | path_data->opm |= lpm; | ||
1142 | |||
1143 | if (conf_data != private->conf_data) | ||
1144 | kfree(conf_data); | ||
1145 | } | 1034 | } |
1146 | 1035 | return 0; | |
1147 | return path_err; | ||
1148 | } | 1036 | } |
1149 | 1037 | ||
1150 | static int verify_fcx_max_data(struct dasd_device *device, __u8 lpm) | 1038 | static int verify_fcx_max_data(struct dasd_device *device, __u8 lpm) |
@@ -1176,200 +1064,80 @@ static int verify_fcx_max_data(struct dasd_device *device, __u8 lpm) | |||
1176 | return 0; | 1064 | return 0; |
1177 | } | 1065 | } |
1178 | 1066 | ||
1179 | static int rebuild_device_uid(struct dasd_device *device, | ||
1180 | struct path_verification_work_data *data) | ||
1181 | { | ||
1182 | struct dasd_eckd_private *private; | ||
1183 | struct dasd_path *path_data; | ||
1184 | __u8 lpm, opm; | ||
1185 | int rc; | ||
1186 | |||
1187 | rc = -ENODEV; | ||
1188 | private = (struct dasd_eckd_private *) device->private; | ||
1189 | path_data = &device->path_data; | ||
1190 | opm = device->path_data.opm; | ||
1191 | |||
1192 | for (lpm = 0x80; lpm; lpm >>= 1) { | ||
1193 | if (!(lpm & opm)) | ||
1194 | continue; | ||
1195 | memset(&data->rcd_buffer, 0, sizeof(data->rcd_buffer)); | ||
1196 | memset(&data->cqr, 0, sizeof(data->cqr)); | ||
1197 | data->cqr.cpaddr = &data->ccw; | ||
1198 | rc = dasd_eckd_read_conf_immediately(device, &data->cqr, | ||
1199 | data->rcd_buffer, | ||
1200 | lpm); | ||
1201 | |||
1202 | if (rc) { | ||
1203 | if (rc == -EOPNOTSUPP) /* -EOPNOTSUPP is ok */ | ||
1204 | continue; | ||
1205 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, | ||
1206 | "Read configuration data " | ||
1207 | "returned error %d", rc); | ||
1208 | break; | ||
1209 | } | ||
1210 | memcpy(private->conf_data, data->rcd_buffer, | ||
1211 | DASD_ECKD_RCD_DATA_SIZE); | ||
1212 | if (dasd_eckd_identify_conf_parts(private)) { | ||
1213 | rc = -ENODEV; | ||
1214 | } else /* first valid path is enough */ | ||
1215 | break; | ||
1216 | } | ||
1217 | |||
1218 | if (!rc) | ||
1219 | rc = dasd_eckd_generate_uid(device); | ||
1220 | |||
1221 | return rc; | ||
1222 | } | ||
1223 | |||
1224 | static void do_path_verification_work(struct work_struct *work) | 1067 | static void do_path_verification_work(struct work_struct *work) |
1225 | { | 1068 | { |
1226 | struct path_verification_work_data *data; | 1069 | struct path_verification_work_data *data; |
1227 | struct dasd_device *device; | 1070 | struct dasd_device *device; |
1228 | struct dasd_eckd_private path_private; | ||
1229 | struct dasd_uid *uid; | ||
1230 | __u8 path_rcd_buf[DASD_ECKD_RCD_DATA_SIZE]; | ||
1231 | __u8 lpm, opm, npm, ppm, epm; | 1071 | __u8 lpm, opm, npm, ppm, epm; |
1232 | unsigned long flags; | 1072 | unsigned long flags; |
1233 | char print_uid[60]; | ||
1234 | int rc; | 1073 | int rc; |
1235 | 1074 | ||
1236 | data = container_of(work, struct path_verification_work_data, worker); | 1075 | data = container_of(work, struct path_verification_work_data, worker); |
1237 | device = data->device; | 1076 | device = data->device; |
1238 | 1077 | ||
1239 | /* delay path verification until device was resumed */ | ||
1240 | if (test_bit(DASD_FLAG_SUSPENDED, &device->flags)) { | ||
1241 | schedule_work(work); | ||
1242 | return; | ||
1243 | } | ||
1244 | |||
1245 | opm = 0; | 1078 | opm = 0; |
1246 | npm = 0; | 1079 | npm = 0; |
1247 | ppm = 0; | 1080 | ppm = 0; |
1248 | epm = 0; | 1081 | epm = 0; |
1249 | for (lpm = 0x80; lpm; lpm >>= 1) { | 1082 | for (lpm = 0x80; lpm; lpm >>= 1) { |
1250 | if (!(lpm & data->tbvpm)) | 1083 | if (lpm & data->tbvpm) { |
1251 | continue; | 1084 | memset(data->rcd_buffer, 0, sizeof(data->rcd_buffer)); |
1252 | memset(&data->rcd_buffer, 0, sizeof(data->rcd_buffer)); | 1085 | memset(&data->cqr, 0, sizeof(data->cqr)); |
1253 | memset(&data->cqr, 0, sizeof(data->cqr)); | 1086 | data->cqr.cpaddr = &data->ccw; |
1254 | data->cqr.cpaddr = &data->ccw; | 1087 | rc = dasd_eckd_read_conf_immediately(device, &data->cqr, |
1255 | rc = dasd_eckd_read_conf_immediately(device, &data->cqr, | 1088 | data->rcd_buffer, |
1256 | data->rcd_buffer, | 1089 | lpm); |
1257 | lpm); | 1090 | if (!rc) { |
1258 | if (!rc) { | 1091 | switch (dasd_eckd_path_access(data->rcd_buffer, |
1259 | switch (dasd_eckd_path_access(data->rcd_buffer, | 1092 | DASD_ECKD_RCD_DATA_SIZE)) { |
1260 | DASD_ECKD_RCD_DATA_SIZE) | 1093 | case 0x02: |
1261 | ) { | 1094 | npm |= lpm; |
1262 | case 0x02: | 1095 | break; |
1263 | npm |= lpm; | 1096 | case 0x03: |
1264 | break; | 1097 | ppm |= lpm; |
1265 | case 0x03: | 1098 | break; |
1266 | ppm |= lpm; | 1099 | } |
1267 | break; | 1100 | opm |= lpm; |
1268 | } | 1101 | } else if (rc == -EOPNOTSUPP) { |
1269 | opm |= lpm; | 1102 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", |
1270 | } else if (rc == -EOPNOTSUPP) { | 1103 | "path verification: No configuration " |
1271 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", | 1104 | "data retrieved"); |
1272 | "path verification: No configuration " | 1105 | opm |= lpm; |
1273 | "data retrieved"); | 1106 | } else if (rc == -EAGAIN) { |
1274 | opm |= lpm; | 1107 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", |
1275 | } else if (rc == -EAGAIN) { | ||
1276 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", | ||
1277 | "path verification: device is stopped," | 1108 | "path verification: device is stopped," |
1278 | " try again later"); | 1109 | " try again later"); |
1279 | epm |= lpm; | 1110 | epm |= lpm; |
1280 | } else { | 1111 | } else { |
1281 | dev_warn(&device->cdev->dev, | 1112 | dev_warn(&device->cdev->dev, |
1282 | "Reading device feature codes failed " | 1113 | "Reading device feature codes failed " |
1283 | "(rc=%d) for new path %x\n", rc, lpm); | 1114 | "(rc=%d) for new path %x\n", rc, lpm); |
1284 | continue; | 1115 | continue; |
1285 | } | 1116 | } |
1286 | if (verify_fcx_max_data(device, lpm)) { | 1117 | if (verify_fcx_max_data(device, lpm)) { |
1287 | opm &= ~lpm; | ||
1288 | npm &= ~lpm; | ||
1289 | ppm &= ~lpm; | ||
1290 | continue; | ||
1291 | } | ||
1292 | |||
1293 | /* | ||
1294 | * save conf_data for comparison after | ||
1295 | * rebuild_device_uid may have changed | ||
1296 | * the original data | ||
1297 | */ | ||
1298 | memcpy(&path_rcd_buf, data->rcd_buffer, | ||
1299 | DASD_ECKD_RCD_DATA_SIZE); | ||
1300 | path_private.conf_data = (void *) &path_rcd_buf; | ||
1301 | path_private.conf_len = DASD_ECKD_RCD_DATA_SIZE; | ||
1302 | if (dasd_eckd_identify_conf_parts(&path_private)) { | ||
1303 | path_private.conf_data = NULL; | ||
1304 | path_private.conf_len = 0; | ||
1305 | continue; | ||
1306 | } | ||
1307 | |||
1308 | /* | ||
1309 | * compare path UID with device UID only if at least | ||
1310 | * one valid path is left | ||
1311 | * in other case the device UID may have changed and | ||
1312 | * the first working path UID will be used as device UID | ||
1313 | */ | ||
1314 | if (device->path_data.opm && | ||
1315 | dasd_eckd_compare_path_uid(device, &path_private)) { | ||
1316 | /* | ||
1317 | * the comparison was not successful | ||
1318 | * rebuild the device UID with at least one | ||
1319 | * known path in case a z/VM hyperswap command | ||
1320 | * has changed the device | ||
1321 | * | ||
1322 | * after this compare again | ||
1323 | * | ||
1324 | * if either the rebuild or the recompare fails | ||
1325 | * the path can not be used | ||
1326 | */ | ||
1327 | if (rebuild_device_uid(device, data) || | ||
1328 | dasd_eckd_compare_path_uid( | ||
1329 | device, &path_private)) { | ||
1330 | uid = &path_private.uid; | ||
1331 | if (strlen(uid->vduit) > 0) | ||
1332 | snprintf(print_uid, sizeof(print_uid), | ||
1333 | "%s.%s.%04x.%02x.%s", | ||
1334 | uid->vendor, uid->serial, | ||
1335 | uid->ssid, uid->real_unit_addr, | ||
1336 | uid->vduit); | ||
1337 | else | ||
1338 | snprintf(print_uid, sizeof(print_uid), | ||
1339 | "%s.%s.%04x.%02x", | ||
1340 | uid->vendor, uid->serial, | ||
1341 | uid->ssid, | ||
1342 | uid->real_unit_addr); | ||
1343 | dev_err(&device->cdev->dev, | ||
1344 | "The newly added channel path %02X " | ||
1345 | "will not be used because it leads " | ||
1346 | "to a different device %s\n", | ||
1347 | lpm, print_uid); | ||
1348 | opm &= ~lpm; | 1118 | opm &= ~lpm; |
1349 | npm &= ~lpm; | 1119 | npm &= ~lpm; |
1350 | ppm &= ~lpm; | 1120 | ppm &= ~lpm; |
1351 | continue; | ||
1352 | } | 1121 | } |
1353 | } | 1122 | } |
1354 | |||
1355 | /* | ||
1356 | * There is a small chance that a path is lost again between | ||
1357 | * above path verification and the following modification of | ||
1358 | * the device opm mask. We could avoid that race here by using | ||
1359 | * yet another path mask, but we rather deal with this unlikely | ||
1360 | * situation in dasd_start_IO. | ||
1361 | */ | ||
1362 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
1363 | if (!device->path_data.opm && opm) { | ||
1364 | device->path_data.opm = opm; | ||
1365 | dasd_generic_path_operational(device); | ||
1366 | } else | ||
1367 | device->path_data.opm |= opm; | ||
1368 | device->path_data.npm |= npm; | ||
1369 | device->path_data.ppm |= ppm; | ||
1370 | device->path_data.tbvpm |= epm; | ||
1371 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
1372 | } | 1123 | } |
1124 | /* | ||
1125 | * There is a small chance that a path is lost again between | ||
1126 | * above path verification and the following modification of | ||
1127 | * the device opm mask. We could avoid that race here by using | ||
1128 | * yet another path mask, but we rather deal with this unlikely | ||
1129 | * situation in dasd_start_IO. | ||
1130 | */ | ||
1131 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
1132 | if (!device->path_data.opm && opm) { | ||
1133 | device->path_data.opm = opm; | ||
1134 | dasd_generic_path_operational(device); | ||
1135 | } else | ||
1136 | device->path_data.opm |= opm; | ||
1137 | device->path_data.npm |= npm; | ||
1138 | device->path_data.ppm |= ppm; | ||
1139 | device->path_data.tbvpm |= epm; | ||
1140 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
1373 | 1141 | ||
1374 | dasd_put_device(device); | 1142 | dasd_put_device(device); |
1375 | if (data->isglobal) | 1143 | if (data->isglobal) |
@@ -1512,8 +1280,7 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device, | |||
1512 | * call might change behaviour of DASD devices. | 1280 | * call might change behaviour of DASD devices. |
1513 | */ | 1281 | */ |
1514 | static int | 1282 | static int |
1515 | dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav, | 1283 | dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav) |
1516 | unsigned long flags) | ||
1517 | { | 1284 | { |
1518 | struct dasd_ccw_req *cqr; | 1285 | struct dasd_ccw_req *cqr; |
1519 | int rc; | 1286 | int rc; |
@@ -1522,19 +1289,10 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav, | |||
1522 | if (IS_ERR(cqr)) | 1289 | if (IS_ERR(cqr)) |
1523 | return PTR_ERR(cqr); | 1290 | return PTR_ERR(cqr); |
1524 | 1291 | ||
1525 | /* | ||
1526 | * set flags e.g. turn on failfast, to prevent blocking | ||
1527 | * the calling function should handle failed requests | ||
1528 | */ | ||
1529 | cqr->flags |= flags; | ||
1530 | |||
1531 | rc = dasd_sleep_on(cqr); | 1292 | rc = dasd_sleep_on(cqr); |
1532 | if (!rc) | 1293 | if (!rc) |
1533 | /* trigger CIO to reprobe devices */ | 1294 | /* trigger CIO to reprobe devices */ |
1534 | css_schedule_reprobe(); | 1295 | css_schedule_reprobe(); |
1535 | else if (cqr->intrc == -EAGAIN) | ||
1536 | rc = -EAGAIN; | ||
1537 | |||
1538 | dasd_sfree_request(cqr, cqr->memdev); | 1296 | dasd_sfree_request(cqr, cqr->memdev); |
1539 | return rc; | 1297 | return rc; |
1540 | } | 1298 | } |
@@ -1542,58 +1300,23 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav, | |||
1542 | /* | 1300 | /* |
1543 | * Valide storage server of current device. | 1301 | * Valide storage server of current device. |
1544 | */ | 1302 | */ |
1545 | static int dasd_eckd_validate_server(struct dasd_device *device, | 1303 | static void dasd_eckd_validate_server(struct dasd_device *device) |
1546 | unsigned long flags) | ||
1547 | { | 1304 | { |
1548 | int rc; | 1305 | int rc; |
1549 | struct dasd_eckd_private *private; | 1306 | struct dasd_eckd_private *private; |
1550 | int enable_pav; | 1307 | int enable_pav; |
1551 | 1308 | ||
1552 | private = (struct dasd_eckd_private *) device->private; | ||
1553 | if (private->uid.type == UA_BASE_PAV_ALIAS || | ||
1554 | private->uid.type == UA_HYPER_PAV_ALIAS) | ||
1555 | return 0; | ||
1556 | if (dasd_nopav || MACHINE_IS_VM) | 1309 | if (dasd_nopav || MACHINE_IS_VM) |
1557 | enable_pav = 0; | 1310 | enable_pav = 0; |
1558 | else | 1311 | else |
1559 | enable_pav = 1; | 1312 | enable_pav = 1; |
1560 | rc = dasd_eckd_psf_ssc(device, enable_pav, flags); | 1313 | rc = dasd_eckd_psf_ssc(device, enable_pav); |
1561 | 1314 | ||
1562 | /* may be requested feature is not available on server, | 1315 | /* may be requested feature is not available on server, |
1563 | * therefore just report error and go ahead */ | 1316 | * therefore just report error and go ahead */ |
1317 | private = (struct dasd_eckd_private *) device->private; | ||
1564 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x " | 1318 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x " |
1565 | "returned rc=%d", private->uid.ssid, rc); | 1319 | "returned rc=%d", private->uid.ssid, rc); |
1566 | return rc; | ||
1567 | } | ||
1568 | |||
1569 | /* | ||
1570 | * worker to do a validate server in case of a lost pathgroup | ||
1571 | */ | ||
1572 | static void dasd_eckd_do_validate_server(struct work_struct *work) | ||
1573 | { | ||
1574 | struct dasd_device *device = container_of(work, struct dasd_device, | ||
1575 | kick_validate); | ||
1576 | if (dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST) | ||
1577 | == -EAGAIN) { | ||
1578 | /* schedule worker again if failed */ | ||
1579 | schedule_work(&device->kick_validate); | ||
1580 | return; | ||
1581 | } | ||
1582 | |||
1583 | dasd_put_device(device); | ||
1584 | } | ||
1585 | |||
1586 | static void dasd_eckd_kick_validate_server(struct dasd_device *device) | ||
1587 | { | ||
1588 | dasd_get_device(device); | ||
1589 | /* exit if device not online or in offline processing */ | ||
1590 | if (test_bit(DASD_FLAG_OFFLINE, &device->flags) || | ||
1591 | device->state < DASD_STATE_ONLINE) { | ||
1592 | dasd_put_device(device); | ||
1593 | return; | ||
1594 | } | ||
1595 | /* queue call to do_validate_server to the kernel event daemon. */ | ||
1596 | schedule_work(&device->kick_validate); | ||
1597 | } | 1320 | } |
1598 | 1321 | ||
1599 | static u32 get_fcx_max_data(struct dasd_device *device) | 1322 | static u32 get_fcx_max_data(struct dasd_device *device) |
@@ -1637,13 +1360,10 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
1637 | struct dasd_eckd_private *private; | 1360 | struct dasd_eckd_private *private; |
1638 | struct dasd_block *block; | 1361 | struct dasd_block *block; |
1639 | struct dasd_uid temp_uid; | 1362 | struct dasd_uid temp_uid; |
1640 | int rc, i; | 1363 | int is_known, rc, i; |
1641 | int readonly; | 1364 | int readonly; |
1642 | unsigned long value; | 1365 | unsigned long value; |
1643 | 1366 | ||
1644 | /* setup work queue for validate server*/ | ||
1645 | INIT_WORK(&device->kick_validate, dasd_eckd_do_validate_server); | ||
1646 | |||
1647 | if (!ccw_device_is_pathgroup(device->cdev)) { | 1367 | if (!ccw_device_is_pathgroup(device->cdev)) { |
1648 | dev_warn(&device->cdev->dev, | 1368 | dev_warn(&device->cdev->dev, |
1649 | "A channel path group could not be established\n"); | 1369 | "A channel path group could not be established\n"); |
@@ -1689,6 +1409,11 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
1689 | device->default_expires = value; | 1409 | device->default_expires = value; |
1690 | } | 1410 | } |
1691 | 1411 | ||
1412 | /* Generate device unique id */ | ||
1413 | rc = dasd_eckd_generate_uid(device); | ||
1414 | if (rc) | ||
1415 | goto out_err1; | ||
1416 | |||
1692 | dasd_eckd_get_uid(device, &temp_uid); | 1417 | dasd_eckd_get_uid(device, &temp_uid); |
1693 | if (temp_uid.type == UA_BASE_DEVICE) { | 1418 | if (temp_uid.type == UA_BASE_DEVICE) { |
1694 | block = dasd_alloc_block(); | 1419 | block = dasd_alloc_block(); |
@@ -1703,12 +1428,22 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
1703 | block->base = device; | 1428 | block->base = device; |
1704 | } | 1429 | } |
1705 | 1430 | ||
1706 | /* register lcu with alias handling, enable PAV */ | 1431 | /* register lcu with alias handling, enable PAV if this is a new lcu */ |
1707 | rc = dasd_alias_make_device_known_to_lcu(device); | 1432 | is_known = dasd_alias_make_device_known_to_lcu(device); |
1708 | if (rc) | 1433 | if (is_known < 0) { |
1434 | rc = is_known; | ||
1709 | goto out_err2; | 1435 | goto out_err2; |
1710 | 1436 | } | |
1711 | dasd_eckd_validate_server(device, 0); | 1437 | /* |
1438 | * dasd_eckd_validate_server is done on the first device that | ||
1439 | * is found for an LCU. All later other devices have to wait | ||
1440 | * for it, so they will read the correct feature codes. | ||
1441 | */ | ||
1442 | if (!is_known) { | ||
1443 | dasd_eckd_validate_server(device); | ||
1444 | dasd_alias_lcu_setup_complete(device); | ||
1445 | } else | ||
1446 | dasd_alias_wait_for_lcu_setup(device); | ||
1712 | 1447 | ||
1713 | /* device may report different configuration data after LCU setup */ | 1448 | /* device may report different configuration data after LCU setup */ |
1714 | rc = dasd_eckd_read_conf(device); | 1449 | rc = dasd_eckd_read_conf(device); |
@@ -1945,10 +1680,7 @@ static int dasd_eckd_end_analysis(struct dasd_block *block) | |||
1945 | count_area = NULL; | 1680 | count_area = NULL; |
1946 | for (i = 0; i < 3; i++) { | 1681 | for (i = 0; i < 3; i++) { |
1947 | if (private->count_area[i].kl != 4 || | 1682 | if (private->count_area[i].kl != 4 || |
1948 | private->count_area[i].dl != dasd_eckd_cdl_reclen(i) - 4 || | 1683 | private->count_area[i].dl != dasd_eckd_cdl_reclen(i) - 4) { |
1949 | private->count_area[i].cyl != 0 || | ||
1950 | private->count_area[i].head != count_area_head[i] || | ||
1951 | private->count_area[i].record != count_area_rec[i]) { | ||
1952 | private->uses_cdl = 0; | 1684 | private->uses_cdl = 0; |
1953 | break; | 1685 | break; |
1954 | } | 1686 | } |
@@ -1960,10 +1692,7 @@ static int dasd_eckd_end_analysis(struct dasd_block *block) | |||
1960 | for (i = 0; i < 5; i++) { | 1692 | for (i = 0; i < 5; i++) { |
1961 | if ((private->count_area[i].kl != 0) || | 1693 | if ((private->count_area[i].kl != 0) || |
1962 | (private->count_area[i].dl != | 1694 | (private->count_area[i].dl != |
1963 | private->count_area[0].dl) || | 1695 | private->count_area[0].dl)) |
1964 | private->count_area[i].cyl != 0 || | ||
1965 | private->count_area[i].head != count_area_head[i] || | ||
1966 | private->count_area[i].record != count_area_rec[i]) | ||
1967 | break; | 1696 | break; |
1968 | } | 1697 | } |
1969 | if (i == 5) | 1698 | if (i == 5) |
@@ -2027,7 +1756,6 @@ static int dasd_eckd_ready_to_online(struct dasd_device *device) | |||
2027 | static int dasd_eckd_online_to_ready(struct dasd_device *device) | 1756 | static int dasd_eckd_online_to_ready(struct dasd_device *device) |
2028 | { | 1757 | { |
2029 | cancel_work_sync(&device->reload_device); | 1758 | cancel_work_sync(&device->reload_device); |
2030 | cancel_work_sync(&device->kick_validate); | ||
2031 | return dasd_alias_remove_device(device); | 1759 | return dasd_alias_remove_device(device); |
2032 | }; | 1760 | }; |
2033 | 1761 | ||
@@ -2293,14 +2021,9 @@ static void dasd_eckd_check_for_device_change(struct dasd_device *device, | |||
2293 | /* first of all check for state change pending interrupt */ | 2021 | /* first of all check for state change pending interrupt */ |
2294 | mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; | 2022 | mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; |
2295 | if ((scsw_dstat(&irb->scsw) & mask) == mask) { | 2023 | if ((scsw_dstat(&irb->scsw) & mask) == mask) { |
2296 | /* | 2024 | /* for alias only and not in offline processing*/ |
2297 | * for alias only, not in offline processing | ||
2298 | * and only if not suspended | ||
2299 | */ | ||
2300 | if (!device->block && private->lcu && | 2025 | if (!device->block && private->lcu && |
2301 | device->state == DASD_STATE_ONLINE && | 2026 | !test_bit(DASD_FLAG_OFFLINE, &device->flags)) { |
2302 | !test_bit(DASD_FLAG_OFFLINE, &device->flags) && | ||
2303 | !test_bit(DASD_FLAG_SUSPENDED, &device->flags)) { | ||
2304 | /* | 2027 | /* |
2305 | * the state change could be caused by an alias | 2028 | * the state change could be caused by an alias |
2306 | * reassignment remove device from alias handling | 2029 | * reassignment remove device from alias handling |
@@ -2447,7 +2170,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single( | |||
2447 | sizeof(struct PFX_eckd_data)); | 2170 | sizeof(struct PFX_eckd_data)); |
2448 | } else { | 2171 | } else { |
2449 | if (define_extent(ccw++, cqr->data, first_trk, | 2172 | if (define_extent(ccw++, cqr->data, first_trk, |
2450 | last_trk, cmd, basedev) == -EAGAIN) { | 2173 | last_trk, cmd, startdev) == -EAGAIN) { |
2451 | /* Clock not in sync and XRC is enabled. | 2174 | /* Clock not in sync and XRC is enabled. |
2452 | * Try again later. | 2175 | * Try again later. |
2453 | */ | 2176 | */ |
@@ -2627,7 +2350,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track( | |||
2627 | new_track = 1; | 2350 | new_track = 1; |
2628 | end_idaw = 0; | 2351 | end_idaw = 0; |
2629 | len_to_track_end = 0; | 2352 | len_to_track_end = 0; |
2630 | idaw_dst = NULL; | 2353 | idaw_dst = 0; |
2631 | idaw_len = 0; | 2354 | idaw_len = 0; |
2632 | rq_for_each_segment(bv, req, iter) { | 2355 | rq_for_each_segment(bv, req, iter) { |
2633 | dst = page_address(bv->bv_page) + bv->bv_offset; | 2356 | dst = page_address(bv->bv_page) + bv->bv_offset; |
@@ -2689,7 +2412,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track( | |||
2689 | if (end_idaw) { | 2412 | if (end_idaw) { |
2690 | idaws = idal_create_words(idaws, idaw_dst, | 2413 | idaws = idal_create_words(idaws, idaw_dst, |
2691 | idaw_len); | 2414 | idaw_len); |
2692 | idaw_dst = NULL; | 2415 | idaw_dst = 0; |
2693 | idaw_len = 0; | 2416 | idaw_len = 0; |
2694 | end_idaw = 0; | 2417 | end_idaw = 0; |
2695 | } | 2418 | } |
@@ -2872,7 +2595,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( | |||
2872 | sector_t recid, trkid; | 2595 | sector_t recid, trkid; |
2873 | unsigned int offs; | 2596 | unsigned int offs; |
2874 | unsigned int count, count_to_trk_end; | 2597 | unsigned int count, count_to_trk_end; |
2875 | int ret; | ||
2876 | 2598 | ||
2877 | basedev = block->base; | 2599 | basedev = block->base; |
2878 | if (rq_data_dir(req) == READ) { | 2600 | if (rq_data_dir(req) == READ) { |
@@ -2913,8 +2635,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( | |||
2913 | 2635 | ||
2914 | itcw = itcw_init(cqr->data, itcw_size, itcw_op, 0, ctidaw, 0); | 2636 | itcw = itcw_init(cqr->data, itcw_size, itcw_op, 0, ctidaw, 0); |
2915 | if (IS_ERR(itcw)) { | 2637 | if (IS_ERR(itcw)) { |
2916 | ret = -EINVAL; | 2638 | dasd_sfree_request(cqr, startdev); |
2917 | goto out_error; | 2639 | return ERR_PTR(-EINVAL); |
2918 | } | 2640 | } |
2919 | cqr->cpaddr = itcw_get_tcw(itcw); | 2641 | cqr->cpaddr = itcw_get_tcw(itcw); |
2920 | if (prepare_itcw(itcw, first_trk, last_trk, | 2642 | if (prepare_itcw(itcw, first_trk, last_trk, |
@@ -2926,8 +2648,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( | |||
2926 | /* Clock not in sync and XRC is enabled. | 2648 | /* Clock not in sync and XRC is enabled. |
2927 | * Try again later. | 2649 | * Try again later. |
2928 | */ | 2650 | */ |
2929 | ret = -EAGAIN; | 2651 | dasd_sfree_request(cqr, startdev); |
2930 | goto out_error; | 2652 | return ERR_PTR(-EAGAIN); |
2931 | } | 2653 | } |
2932 | len_to_track_end = 0; | 2654 | len_to_track_end = 0; |
2933 | /* | 2655 | /* |
@@ -2966,10 +2688,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( | |||
2966 | tidaw_flags = 0; | 2688 | tidaw_flags = 0; |
2967 | last_tidaw = itcw_add_tidaw(itcw, tidaw_flags, | 2689 | last_tidaw = itcw_add_tidaw(itcw, tidaw_flags, |
2968 | dst, part_len); | 2690 | dst, part_len); |
2969 | if (IS_ERR(last_tidaw)) { | 2691 | if (IS_ERR(last_tidaw)) |
2970 | ret = -EINVAL; | 2692 | return ERR_PTR(-EINVAL); |
2971 | goto out_error; | ||
2972 | } | ||
2973 | dst += part_len; | 2693 | dst += part_len; |
2974 | } | 2694 | } |
2975 | } | 2695 | } |
@@ -2978,10 +2698,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( | |||
2978 | dst = page_address(bv->bv_page) + bv->bv_offset; | 2698 | dst = page_address(bv->bv_page) + bv->bv_offset; |
2979 | last_tidaw = itcw_add_tidaw(itcw, 0x00, | 2699 | last_tidaw = itcw_add_tidaw(itcw, 0x00, |
2980 | dst, bv->bv_len); | 2700 | dst, bv->bv_len); |
2981 | if (IS_ERR(last_tidaw)) { | 2701 | if (IS_ERR(last_tidaw)) |
2982 | ret = -EINVAL; | 2702 | return ERR_PTR(-EINVAL); |
2983 | goto out_error; | ||
2984 | } | ||
2985 | } | 2703 | } |
2986 | } | 2704 | } |
2987 | last_tidaw->flags |= TIDAW_FLAGS_LAST; | 2705 | last_tidaw->flags |= TIDAW_FLAGS_LAST; |
@@ -3001,9 +2719,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( | |||
3001 | cqr->buildclk = get_clock(); | 2719 | cqr->buildclk = get_clock(); |
3002 | cqr->status = DASD_CQR_FILLED; | 2720 | cqr->status = DASD_CQR_FILLED; |
3003 | return cqr; | 2721 | return cqr; |
3004 | out_error: | ||
3005 | dasd_sfree_request(cqr, startdev); | ||
3006 | return ERR_PTR(ret); | ||
3007 | } | 2722 | } |
3008 | 2723 | ||
3009 | static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev, | 2724 | static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev, |
@@ -3833,7 +3548,7 @@ dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp) | |||
3833 | case BIODASDSYMMIO: | 3548 | case BIODASDSYMMIO: |
3834 | return dasd_symm_io(device, argp); | 3549 | return dasd_symm_io(device, argp); |
3835 | default: | 3550 | default: |
3836 | return -ENOTTY; | 3551 | return -ENOIOCTLCMD; |
3837 | } | 3552 | } |
3838 | } | 3553 | } |
3839 | 3554 | ||
@@ -3849,7 +3564,7 @@ dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page) | |||
3849 | 3564 | ||
3850 | len = 0; | 3565 | len = 0; |
3851 | while (from <= to) { | 3566 | while (from <= to) { |
3852 | len += sprintf(page + len, PRINTK_HEADER | 3567 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
3853 | " CCW %p: %08X %08X DAT:", | 3568 | " CCW %p: %08X %08X DAT:", |
3854 | from, ((int *) from)[0], ((int *) from)[1]); | 3569 | from, ((int *) from)[0], ((int *) from)[1]); |
3855 | 3570 | ||
@@ -3910,23 +3625,23 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device, | |||
3910 | return; | 3625 | return; |
3911 | } | 3626 | } |
3912 | /* dump the sense data */ | 3627 | /* dump the sense data */ |
3913 | len = sprintf(page, PRINTK_HEADER | 3628 | len = sprintf(page, KERN_ERR PRINTK_HEADER |
3914 | " I/O status report for device %s:\n", | 3629 | " I/O status report for device %s:\n", |
3915 | dev_name(&device->cdev->dev)); | 3630 | dev_name(&device->cdev->dev)); |
3916 | len += sprintf(page + len, PRINTK_HEADER | 3631 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
3917 | " in req: %p CC:%02X FC:%02X AC:%02X SC:%02X DS:%02X " | 3632 | " in req: %p CC:%02X FC:%02X AC:%02X SC:%02X DS:%02X " |
3918 | "CS:%02X RC:%d\n", | 3633 | "CS:%02X RC:%d\n", |
3919 | req, scsw_cc(&irb->scsw), scsw_fctl(&irb->scsw), | 3634 | req, scsw_cc(&irb->scsw), scsw_fctl(&irb->scsw), |
3920 | scsw_actl(&irb->scsw), scsw_stctl(&irb->scsw), | 3635 | scsw_actl(&irb->scsw), scsw_stctl(&irb->scsw), |
3921 | scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw), | 3636 | scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw), |
3922 | req ? req->intrc : 0); | 3637 | req ? req->intrc : 0); |
3923 | len += sprintf(page + len, PRINTK_HEADER | 3638 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
3924 | " device %s: Failing CCW: %p\n", | 3639 | " device %s: Failing CCW: %p\n", |
3925 | dev_name(&device->cdev->dev), | 3640 | dev_name(&device->cdev->dev), |
3926 | (void *) (addr_t) irb->scsw.cmd.cpa); | 3641 | (void *) (addr_t) irb->scsw.cmd.cpa); |
3927 | if (irb->esw.esw0.erw.cons) { | 3642 | if (irb->esw.esw0.erw.cons) { |
3928 | for (sl = 0; sl < 4; sl++) { | 3643 | for (sl = 0; sl < 4; sl++) { |
3929 | len += sprintf(page + len, PRINTK_HEADER | 3644 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
3930 | " Sense(hex) %2d-%2d:", | 3645 | " Sense(hex) %2d-%2d:", |
3931 | (8 * sl), ((8 * sl) + 7)); | 3646 | (8 * sl), ((8 * sl) + 7)); |
3932 | 3647 | ||
@@ -3939,23 +3654,23 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device, | |||
3939 | 3654 | ||
3940 | if (irb->ecw[27] & DASD_SENSE_BIT_0) { | 3655 | if (irb->ecw[27] & DASD_SENSE_BIT_0) { |
3941 | /* 24 Byte Sense Data */ | 3656 | /* 24 Byte Sense Data */ |
3942 | sprintf(page + len, PRINTK_HEADER | 3657 | sprintf(page + len, KERN_ERR PRINTK_HEADER |
3943 | " 24 Byte: %x MSG %x, " | 3658 | " 24 Byte: %x MSG %x, " |
3944 | "%s MSGb to SYSOP\n", | 3659 | "%s MSGb to SYSOP\n", |
3945 | irb->ecw[7] >> 4, irb->ecw[7] & 0x0f, | 3660 | irb->ecw[7] >> 4, irb->ecw[7] & 0x0f, |
3946 | irb->ecw[1] & 0x10 ? "" : "no"); | 3661 | irb->ecw[1] & 0x10 ? "" : "no"); |
3947 | } else { | 3662 | } else { |
3948 | /* 32 Byte Sense Data */ | 3663 | /* 32 Byte Sense Data */ |
3949 | sprintf(page + len, PRINTK_HEADER | 3664 | sprintf(page + len, KERN_ERR PRINTK_HEADER |
3950 | " 32 Byte: Format: %x " | 3665 | " 32 Byte: Format: %x " |
3951 | "Exception class %x\n", | 3666 | "Exception class %x\n", |
3952 | irb->ecw[6] & 0x0f, irb->ecw[22] >> 4); | 3667 | irb->ecw[6] & 0x0f, irb->ecw[22] >> 4); |
3953 | } | 3668 | } |
3954 | } else { | 3669 | } else { |
3955 | sprintf(page + len, PRINTK_HEADER | 3670 | sprintf(page + len, KERN_ERR PRINTK_HEADER |
3956 | " SORRY - NO VALID SENSE AVAILABLE\n"); | 3671 | " SORRY - NO VALID SENSE AVAILABLE\n"); |
3957 | } | 3672 | } |
3958 | printk(KERN_ERR "%s", page); | 3673 | printk("%s", page); |
3959 | 3674 | ||
3960 | if (req) { | 3675 | if (req) { |
3961 | /* req == NULL for unsolicited interrupts */ | 3676 | /* req == NULL for unsolicited interrupts */ |
@@ -3964,10 +3679,10 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device, | |||
3964 | first = req->cpaddr; | 3679 | first = req->cpaddr; |
3965 | for (last = first; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++); | 3680 | for (last = first; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++); |
3966 | to = min(first + 6, last); | 3681 | to = min(first + 6, last); |
3967 | len = sprintf(page, PRINTK_HEADER | 3682 | len = sprintf(page, KERN_ERR PRINTK_HEADER |
3968 | " Related CP in req: %p\n", req); | 3683 | " Related CP in req: %p\n", req); |
3969 | dasd_eckd_dump_ccw_range(first, to, page + len); | 3684 | dasd_eckd_dump_ccw_range(first, to, page + len); |
3970 | printk(KERN_ERR "%s", page); | 3685 | printk("%s", page); |
3971 | 3686 | ||
3972 | /* print failing CCW area (maximum 4) */ | 3687 | /* print failing CCW area (maximum 4) */ |
3973 | /* scsw->cda is either valid or zero */ | 3688 | /* scsw->cda is either valid or zero */ |
@@ -3977,7 +3692,7 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device, | |||
3977 | irb->scsw.cmd.cpa; /* failing CCW */ | 3692 | irb->scsw.cmd.cpa; /* failing CCW */ |
3978 | if (from < fail - 2) { | 3693 | if (from < fail - 2) { |
3979 | from = fail - 2; /* there is a gap - print header */ | 3694 | from = fail - 2; /* there is a gap - print header */ |
3980 | len += sprintf(page, PRINTK_HEADER "......\n"); | 3695 | len += sprintf(page, KERN_ERR PRINTK_HEADER "......\n"); |
3981 | } | 3696 | } |
3982 | to = min(fail + 1, last); | 3697 | to = min(fail + 1, last); |
3983 | len += dasd_eckd_dump_ccw_range(from, to, page + len); | 3698 | len += dasd_eckd_dump_ccw_range(from, to, page + len); |
@@ -3986,11 +3701,11 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device, | |||
3986 | from = max(from, ++to); | 3701 | from = max(from, ++to); |
3987 | if (from < last - 1) { | 3702 | if (from < last - 1) { |
3988 | from = last - 1; /* there is a gap - print header */ | 3703 | from = last - 1; /* there is a gap - print header */ |
3989 | len += sprintf(page + len, PRINTK_HEADER "......\n"); | 3704 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n"); |
3990 | } | 3705 | } |
3991 | len += dasd_eckd_dump_ccw_range(from, last, page + len); | 3706 | len += dasd_eckd_dump_ccw_range(from, last, page + len); |
3992 | if (len > 0) | 3707 | if (len > 0) |
3993 | printk(KERN_ERR "%s", page); | 3708 | printk("%s", page); |
3994 | } | 3709 | } |
3995 | free_page((unsigned long) page); | 3710 | free_page((unsigned long) page); |
3996 | } | 3711 | } |
@@ -4014,10 +3729,10 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device, | |||
4014 | return; | 3729 | return; |
4015 | } | 3730 | } |
4016 | /* dump the sense data */ | 3731 | /* dump the sense data */ |
4017 | len = sprintf(page, PRINTK_HEADER | 3732 | len = sprintf(page, KERN_ERR PRINTK_HEADER |
4018 | " I/O status report for device %s:\n", | 3733 | " I/O status report for device %s:\n", |
4019 | dev_name(&device->cdev->dev)); | 3734 | dev_name(&device->cdev->dev)); |
4020 | len += sprintf(page + len, PRINTK_HEADER | 3735 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
4021 | " in req: %p CC:%02X FC:%02X AC:%02X SC:%02X DS:%02X " | 3736 | " in req: %p CC:%02X FC:%02X AC:%02X SC:%02X DS:%02X " |
4022 | "CS:%02X fcxs:%02X schxs:%02X RC:%d\n", | 3737 | "CS:%02X fcxs:%02X schxs:%02X RC:%d\n", |
4023 | req, scsw_cc(&irb->scsw), scsw_fctl(&irb->scsw), | 3738 | req, scsw_cc(&irb->scsw), scsw_fctl(&irb->scsw), |
@@ -4025,7 +3740,7 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device, | |||
4025 | scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw), | 3740 | scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw), |
4026 | irb->scsw.tm.fcxs, irb->scsw.tm.schxs, | 3741 | irb->scsw.tm.fcxs, irb->scsw.tm.schxs, |
4027 | req ? req->intrc : 0); | 3742 | req ? req->intrc : 0); |
4028 | len += sprintf(page + len, PRINTK_HEADER | 3743 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
4029 | " device %s: Failing TCW: %p\n", | 3744 | " device %s: Failing TCW: %p\n", |
4030 | dev_name(&device->cdev->dev), | 3745 | dev_name(&device->cdev->dev), |
4031 | (void *) (addr_t) irb->scsw.tm.tcw); | 3746 | (void *) (addr_t) irb->scsw.tm.tcw); |
@@ -4037,42 +3752,43 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device, | |||
4037 | (struct tcw *)(unsigned long)irb->scsw.tm.tcw); | 3752 | (struct tcw *)(unsigned long)irb->scsw.tm.tcw); |
4038 | 3753 | ||
4039 | if (tsb) { | 3754 | if (tsb) { |
4040 | len += sprintf(page + len, PRINTK_HEADER | 3755 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
4041 | " tsb->length %d\n", tsb->length); | 3756 | " tsb->length %d\n", tsb->length); |
4042 | len += sprintf(page + len, PRINTK_HEADER | 3757 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
4043 | " tsb->flags %x\n", tsb->flags); | 3758 | " tsb->flags %x\n", tsb->flags); |
4044 | len += sprintf(page + len, PRINTK_HEADER | 3759 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
4045 | " tsb->dcw_offset %d\n", tsb->dcw_offset); | 3760 | " tsb->dcw_offset %d\n", tsb->dcw_offset); |
4046 | len += sprintf(page + len, PRINTK_HEADER | 3761 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
4047 | " tsb->count %d\n", tsb->count); | 3762 | " tsb->count %d\n", tsb->count); |
4048 | residual = tsb->count - 28; | 3763 | residual = tsb->count - 28; |
4049 | len += sprintf(page + len, PRINTK_HEADER | 3764 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
4050 | " residual %d\n", residual); | 3765 | " residual %d\n", residual); |
4051 | 3766 | ||
4052 | switch (tsb->flags & 0x07) { | 3767 | switch (tsb->flags & 0x07) { |
4053 | case 1: /* tsa_iostat */ | 3768 | case 1: /* tsa_iostat */ |
4054 | len += sprintf(page + len, PRINTK_HEADER | 3769 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
4055 | " tsb->tsa.iostat.dev_time %d\n", | 3770 | " tsb->tsa.iostat.dev_time %d\n", |
4056 | tsb->tsa.iostat.dev_time); | 3771 | tsb->tsa.iostat.dev_time); |
4057 | len += sprintf(page + len, PRINTK_HEADER | 3772 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
4058 | " tsb->tsa.iostat.def_time %d\n", | 3773 | " tsb->tsa.iostat.def_time %d\n", |
4059 | tsb->tsa.iostat.def_time); | 3774 | tsb->tsa.iostat.def_time); |
4060 | len += sprintf(page + len, PRINTK_HEADER | 3775 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
4061 | " tsb->tsa.iostat.queue_time %d\n", | 3776 | " tsb->tsa.iostat.queue_time %d\n", |
4062 | tsb->tsa.iostat.queue_time); | 3777 | tsb->tsa.iostat.queue_time); |
4063 | len += sprintf(page + len, PRINTK_HEADER | 3778 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
4064 | " tsb->tsa.iostat.dev_busy_time %d\n", | 3779 | " tsb->tsa.iostat.dev_busy_time %d\n", |
4065 | tsb->tsa.iostat.dev_busy_time); | 3780 | tsb->tsa.iostat.dev_busy_time); |
4066 | len += sprintf(page + len, PRINTK_HEADER | 3781 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
4067 | " tsb->tsa.iostat.dev_act_time %d\n", | 3782 | " tsb->tsa.iostat.dev_act_time %d\n", |
4068 | tsb->tsa.iostat.dev_act_time); | 3783 | tsb->tsa.iostat.dev_act_time); |
4069 | sense = tsb->tsa.iostat.sense; | 3784 | sense = tsb->tsa.iostat.sense; |
4070 | break; | 3785 | break; |
4071 | case 2: /* ts_ddpc */ | 3786 | case 2: /* ts_ddpc */ |
4072 | len += sprintf(page + len, PRINTK_HEADER | 3787 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
4073 | " tsb->tsa.ddpc.rc %d\n", tsb->tsa.ddpc.rc); | 3788 | " tsb->tsa.ddpc.rc %d\n", tsb->tsa.ddpc.rc); |
4074 | for (sl = 0; sl < 2; sl++) { | 3789 | for (sl = 0; sl < 2; sl++) { |
4075 | len += sprintf(page + len, PRINTK_HEADER | 3790 | len += sprintf(page + len, |
3791 | KERN_ERR PRINTK_HEADER | ||
4076 | " tsb->tsa.ddpc.rcq %2d-%2d: ", | 3792 | " tsb->tsa.ddpc.rcq %2d-%2d: ", |
4077 | (8 * sl), ((8 * sl) + 7)); | 3793 | (8 * sl), ((8 * sl) + 7)); |
4078 | rcq = tsb->tsa.ddpc.rcq; | 3794 | rcq = tsb->tsa.ddpc.rcq; |
@@ -4085,14 +3801,15 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device, | |||
4085 | sense = tsb->tsa.ddpc.sense; | 3801 | sense = tsb->tsa.ddpc.sense; |
4086 | break; | 3802 | break; |
4087 | case 3: /* tsa_intrg */ | 3803 | case 3: /* tsa_intrg */ |
4088 | len += sprintf(page + len, PRINTK_HEADER | 3804 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
4089 | " tsb->tsa.intrg.: not supportet yet\n"); | 3805 | " tsb->tsa.intrg.: not supportet yet \n"); |
4090 | break; | 3806 | break; |
4091 | } | 3807 | } |
4092 | 3808 | ||
4093 | if (sense) { | 3809 | if (sense) { |
4094 | for (sl = 0; sl < 4; sl++) { | 3810 | for (sl = 0; sl < 4; sl++) { |
4095 | len += sprintf(page + len, PRINTK_HEADER | 3811 | len += sprintf(page + len, |
3812 | KERN_ERR PRINTK_HEADER | ||
4096 | " Sense(hex) %2d-%2d:", | 3813 | " Sense(hex) %2d-%2d:", |
4097 | (8 * sl), ((8 * sl) + 7)); | 3814 | (8 * sl), ((8 * sl) + 7)); |
4098 | for (sct = 0; sct < 8; sct++) { | 3815 | for (sct = 0; sct < 8; sct++) { |
@@ -4104,27 +3821,27 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device, | |||
4104 | 3821 | ||
4105 | if (sense[27] & DASD_SENSE_BIT_0) { | 3822 | if (sense[27] & DASD_SENSE_BIT_0) { |
4106 | /* 24 Byte Sense Data */ | 3823 | /* 24 Byte Sense Data */ |
4107 | sprintf(page + len, PRINTK_HEADER | 3824 | sprintf(page + len, KERN_ERR PRINTK_HEADER |
4108 | " 24 Byte: %x MSG %x, " | 3825 | " 24 Byte: %x MSG %x, " |
4109 | "%s MSGb to SYSOP\n", | 3826 | "%s MSGb to SYSOP\n", |
4110 | sense[7] >> 4, sense[7] & 0x0f, | 3827 | sense[7] >> 4, sense[7] & 0x0f, |
4111 | sense[1] & 0x10 ? "" : "no"); | 3828 | sense[1] & 0x10 ? "" : "no"); |
4112 | } else { | 3829 | } else { |
4113 | /* 32 Byte Sense Data */ | 3830 | /* 32 Byte Sense Data */ |
4114 | sprintf(page + len, PRINTK_HEADER | 3831 | sprintf(page + len, KERN_ERR PRINTK_HEADER |
4115 | " 32 Byte: Format: %x " | 3832 | " 32 Byte: Format: %x " |
4116 | "Exception class %x\n", | 3833 | "Exception class %x\n", |
4117 | sense[6] & 0x0f, sense[22] >> 4); | 3834 | sense[6] & 0x0f, sense[22] >> 4); |
4118 | } | 3835 | } |
4119 | } else { | 3836 | } else { |
4120 | sprintf(page + len, PRINTK_HEADER | 3837 | sprintf(page + len, KERN_ERR PRINTK_HEADER |
4121 | " SORRY - NO VALID SENSE AVAILABLE\n"); | 3838 | " SORRY - NO VALID SENSE AVAILABLE\n"); |
4122 | } | 3839 | } |
4123 | } else { | 3840 | } else { |
4124 | sprintf(page + len, PRINTK_HEADER | 3841 | sprintf(page + len, KERN_ERR PRINTK_HEADER |
4125 | " SORRY - NO TSB DATA AVAILABLE\n"); | 3842 | " SORRY - NO TSB DATA AVAILABLE\n"); |
4126 | } | 3843 | } |
4127 | printk(KERN_ERR "%s", page); | 3844 | printk("%s", page); |
4128 | free_page((unsigned long) page); | 3845 | free_page((unsigned long) page); |
4129 | } | 3846 | } |
4130 | 3847 | ||
@@ -4154,14 +3871,16 @@ static int dasd_eckd_restore_device(struct dasd_device *device) | |||
4154 | { | 3871 | { |
4155 | struct dasd_eckd_private *private; | 3872 | struct dasd_eckd_private *private; |
4156 | struct dasd_eckd_characteristics temp_rdc_data; | 3873 | struct dasd_eckd_characteristics temp_rdc_data; |
4157 | int rc; | 3874 | int is_known, rc; |
4158 | struct dasd_uid temp_uid; | 3875 | struct dasd_uid temp_uid; |
4159 | unsigned long flags; | 3876 | unsigned long flags; |
4160 | 3877 | ||
4161 | private = (struct dasd_eckd_private *) device->private; | 3878 | private = (struct dasd_eckd_private *) device->private; |
4162 | 3879 | ||
4163 | /* Read Configuration Data */ | 3880 | /* Read Configuration Data */ |
4164 | dasd_eckd_read_conf(device); | 3881 | rc = dasd_eckd_read_conf(device); |
3882 | if (rc) | ||
3883 | goto out_err; | ||
4165 | 3884 | ||
4166 | dasd_eckd_get_uid(device, &temp_uid); | 3885 | dasd_eckd_get_uid(device, &temp_uid); |
4167 | /* Generate device unique id */ | 3886 | /* Generate device unique id */ |
@@ -4175,13 +3894,19 @@ static int dasd_eckd_restore_device(struct dasd_device *device) | |||
4175 | goto out_err; | 3894 | goto out_err; |
4176 | 3895 | ||
4177 | /* register lcu with alias handling, enable PAV if this is a new lcu */ | 3896 | /* register lcu with alias handling, enable PAV if this is a new lcu */ |
4178 | rc = dasd_alias_make_device_known_to_lcu(device); | 3897 | is_known = dasd_alias_make_device_known_to_lcu(device); |
4179 | if (rc) | 3898 | if (is_known < 0) |
4180 | return rc; | 3899 | return is_known; |
4181 | dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST); | 3900 | if (!is_known) { |
3901 | dasd_eckd_validate_server(device); | ||
3902 | dasd_alias_lcu_setup_complete(device); | ||
3903 | } else | ||
3904 | dasd_alias_wait_for_lcu_setup(device); | ||
4182 | 3905 | ||
4183 | /* RE-Read Configuration Data */ | 3906 | /* RE-Read Configuration Data */ |
4184 | dasd_eckd_read_conf(device); | 3907 | rc = dasd_eckd_read_conf(device); |
3908 | if (rc) | ||
3909 | goto out_err; | ||
4185 | 3910 | ||
4186 | /* Read Feature Codes */ | 3911 | /* Read Feature Codes */ |
4187 | dasd_eckd_read_features(device); | 3912 | dasd_eckd_read_features(device); |
@@ -4269,12 +3994,10 @@ static struct ccw_driver dasd_eckd_driver = { | |||
4269 | .set_online = dasd_eckd_set_online, | 3994 | .set_online = dasd_eckd_set_online, |
4270 | .notify = dasd_generic_notify, | 3995 | .notify = dasd_generic_notify, |
4271 | .path_event = dasd_generic_path_event, | 3996 | .path_event = dasd_generic_path_event, |
4272 | .shutdown = dasd_generic_shutdown, | ||
4273 | .freeze = dasd_generic_pm_freeze, | 3997 | .freeze = dasd_generic_pm_freeze, |
4274 | .thaw = dasd_generic_restore_device, | 3998 | .thaw = dasd_generic_restore_device, |
4275 | .restore = dasd_generic_restore_device, | 3999 | .restore = dasd_generic_restore_device, |
4276 | .uc_handler = dasd_generic_uc_handler, | 4000 | .uc_handler = dasd_generic_uc_handler, |
4277 | .int_class = IRQIO_DAS, | ||
4278 | }; | 4001 | }; |
4279 | 4002 | ||
4280 | /* | 4003 | /* |
@@ -4319,7 +4042,6 @@ static struct dasd_discipline dasd_eckd_discipline = { | |||
4319 | .restore = dasd_eckd_restore_device, | 4042 | .restore = dasd_eckd_restore_device, |
4320 | .reload = dasd_eckd_reload_device, | 4043 | .reload = dasd_eckd_reload_device, |
4321 | .get_uid = dasd_eckd_get_uid, | 4044 | .get_uid = dasd_eckd_get_uid, |
4322 | .kick_validate = dasd_eckd_kick_validate_server, | ||
4323 | }; | 4045 | }; |
4324 | 4046 | ||
4325 | static int __init | 4047 | static int __init |