aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorChristof Schmitt <christof.schmitt@de.ibm.com>2009-07-13 09:06:06 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-07-30 09:49:56 -0400
commit426f6059b0eb66cec139f4b9066168ab72b85774 (patch)
tree5a117d5f0a885b591bea2b6bdf8475fb6745f2af /drivers/s390
parent688a1820bde27749f22b18b94ef1c9bc179b1b29 (diff)
[SCSI] zfcp: Use unchained mode for small ct and els requests
The ELS ADISC and the GID_PN requests sent from zfcp fit into unchained FSF requests. Change the FSF allocation logic to use unchained requests whenever possible where everything fits in one SBAL. This avoids acquiring more SBALs than necessary, especially during zfcp recovery when things might be stalled. Reviewed-by: Swen Schillig <swen@vnet.ibm.com> Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/s390')
-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