aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c33
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
1013static 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
1025static int zfcp_fsf_one_sbal(struct scatterlist *sg)
1026{
1027 return sg_is_last(sg) && sg->length <= PAGE_SIZE;
1028}
1029
1013static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, 1030static 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