1 From: Gerald Schaefer <geraldsc@de.ibm.com>
2 Subject: zfcp: Use only single SBAL commands from recovery
3 References: bnc#518291,LTC#54462
5 Symptom: Issuing an ELS request might not detect a stalled
7 Problem: zfcp uses chained SBALs for ELS requests leading to the
8 situation that the ELS request gets one free SBAL, but
9 not the following ones. In this situation the ELS request
10 fails but does not trigger the error handling for the
12 Solution: Use unchained SBALs where possible, especially for
13 commands from the erp. This guarantees that each erp
14 command will get the required SBAL or trigger queue
17 Acked-by: John Jolly <jjolly@suse.de>
19 drivers/s390/scsi/zfcp_fsf.c | 33 +++++++++++++++++++++++++--------
20 1 file changed, 25 insertions(+), 8 deletions(-)
22 --- a/drivers/s390/scsi/zfcp_fsf.c 2009-07-01 12:26:28.000000000 +0200
23 +++ b/drivers/s390/scsi/zfcp_fsf.c 2009-07-01 12:28:43.000000000 +0200
24 @@ -1012,6 +1012,23 @@ skip_fsfstatus:
25 send_ct->handler(send_ct->handler_data);
28 +static void zfcp_fsf_setup_ct_els_unchained(struct qdio_buffer_element *sbale,
29 + struct scatterlist *sg_req,
30 + struct scatterlist *sg_resp)
32 + sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
33 + sbale[2].addr = sg_virt(sg_req);
34 + sbale[2].length = sg_req->length;
35 + sbale[3].addr = sg_virt(sg_resp);
36 + sbale[3].length = sg_resp->length;
37 + sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
40 +static int zfcp_fsf_one_sbal(struct scatterlist *sg)
42 + return sg_is_last(sg) && sg->length <= PAGE_SIZE;
45 static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
46 struct scatterlist *sg_req,
47 struct scatterlist *sg_resp,
48 @@ -1022,16 +1039,16 @@ static int zfcp_fsf_setup_ct_els_sbals(s
51 if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
52 - if (sg_req->length > PAGE_SIZE || sg_resp->length > PAGE_SIZE ||
53 - !sg_is_last(sg_req) || !sg_is_last(sg_resp))
54 + if (!zfcp_fsf_one_sbal(sg_req) || !zfcp_fsf_one_sbal(sg_resp))
57 - sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
58 - sbale[2].addr = sg_virt(sg_req);
59 - sbale[2].length = sg_req->length;
60 - sbale[3].addr = sg_virt(sg_resp);
61 - sbale[3].length = sg_resp->length;
62 - sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
63 + zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp);
67 + /* use single, unchained SBAL if it can hold the request */
68 + if (zfcp_fsf_one_sbal(sg_req) && zfcp_fsf_one_sbal(sg_resp)) {
69 + zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp);