+++ /dev/null
-From: Gerald Schaefer <geraldsc@de.ibm.com>
-Subject: zfcp: Use only single SBAL commands from recovery
-References: bnc#518291,LTC#54462
-
-Symptom: Issuing an ELS request might not detect a stalled
- outbound queue
-Problem: zfcp uses chained SBALs for ELS requests leading to the
- situation that the ELS request gets one free SBAL, but
- not the following ones. In this situation the ELS request
- fails but does not trigger the error handling for the
- stalled queue.
-Solution: Use unchained SBALs where possible, especially for
- commands from the erp. This guarantees that each erp
- command will get the required SBAL or trigger queue
- recovery.
-
-Acked-by: John Jolly <jjolly@suse.de>
----
- drivers/s390/scsi/zfcp_fsf.c | 33 +++++++++++++++++++++++++--------
- 1 file changed, 25 insertions(+), 8 deletions(-)
-
---- a/drivers/s390/scsi/zfcp_fsf.c 2009-07-01 12:26:28.000000000 +0200
-+++ b/drivers/s390/scsi/zfcp_fsf.c 2009-07-01 12:28:43.000000000 +0200
-@@ -1012,6 +1012,23 @@ skip_fsfstatus:
- send_ct->handler(send_ct->handler_data);
- }
-
-+static void zfcp_fsf_setup_ct_els_unchained(struct qdio_buffer_element *sbale,
-+ struct scatterlist *sg_req,
-+ struct scatterlist *sg_resp)
-+{
-+ sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
-+ sbale[2].addr = sg_virt(sg_req);
-+ sbale[2].length = sg_req->length;
-+ sbale[3].addr = sg_virt(sg_resp);
-+ sbale[3].length = sg_resp->length;
-+ sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
-+}
-+
-+static int zfcp_fsf_one_sbal(struct scatterlist *sg)
-+{
-+ return sg_is_last(sg) && sg->length <= PAGE_SIZE;
-+}
-+
- static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
- struct scatterlist *sg_req,
- struct scatterlist *sg_resp,
-@@ -1022,16 +1039,16 @@ static int zfcp_fsf_setup_ct_els_sbals(s
- int bytes;
-
- if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
-- if (sg_req->length > PAGE_SIZE || sg_resp->length > PAGE_SIZE ||
-- !sg_is_last(sg_req) || !sg_is_last(sg_resp))
-+ if (!zfcp_fsf_one_sbal(sg_req) || !zfcp_fsf_one_sbal(sg_resp))
- return -EOPNOTSUPP;
-
-- sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
-- sbale[2].addr = sg_virt(sg_req);
-- sbale[2].length = sg_req->length;
-- sbale[3].addr = sg_virt(sg_resp);
-- sbale[3].length = sg_resp->length;
-- sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
-+ zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp);
-+ return 0;
-+ }
-+
-+ /* use single, unchained SBAL if it can hold the request */
-+ if (zfcp_fsf_one_sbal(sg_req) && zfcp_fsf_one_sbal(sg_resp)) {
-+ zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp);
- return 0;
- }
-