diff options
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index c4eb62b32a32..bec912547fb8 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -1010,6 +1010,23 @@ skip_fsfstatus: | |||
1010 | send_ct->handler(send_ct->handler_data); | 1010 | send_ct->handler(send_ct->handler_data); |
1011 | } | 1011 | } |
1012 | 1012 | ||
1013 | static void zfcp_fsf_setup_ct_els_unchained(struct qdio_buffer_element *sbale, | ||
1014 | struct scatterlist *sg_req, | ||
1015 | struct scatterlist *sg_resp) | ||
1016 | { | ||
1017 | sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ; | ||
1018 | sbale[2].addr = sg_virt(sg_req); | ||
1019 | sbale[2].length = sg_req->length; | ||
1020 | sbale[3].addr = sg_virt(sg_resp); | ||
1021 | sbale[3].length = sg_resp->length; | ||
1022 | sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; | ||
1023 | } | ||
1024 | |||
1025 | static int zfcp_fsf_one_sbal(struct scatterlist *sg) | ||
1026 | { | ||
1027 | return sg_is_last(sg) && sg->length <= PAGE_SIZE; | ||
1028 | } | ||
1029 | |||
1013 | static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, | 1030 | static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, |
1014 | struct scatterlist *sg_req, | 1031 | struct scatterlist *sg_req, |
1015 | struct scatterlist *sg_resp, | 1032 | struct scatterlist *sg_resp, |
@@ -1020,16 +1037,16 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, | |||
1020 | int bytes; | 1037 | int bytes; |
1021 | 1038 | ||
1022 | if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) { | 1039 | if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) { |
1023 | if (sg_req->length > PAGE_SIZE || sg_resp->length > PAGE_SIZE || | 1040 | if (!zfcp_fsf_one_sbal(sg_req) || !zfcp_fsf_one_sbal(sg_resp)) |
1024 | !sg_is_last(sg_req) || !sg_is_last(sg_resp)) | ||
1025 | return -EOPNOTSUPP; | 1041 | return -EOPNOTSUPP; |
1026 | 1042 | ||
1027 | sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ; | 1043 | zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp); |
1028 | sbale[2].addr = sg_virt(sg_req); | 1044 | return 0; |
1029 | sbale[2].length = sg_req->length; | 1045 | } |
1030 | sbale[3].addr = sg_virt(sg_resp); | 1046 | |
1031 | sbale[3].length = sg_resp->length; | 1047 | /* use single, unchained SBAL if it can hold the request */ |
1032 | sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; | 1048 | if (zfcp_fsf_one_sbal(sg_req) && zfcp_fsf_one_sbal(sg_resp)) { |
1049 | zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp); | ||
1033 | return 0; | 1050 | return 0; |
1034 | } | 1051 | } |
1035 | 1052 | ||