aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd_eckd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/block/dasd_eckd.c')
-rw-r--r--drivers/s390/block/dasd_eckd.c261
1 files changed, 221 insertions, 40 deletions
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 549443af121c..a1ebf5722ae5 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -90,6 +90,18 @@ static struct {
90} *dasd_reserve_req; 90} *dasd_reserve_req;
91static DEFINE_MUTEX(dasd_reserve_mutex); 91static DEFINE_MUTEX(dasd_reserve_mutex);
92 92
93/* definitions for the path verification worker */
94struct path_verification_work_data {
95 struct work_struct worker;
96 struct dasd_device *device;
97 struct dasd_ccw_req cqr;
98 struct ccw1 ccw;
99 __u8 rcd_buffer[DASD_ECKD_RCD_DATA_SIZE];
100 int isglobal;
101 __u8 tbvpm;
102};
103static struct path_verification_work_data *path_verification_worker;
104static DEFINE_MUTEX(dasd_path_verification_mutex);
93 105
94/* initial attempt at a probe function. this can be simplified once 106/* initial attempt at a probe function. this can be simplified once
95 * the other detection code is gone */ 107 * the other detection code is gone */
@@ -755,26 +767,27 @@ static int dasd_eckd_get_uid(struct dasd_device *device, struct dasd_uid *uid)
755 return -EINVAL; 767 return -EINVAL;
756} 768}
757 769
758static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device, 770static void dasd_eckd_fill_rcd_cqr(struct dasd_device *device,
759 void *rcd_buffer, 771 struct dasd_ccw_req *cqr,
760 struct ciw *ciw, __u8 lpm) 772 __u8 *rcd_buffer,
773 __u8 lpm)
761{ 774{
762 struct dasd_ccw_req *cqr;
763 struct ccw1 *ccw; 775 struct ccw1 *ccw;
764 776 /*
765 cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* RCD */, ciw->count, 777 * buffer has to start with EBCDIC "V1.0" to show
766 device); 778 * support for virtual device SNEQ
767 779 */
768 if (IS_ERR(cqr)) { 780 rcd_buffer[0] = 0xE5;
769 DBF_DEV_EVENT(DBF_WARNING, device, "%s", 781 rcd_buffer[1] = 0xF1;
770 "Could not allocate RCD request"); 782 rcd_buffer[2] = 0x4B;
771 return cqr; 783 rcd_buffer[3] = 0xF0;
772 }
773 784
774 ccw = cqr->cpaddr; 785 ccw = cqr->cpaddr;
775 ccw->cmd_code = ciw->cmd; 786 ccw->cmd_code = DASD_ECKD_CCW_RCD;
787 ccw->flags = 0;
776 ccw->cda = (__u32)(addr_t)rcd_buffer; 788 ccw->cda = (__u32)(addr_t)rcd_buffer;
777 ccw->count = ciw->count; 789 ccw->count = DASD_ECKD_RCD_DATA_SIZE;
790 cqr->magic = DASD_ECKD_MAGIC;
778 791
779 cqr->startdev = device; 792 cqr->startdev = device;
780 cqr->memdev = device; 793 cqr->memdev = device;
@@ -784,7 +797,29 @@ static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device,
784 cqr->retries = 256; 797 cqr->retries = 256;
785 cqr->buildclk = get_clock(); 798 cqr->buildclk = get_clock();
786 cqr->status = DASD_CQR_FILLED; 799 cqr->status = DASD_CQR_FILLED;
787 return cqr; 800 set_bit(DASD_CQR_VERIFY_PATH, &cqr->flags);
801}
802
803static int dasd_eckd_read_conf_immediately(struct dasd_device *device,
804 struct dasd_ccw_req *cqr,
805 __u8 *rcd_buffer,
806 __u8 lpm)
807{
808 struct ciw *ciw;
809 int rc;
810 /*
811 * sanity check: scan for RCD command in extended SenseID data
812 * some devices do not support RCD
813 */
814 ciw = ccw_device_get_ciw(device->cdev, CIW_TYPE_RCD);
815 if (!ciw || ciw->cmd != DASD_ECKD_CCW_RCD)
816 return -EOPNOTSUPP;
817
818 dasd_eckd_fill_rcd_cqr(device, cqr, rcd_buffer, lpm);
819 clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
820 cqr->retries = 5;
821 rc = dasd_sleep_on_immediatly(cqr);
822 return rc;
788} 823}
789 824
790static int dasd_eckd_read_conf_lpm(struct dasd_device *device, 825static int dasd_eckd_read_conf_lpm(struct dasd_device *device,
@@ -797,32 +832,29 @@ static int dasd_eckd_read_conf_lpm(struct dasd_device *device,
797 struct dasd_ccw_req *cqr; 832 struct dasd_ccw_req *cqr;
798 833
799 /* 834 /*
800 * scan for RCD command in extended SenseID data 835 * sanity check: scan for RCD command in extended SenseID data
836 * some devices do not support RCD
801 */ 837 */
802 ciw = ccw_device_get_ciw(device->cdev, CIW_TYPE_RCD); 838 ciw = ccw_device_get_ciw(device->cdev, CIW_TYPE_RCD);
803 if (!ciw || ciw->cmd == 0) { 839 if (!ciw || ciw->cmd != DASD_ECKD_CCW_RCD) {
804 ret = -EOPNOTSUPP; 840 ret = -EOPNOTSUPP;
805 goto out_error; 841 goto out_error;
806 } 842 }
807 rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA); 843 rcd_buf = kzalloc(DASD_ECKD_RCD_DATA_SIZE, GFP_KERNEL | GFP_DMA);
808 if (!rcd_buf) { 844 if (!rcd_buf) {
809 ret = -ENOMEM; 845 ret = -ENOMEM;
810 goto out_error; 846 goto out_error;
811 } 847 }
812 848 cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* RCD */,
813 /* 849 0, /* use rcd_buf as data ara */
814 * buffer has to start with EBCDIC "V1.0" to show 850 device);
815 * support for virtual device SNEQ
816 */
817 rcd_buf[0] = 0xE5;
818 rcd_buf[1] = 0xF1;
819 rcd_buf[2] = 0x4B;
820 rcd_buf[3] = 0xF0;
821 cqr = dasd_eckd_build_rcd_lpm(device, rcd_buf, ciw, lpm);
822 if (IS_ERR(cqr)) { 851 if (IS_ERR(cqr)) {
823 ret = PTR_ERR(cqr); 852 DBF_DEV_EVENT(DBF_WARNING, device, "%s",
853 "Could not allocate RCD request");
854 ret = -ENOMEM;
824 goto out_error; 855 goto out_error;
825 } 856 }
857 dasd_eckd_fill_rcd_cqr(device, cqr, rcd_buf, lpm);
826 ret = dasd_sleep_on(cqr); 858 ret = dasd_sleep_on(cqr);
827 /* 859 /*
828 * on success we update the user input parms 860 * on success we update the user input parms
@@ -831,7 +863,7 @@ static int dasd_eckd_read_conf_lpm(struct dasd_device *device,
831 if (ret) 863 if (ret)
832 goto out_error; 864 goto out_error;
833 865
834 *rcd_buffer_size = ciw->count; 866 *rcd_buffer_size = DASD_ECKD_RCD_DATA_SIZE;
835 *rcd_buffer = rcd_buf; 867 *rcd_buffer = rcd_buf;
836 return 0; 868 return 0;
837out_error: 869out_error:
@@ -901,18 +933,18 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
901 void *conf_data; 933 void *conf_data;
902 int conf_len, conf_data_saved; 934 int conf_len, conf_data_saved;
903 int rc; 935 int rc;
904 __u8 lpm; 936 __u8 lpm, opm;
905 struct dasd_eckd_private *private; 937 struct dasd_eckd_private *private;
906 struct dasd_eckd_path *path_data; 938 struct dasd_path *path_data;
907 939
908 private = (struct dasd_eckd_private *) device->private; 940 private = (struct dasd_eckd_private *) device->private;
909 path_data = (struct dasd_eckd_path *) &private->path_data; 941 path_data = &device->path_data;
910 path_data->opm = ccw_device_get_path_mask(device->cdev); 942 opm = ccw_device_get_path_mask(device->cdev);
911 lpm = 0x80; 943 lpm = 0x80;
912 conf_data_saved = 0; 944 conf_data_saved = 0;
913 /* get configuration data per operational path */ 945 /* get configuration data per operational path */
914 for (lpm = 0x80; lpm; lpm>>= 1) { 946 for (lpm = 0x80; lpm; lpm>>= 1) {
915 if (lpm & path_data->opm){ 947 if (lpm & opm) {
916 rc = dasd_eckd_read_conf_lpm(device, &conf_data, 948 rc = dasd_eckd_read_conf_lpm(device, &conf_data,
917 &conf_len, lpm); 949 &conf_len, lpm);
918 if (rc && rc != -EOPNOTSUPP) { /* -EOPNOTSUPP is ok */ 950 if (rc && rc != -EOPNOTSUPP) { /* -EOPNOTSUPP is ok */
@@ -925,6 +957,8 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
925 DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", 957 DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
926 "No configuration data " 958 "No configuration data "
927 "retrieved"); 959 "retrieved");
960 /* no further analysis possible */
961 path_data->opm |= lpm;
928 continue; /* no error */ 962 continue; /* no error */
929 } 963 }
930 /* save first valid configuration data */ 964 /* save first valid configuration data */
@@ -948,6 +982,7 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
948 path_data->ppm |= lpm; 982 path_data->ppm |= lpm;
949 break; 983 break;
950 } 984 }
985 path_data->opm |= lpm;
951 if (conf_data != private->conf_data) 986 if (conf_data != private->conf_data)
952 kfree(conf_data); 987 kfree(conf_data);
953 } 988 }
@@ -955,6 +990,140 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
955 return 0; 990 return 0;
956} 991}
957 992
993static int verify_fcx_max_data(struct dasd_device *device, __u8 lpm)
994{
995 struct dasd_eckd_private *private;
996 int mdc;
997 u32 fcx_max_data;
998
999 private = (struct dasd_eckd_private *) device->private;
1000 if (private->fcx_max_data) {
1001 mdc = ccw_device_get_mdc(device->cdev, lpm);
1002 if ((mdc < 0)) {
1003 dev_warn(&device->cdev->dev,
1004 "Detecting the maximum data size for zHPF "
1005 "requests failed (rc=%d) for a new path %x\n",
1006 mdc, lpm);
1007 return mdc;
1008 }
1009 fcx_max_data = mdc * FCX_MAX_DATA_FACTOR;
1010 if (fcx_max_data < private->fcx_max_data) {
1011 dev_warn(&device->cdev->dev,
1012 "The maximum data size for zHPF requests %u "
1013 "on a new path %x is below the active maximum "
1014 "%u\n", fcx_max_data, lpm,
1015 private->fcx_max_data);
1016 return -EACCES;
1017 }
1018 }
1019 return 0;
1020}
1021
1022static void do_path_verification_work(struct work_struct *work)
1023{
1024 struct path_verification_work_data *data;
1025 struct dasd_device *device;
1026 __u8 lpm, opm, npm, ppm, epm;
1027 unsigned long flags;
1028 int rc;
1029
1030 data = container_of(work, struct path_verification_work_data, worker);
1031 device = data->device;
1032
1033 opm = 0;
1034 npm = 0;
1035 ppm = 0;
1036 epm = 0;
1037 for (lpm = 0x80; lpm; lpm >>= 1) {
1038 if (lpm & data->tbvpm) {
1039 memset(data->rcd_buffer, 0, sizeof(data->rcd_buffer));
1040 memset(&data->cqr, 0, sizeof(data->cqr));
1041 data->cqr.cpaddr = &data->ccw;
1042 rc = dasd_eckd_read_conf_immediately(device, &data->cqr,
1043 data->rcd_buffer,
1044 lpm);
1045 if (!rc) {
1046 switch (dasd_eckd_path_access(data->rcd_buffer,
1047 DASD_ECKD_RCD_DATA_SIZE)) {
1048 case 0x02:
1049 npm |= lpm;
1050 break;
1051 case 0x03:
1052 ppm |= lpm;
1053 break;
1054 }
1055 opm |= lpm;
1056 } else if (rc == -EOPNOTSUPP) {
1057 DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
1058 "path verification: No configuration "
1059 "data retrieved");
1060 opm |= lpm;
1061 } else if (rc == -EAGAIN) {
1062 DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
1063 "path verification: device is stopped,"
1064 " try again later");
1065 epm |= lpm;
1066 } else {
1067 dev_warn(&device->cdev->dev,
1068 "Reading device feature codes failed "
1069 "(rc=%d) for new path %x\n", rc, lpm);
1070 continue;
1071 }
1072 if (verify_fcx_max_data(device, lpm)) {
1073 opm &= ~lpm;
1074 npm &= ~lpm;
1075 ppm &= ~lpm;
1076 }
1077 }
1078 }
1079 /*
1080 * There is a small chance that a path is lost again between
1081 * above path verification and the following modification of
1082 * the device opm mask. We could avoid that race here by using
1083 * yet another path mask, but we rather deal with this unlikely
1084 * situation in dasd_start_IO.
1085 */
1086 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
1087 if (!device->path_data.opm && opm) {
1088 device->path_data.opm = opm;
1089 dasd_generic_path_operational(device);
1090 } else
1091 device->path_data.opm |= opm;
1092 device->path_data.npm |= npm;
1093 device->path_data.ppm |= ppm;
1094 device->path_data.tbvpm |= epm;
1095 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
1096
1097 dasd_put_device(device);
1098 if (data->isglobal)
1099 mutex_unlock(&dasd_path_verification_mutex);
1100 else
1101 kfree(data);
1102}
1103
1104static int dasd_eckd_verify_path(struct dasd_device *device, __u8 lpm)
1105{
1106 struct path_verification_work_data *data;
1107
1108 data = kmalloc(sizeof(*data), GFP_ATOMIC | GFP_DMA);
1109 if (!data) {
1110 if (mutex_trylock(&dasd_path_verification_mutex)) {
1111 data = path_verification_worker;
1112 data->isglobal = 1;
1113 } else
1114 return -ENOMEM;
1115 } else {
1116 memset(data, 0, sizeof(*data));
1117 data->isglobal = 0;
1118 }
1119 INIT_WORK(&data->worker, do_path_verification_work);
1120 dasd_get_device(device);
1121 data->device = device;
1122 data->tbvpm = lpm;
1123 schedule_work(&data->worker);
1124 return 0;
1125}
1126
958static int dasd_eckd_read_features(struct dasd_device *device) 1127static int dasd_eckd_read_features(struct dasd_device *device)
959{ 1128{
960 struct dasd_psf_prssd_data *prssdp; 1129 struct dasd_psf_prssd_data *prssdp;
@@ -1749,6 +1918,7 @@ static void dasd_eckd_handle_terminated_request(struct dasd_ccw_req *cqr)
1749 if (cqr->block && (cqr->startdev != cqr->block->base)) { 1918 if (cqr->block && (cqr->startdev != cqr->block->base)) {
1750 dasd_eckd_reset_ccw_to_base_io(cqr); 1919 dasd_eckd_reset_ccw_to_base_io(cqr);
1751 cqr->startdev = cqr->block->base; 1920 cqr->startdev = cqr->block->base;
1921 cqr->lpm = cqr->block->base->path_data.opm;
1752 } 1922 }
1753}; 1923};
1754 1924
@@ -2017,7 +2187,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
2017 cqr->memdev = startdev; 2187 cqr->memdev = startdev;
2018 cqr->block = block; 2188 cqr->block = block;
2019 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */ 2189 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
2020 cqr->lpm = private->path_data.ppm; 2190 cqr->lpm = startdev->path_data.ppm;
2021 cqr->retries = 256; 2191 cqr->retries = 256;
2022 cqr->buildclk = get_clock(); 2192 cqr->buildclk = get_clock();
2023 cqr->status = DASD_CQR_FILLED; 2193 cqr->status = DASD_CQR_FILLED;
@@ -2194,7 +2364,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
2194 cqr->memdev = startdev; 2364 cqr->memdev = startdev;
2195 cqr->block = block; 2365 cqr->block = block;
2196 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */ 2366 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
2197 cqr->lpm = private->path_data.ppm; 2367 cqr->lpm = startdev->path_data.ppm;
2198 cqr->retries = 256; 2368 cqr->retries = 256;
2199 cqr->buildclk = get_clock(); 2369 cqr->buildclk = get_clock();
2200 cqr->status = DASD_CQR_FILLED; 2370 cqr->status = DASD_CQR_FILLED;
@@ -2484,7 +2654,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
2484 cqr->memdev = startdev; 2654 cqr->memdev = startdev;
2485 cqr->block = block; 2655 cqr->block = block;
2486 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */ 2656 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
2487 cqr->lpm = private->path_data.ppm; 2657 cqr->lpm = startdev->path_data.ppm;
2488 cqr->retries = 256; 2658 cqr->retries = 256;
2489 cqr->buildclk = get_clock(); 2659 cqr->buildclk = get_clock();
2490 cqr->status = DASD_CQR_FILLED; 2660 cqr->status = DASD_CQR_FILLED;
@@ -3624,6 +3794,7 @@ static struct ccw_driver dasd_eckd_driver = {
3624 .set_offline = dasd_generic_set_offline, 3794 .set_offline = dasd_generic_set_offline,
3625 .set_online = dasd_eckd_set_online, 3795 .set_online = dasd_eckd_set_online,
3626 .notify = dasd_generic_notify, 3796 .notify = dasd_generic_notify,
3797 .path_event = dasd_generic_path_event,
3627 .freeze = dasd_generic_pm_freeze, 3798 .freeze = dasd_generic_pm_freeze,
3628 .thaw = dasd_generic_restore_device, 3799 .thaw = dasd_generic_restore_device,
3629 .restore = dasd_generic_restore_device, 3800 .restore = dasd_generic_restore_device,
@@ -3651,6 +3822,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
3651 .check_device = dasd_eckd_check_characteristics, 3822 .check_device = dasd_eckd_check_characteristics,
3652 .uncheck_device = dasd_eckd_uncheck_device, 3823 .uncheck_device = dasd_eckd_uncheck_device,
3653 .do_analysis = dasd_eckd_do_analysis, 3824 .do_analysis = dasd_eckd_do_analysis,
3825 .verify_path = dasd_eckd_verify_path,
3654 .ready_to_online = dasd_eckd_ready_to_online, 3826 .ready_to_online = dasd_eckd_ready_to_online,
3655 .online_to_ready = dasd_eckd_online_to_ready, 3827 .online_to_ready = dasd_eckd_online_to_ready,
3656 .fill_geometry = dasd_eckd_fill_geometry, 3828 .fill_geometry = dasd_eckd_fill_geometry,
@@ -3683,11 +3855,19 @@ dasd_eckd_init(void)
3683 GFP_KERNEL | GFP_DMA); 3855 GFP_KERNEL | GFP_DMA);
3684 if (!dasd_reserve_req) 3856 if (!dasd_reserve_req)
3685 return -ENOMEM; 3857 return -ENOMEM;
3858 path_verification_worker = kmalloc(sizeof(*path_verification_worker),
3859 GFP_KERNEL | GFP_DMA);
3860 if (!path_verification_worker) {
3861 kfree(dasd_reserve_req);
3862 return -ENOMEM;
3863 }
3686 ret = ccw_driver_register(&dasd_eckd_driver); 3864 ret = ccw_driver_register(&dasd_eckd_driver);
3687 if (!ret) 3865 if (!ret)
3688 wait_for_device_probe(); 3866 wait_for_device_probe();
3689 else 3867 else {
3868 kfree(path_verification_worker);
3690 kfree(dasd_reserve_req); 3869 kfree(dasd_reserve_req);
3870 }
3691 return ret; 3871 return ret;
3692} 3872}
3693 3873
@@ -3695,6 +3875,7 @@ static void __exit
3695dasd_eckd_cleanup(void) 3875dasd_eckd_cleanup(void)
3696{ 3876{
3697 ccw_driver_unregister(&dasd_eckd_driver); 3877 ccw_driver_unregister(&dasd_eckd_driver);
3878 kfree(path_verification_worker);
3698 kfree(dasd_reserve_req); 3879 kfree(dasd_reserve_req);
3699} 3880}
3700 3881