aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSwen Schillig <swen@vnet.ibm.com>2011-08-15 08:40:32 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-08-27 10:37:03 -0400
commit86a9668a8d29ea711613e1cb37efa68e7c4db564 (patch)
tree58a39ba842f928bd9629cfb8468322a96fe7459f
parentdfe5bb506172307e43287b8962348fb85801c0f4 (diff)
[SCSI] zfcp: support for hardware data router
FICON Express8S supports hardware data router, which requires an adapted qdio request format. This part 2/2 exploits the functionality in zfcp. Signed-off-by: Swen Schillig <swen@vnet.ibm.com> Signed-off-by: Steffen Maier <maier@linux.vnet.ibm.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c36
-rw-r--r--drivers/s390/scsi/zfcp_def.h7
-rw-r--r--drivers/s390/scsi/zfcp_ext.h1
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c77
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c58
-rw-r--r--drivers/s390/scsi/zfcp_qdio.h66
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c10
7 files changed, 195 insertions, 60 deletions
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 96d1462e0bf5..967e7b70e977 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -163,6 +163,42 @@ void zfcp_dbf_hba_bit_err(char *tag, struct zfcp_fsf_req *req)
163 spin_unlock_irqrestore(&dbf->hba_lock, flags); 163 spin_unlock_irqrestore(&dbf->hba_lock, flags);
164} 164}
165 165
166/**
167 * zfcp_dbf_hba_def_err - trace event for deferred error messages
168 * @adapter: pointer to struct zfcp_adapter
169 * @req_id: request id which caused the deferred error message
170 * @scount: number of sbals incl. the signaling sbal
171 * @pl: array of all involved sbals
172 */
173void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount,
174 void **pl)
175{
176 struct zfcp_dbf *dbf = adapter->dbf;
177 struct zfcp_dbf_pay *payload = &dbf->pay_buf;
178 unsigned long flags;
179 u16 length;
180
181 if (!pl)
182 return;
183
184 spin_lock_irqsave(&dbf->pay_lock, flags);
185 memset(payload, 0, sizeof(*payload));
186
187 memcpy(payload->area, "def_err", 7);
188 payload->fsf_req_id = req_id;
189 payload->counter = 0;
190 length = min((u16)sizeof(struct qdio_buffer),
191 (u16)ZFCP_DBF_PAY_MAX_REC);
192
193 while ((char *)pl[payload->counter] && payload->counter < scount) {
194 memcpy(payload->data, (char *)pl[payload->counter], length);
195 debug_event(dbf->pay, 1, payload, zfcp_dbf_plen(length));
196 payload->counter++;
197 }
198
199 spin_unlock_irqrestore(&dbf->pay_lock, flags);
200}
201
166static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec, 202static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec,
167 struct zfcp_adapter *adapter, 203 struct zfcp_adapter *adapter,
168 struct zfcp_port *port, 204 struct zfcp_port *port,
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 527ba48eea57..ed5d921e82cd 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -72,6 +72,7 @@ struct zfcp_reqlist;
72#define ZFCP_STATUS_COMMON_NOESC 0x00200000 72#define ZFCP_STATUS_COMMON_NOESC 0x00200000
73 73
74/* adapter status */ 74/* adapter status */
75#define ZFCP_STATUS_ADAPTER_MB_ACT 0x00000001
75#define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002 76#define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002
76#define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED 0x00000004 77#define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED 0x00000004
77#define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008 78#define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008
@@ -314,4 +315,10 @@ struct zfcp_fsf_req {
314 void (*handler)(struct zfcp_fsf_req *); 315 void (*handler)(struct zfcp_fsf_req *);
315}; 316};
316 317
318static inline
319int zfcp_adapter_multi_buffer_active(struct zfcp_adapter *adapter)
320{
321 return atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_MB_ACT;
322}
323
317#endif /* ZFCP_DEF_H */ 324#endif /* ZFCP_DEF_H */
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 03627cfd81cd..2302e1cfb76c 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -53,6 +53,7 @@ extern void zfcp_dbf_hba_fsf_uss(char *, struct zfcp_fsf_req *);
53extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_req *); 53extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_req *);
54extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *); 54extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *);
55extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); 55extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *);
56extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **);
56extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); 57extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32);
57extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); 58extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *);
58extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); 59extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index fa86c6a28572..e9a787e2e6a5 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -936,39 +936,47 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
936 struct scatterlist *sg_resp) 936 struct scatterlist *sg_resp)
937{ 937{
938 struct zfcp_adapter *adapter = req->adapter; 938 struct zfcp_adapter *adapter = req->adapter;
939 struct zfcp_qdio *qdio = adapter->qdio;
940 struct fsf_qtcb *qtcb = req->qtcb;
939 u32 feat = adapter->adapter_features; 941 u32 feat = adapter->adapter_features;
940 int bytes;
941 942
942 if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) { 943 if (zfcp_adapter_multi_buffer_active(adapter)) {
943 if (!zfcp_qdio_sg_one_sbale(sg_req) || 944 if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req))
944 !zfcp_qdio_sg_one_sbale(sg_resp)) 945 return -EIO;
945 return -EOPNOTSUPP; 946 if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp))
947 return -EIO;
946 948
947 zfcp_fsf_setup_ct_els_unchained(adapter->qdio, &req->qdio_req, 949 zfcp_qdio_set_data_div(qdio, &req->qdio_req,
948 sg_req, sg_resp); 950 zfcp_qdio_sbale_count(sg_req));
951 zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
952 zfcp_qdio_set_scount(qdio, &req->qdio_req);
949 return 0; 953 return 0;
950 } 954 }
951 955
952 /* use single, unchained SBAL if it can hold the request */ 956 /* use single, unchained SBAL if it can hold the request */
953 if (zfcp_qdio_sg_one_sbale(sg_req) && zfcp_qdio_sg_one_sbale(sg_resp)) { 957 if (zfcp_qdio_sg_one_sbale(sg_req) && zfcp_qdio_sg_one_sbale(sg_resp)) {
954 zfcp_fsf_setup_ct_els_unchained(adapter->qdio, &req->qdio_req, 958 zfcp_fsf_setup_ct_els_unchained(qdio, &req->qdio_req,
955 sg_req, sg_resp); 959 sg_req, sg_resp);
956 return 0; 960 return 0;
957 } 961 }
958 962
959 bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req, sg_req); 963 if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS))
960 if (bytes <= 0) 964 return -EOPNOTSUPP;
965
966 if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req))
961 return -EIO; 967 return -EIO;
962 zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
963 req->qtcb->bottom.support.req_buf_length = bytes;
964 zfcp_qdio_skip_to_last_sbale(&req->qdio_req);
965 968
966 bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req, 969 qtcb->bottom.support.req_buf_length = zfcp_qdio_real_bytes(sg_req);
967 sg_resp); 970
968 req->qtcb->bottom.support.resp_buf_length = bytes; 971 zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
969 if (bytes <= 0) 972 zfcp_qdio_skip_to_last_sbale(qdio, &req->qdio_req);
973
974 if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp))
970 return -EIO; 975 return -EIO;
971 zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req); 976
977 qtcb->bottom.support.resp_buf_length = zfcp_qdio_real_bytes(sg_resp);
978
979 zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
972 980
973 return 0; 981 return 0;
974} 982}
@@ -1119,7 +1127,8 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
1119 1127
1120 req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 1128 req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1121 1129
1122 zfcp_qdio_sbal_limit(qdio, &req->qdio_req, 2); 1130 if (!zfcp_adapter_multi_buffer_active(adapter))
1131 zfcp_qdio_sbal_limit(qdio, &req->qdio_req, 2);
1123 1132
1124 ret = zfcp_fsf_setup_ct_els(req, els->req, els->resp, timeout); 1133 ret = zfcp_fsf_setup_ct_els(req, els->req, els->resp, timeout);
1125 1134
@@ -2162,7 +2171,7 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
2162 struct zfcp_fsf_req *req; 2171 struct zfcp_fsf_req *req;
2163 struct fcp_cmnd *fcp_cmnd; 2172 struct fcp_cmnd *fcp_cmnd;
2164 u8 sbtype = SBAL_SFLAGS0_TYPE_READ; 2173 u8 sbtype = SBAL_SFLAGS0_TYPE_READ;
2165 int real_bytes, retval = -EIO, dix_bytes = 0; 2174 int retval = -EIO;
2166 struct scsi_device *sdev = scsi_cmnd->device; 2175 struct scsi_device *sdev = scsi_cmnd->device;
2167 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); 2176 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
2168 struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; 2177 struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
@@ -2216,18 +2225,22 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
2216 if (scsi_prot_sg_count(scsi_cmnd)) { 2225 if (scsi_prot_sg_count(scsi_cmnd)) {
2217 zfcp_qdio_set_data_div(qdio, &req->qdio_req, 2226 zfcp_qdio_set_data_div(qdio, &req->qdio_req,
2218 scsi_prot_sg_count(scsi_cmnd)); 2227 scsi_prot_sg_count(scsi_cmnd));
2219 dix_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, 2228 retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
2229 scsi_prot_sglist(scsi_cmnd));
2230 if (retval)
2231 goto failed_scsi_cmnd;
2232 io->prot_data_length = zfcp_qdio_real_bytes(
2220 scsi_prot_sglist(scsi_cmnd)); 2233 scsi_prot_sglist(scsi_cmnd));
2221 io->prot_data_length = dix_bytes;
2222 } 2234 }
2223 2235
2224 real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, 2236 retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
2225 scsi_sglist(scsi_cmnd)); 2237 scsi_sglist(scsi_cmnd));
2226 2238 if (unlikely(retval))
2227 if (unlikely(real_bytes < 0) || unlikely(dix_bytes < 0))
2228 goto failed_scsi_cmnd; 2239 goto failed_scsi_cmnd;
2229 2240
2230 zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req); 2241 zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
2242 if (zfcp_adapter_multi_buffer_active(adapter))
2243 zfcp_qdio_set_scount(qdio, &req->qdio_req);
2231 2244
2232 retval = zfcp_fsf_req_send(req); 2245 retval = zfcp_fsf_req_send(req);
2233 if (unlikely(retval)) 2246 if (unlikely(retval))
@@ -2329,7 +2342,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
2329 struct zfcp_qdio *qdio = adapter->qdio; 2342 struct zfcp_qdio *qdio = adapter->qdio;
2330 struct zfcp_fsf_req *req = NULL; 2343 struct zfcp_fsf_req *req = NULL;
2331 struct fsf_qtcb_bottom_support *bottom; 2344 struct fsf_qtcb_bottom_support *bottom;
2332 int retval = -EIO, bytes; 2345 int retval = -EIO;
2333 u8 direction; 2346 u8 direction;
2334 2347
2335 if (!(adapter->adapter_features & FSF_FEATURE_CFDC)) 2348 if (!(adapter->adapter_features & FSF_FEATURE_CFDC))
@@ -2362,13 +2375,17 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
2362 bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE; 2375 bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
2363 bottom->option = fsf_cfdc->option; 2376 bottom->option = fsf_cfdc->option;
2364 2377
2365 bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, fsf_cfdc->sg); 2378 retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, fsf_cfdc->sg);
2366 2379
2367 if (bytes != ZFCP_CFDC_MAX_SIZE) { 2380 if (retval ||
2381 (zfcp_qdio_real_bytes(fsf_cfdc->sg) != ZFCP_CFDC_MAX_SIZE)) {
2368 zfcp_fsf_req_free(req); 2382 zfcp_fsf_req_free(req);
2383 retval = -EIO;
2369 goto out; 2384 goto out;
2370 } 2385 }
2371 zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req); 2386 zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
2387 if (zfcp_adapter_multi_buffer_active(adapter))
2388 zfcp_qdio_set_scount(qdio, &req->qdio_req);
2372 2389
2373 zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); 2390 zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
2374 retval = zfcp_fsf_req_send(req); 2391 retval = zfcp_fsf_req_send(req);
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index d9c40ea73eef..df9e69f54742 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -15,6 +15,10 @@
15 15
16#define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer)) 16#define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer))
17 17
18static bool enable_multibuffer;
19module_param_named(datarouter, enable_multibuffer, bool, 0400);
20MODULE_PARM_DESC(datarouter, "Enable hardware data router support");
21
18static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal) 22static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal)
19{ 23{
20 int pos; 24 int pos;
@@ -37,8 +41,11 @@ static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id,
37 41
38 dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n"); 42 dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n");
39 43
40 if (qdio_err & QDIO_ERROR_SLSB_STATE) 44 if (qdio_err & QDIO_ERROR_SLSB_STATE) {
41 zfcp_qdio_siosl(adapter); 45 zfcp_qdio_siosl(adapter);
46 zfcp_erp_adapter_shutdown(adapter, 0, id);
47 return;
48 }
42 zfcp_erp_adapter_reopen(adapter, 49 zfcp_erp_adapter_reopen(adapter,
43 ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | 50 ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
44 ZFCP_STATUS_COMMON_ERP_FAILED, id); 51 ZFCP_STATUS_COMMON_ERP_FAILED, id);
@@ -93,9 +100,27 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
93 unsigned long parm) 100 unsigned long parm)
94{ 101{
95 struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm; 102 struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
96 int sbal_idx, sbal_no; 103 struct zfcp_adapter *adapter = qdio->adapter;
104 struct qdio_buffer_element *sbale;
105 int sbal_no, sbal_idx;
106 void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1];
107 u64 req_id;
108 u8 scount;
97 109
98 if (unlikely(qdio_err)) { 110 if (unlikely(qdio_err)) {
111 memset(pl, 0, ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
112 if (zfcp_adapter_multi_buffer_active(adapter)) {
113 sbale = qdio->res_q[idx]->element;
114 req_id = (u64) sbale->addr;
115 scount = sbale->scount + 1; /* incl. signaling SBAL */
116
117 for (sbal_no = 0; sbal_no < scount; sbal_no++) {
118 sbal_idx = (idx + sbal_no) %
119 QDIO_MAX_BUFFERS_PER_Q;
120 pl[sbal_no] = qdio->res_q[sbal_idx];
121 }
122 zfcp_dbf_hba_def_err(adapter, req_id, scount, pl);
123 }
99 zfcp_qdio_handler_error(qdio, "qdires1", qdio_err); 124 zfcp_qdio_handler_error(qdio, "qdires1", qdio_err);
100 return; 125 return;
101 } 126 }
@@ -155,7 +180,7 @@ zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
155static struct qdio_buffer_element * 180static struct qdio_buffer_element *
156zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) 181zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
157{ 182{
158 if (q_req->sbale_curr == ZFCP_QDIO_LAST_SBALE_PER_SBAL) 183 if (q_req->sbale_curr == qdio->max_sbale_per_sbal - 1)
159 return zfcp_qdio_sbal_chain(qdio, q_req); 184 return zfcp_qdio_sbal_chain(qdio, q_req);
160 q_req->sbale_curr++; 185 q_req->sbale_curr++;
161 return zfcp_qdio_sbale_curr(qdio, q_req); 186 return zfcp_qdio_sbale_curr(qdio, q_req);
@@ -167,13 +192,12 @@ zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
167 * @q_req: pointer to struct zfcp_qdio_req 192 * @q_req: pointer to struct zfcp_qdio_req
168 * @sg: scatter-gather list 193 * @sg: scatter-gather list
169 * @max_sbals: upper bound for number of SBALs to be used 194 * @max_sbals: upper bound for number of SBALs to be used
170 * Returns: number of bytes, or error (negativ) 195 * Returns: zero or -EINVAL on error
171 */ 196 */
172int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, 197int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
173 struct scatterlist *sg) 198 struct scatterlist *sg)
174{ 199{
175 struct qdio_buffer_element *sbale; 200 struct qdio_buffer_element *sbale;
176 int bytes = 0;
177 201
178 /* set storage-block type for this request */ 202 /* set storage-block type for this request */
179 sbale = zfcp_qdio_sbale_req(qdio, q_req); 203 sbale = zfcp_qdio_sbale_req(qdio, q_req);
@@ -187,14 +211,10 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
187 q_req->sbal_number); 211 q_req->sbal_number);
188 return -EINVAL; 212 return -EINVAL;
189 } 213 }
190
191 sbale->addr = sg_virt(sg); 214 sbale->addr = sg_virt(sg);
192 sbale->length = sg->length; 215 sbale->length = sg->length;
193
194 bytes += sg->length;
195 } 216 }
196 217 return 0;
197 return bytes;
198} 218}
199 219
200static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio) 220static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
@@ -283,6 +303,8 @@ static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
283 memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8); 303 memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8);
284 ASCEBC(id->adapter_name, 8); 304 ASCEBC(id->adapter_name, 8);
285 id->qib_rflags = QIB_RFLAGS_ENABLE_DATA_DIV; 305 id->qib_rflags = QIB_RFLAGS_ENABLE_DATA_DIV;
306 if (enable_multibuffer)
307 id->qdr_ac |= QDR_AC_MULTI_BUFFER_ENABLE;
286 id->no_input_qs = 1; 308 id->no_input_qs = 1;
287 id->no_output_qs = 1; 309 id->no_output_qs = 1;
288 id->input_handler = zfcp_qdio_int_resp; 310 id->input_handler = zfcp_qdio_int_resp;
@@ -378,6 +400,17 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio)
378 atomic_set_mask(ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED, 400 atomic_set_mask(ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED,
379 &qdio->adapter->status); 401 &qdio->adapter->status);
380 402
403 if (ssqd.qdioac2 & CHSC_AC2_MULTI_BUFFER_ENABLED) {
404 atomic_set_mask(ZFCP_STATUS_ADAPTER_MB_ACT, &adapter->status);
405 qdio->max_sbale_per_sbal = QDIO_MAX_ELEMENTS_PER_BUFFER;
406 } else {
407 atomic_clear_mask(ZFCP_STATUS_ADAPTER_MB_ACT, &adapter->status);
408 qdio->max_sbale_per_sbal = QDIO_MAX_ELEMENTS_PER_BUFFER - 1;
409 }
410
411 qdio->max_sbale_per_req =
412 ZFCP_QDIO_MAX_SBALS_PER_REQ * qdio->max_sbale_per_sbal
413 - 2;
381 if (qdio_activate(cdev)) 414 if (qdio_activate(cdev))
382 goto failed_qdio; 415 goto failed_qdio;
383 416
@@ -397,6 +430,11 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio)
397 atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q); 430 atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q);
398 atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status); 431 atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
399 432
433 if (adapter->scsi_host) {
434 adapter->scsi_host->sg_tablesize = qdio->max_sbale_per_req;
435 adapter->scsi_host->max_sectors = qdio->max_sbale_per_req * 8;
436 }
437
400 return 0; 438 return 0;
401 439
402failed_qdio: 440failed_qdio:
diff --git a/drivers/s390/scsi/zfcp_qdio.h b/drivers/s390/scsi/zfcp_qdio.h
index 54e22ace012b..8ac7f5342d29 100644
--- a/drivers/s390/scsi/zfcp_qdio.h
+++ b/drivers/s390/scsi/zfcp_qdio.h
@@ -13,20 +13,9 @@
13 13
14#define ZFCP_QDIO_SBALE_LEN PAGE_SIZE 14#define ZFCP_QDIO_SBALE_LEN PAGE_SIZE
15 15
16/* DMQ bug workaround: don't use last SBALE */
17#define ZFCP_QDIO_MAX_SBALES_PER_SBAL (QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
18
19/* index of last SBALE (with respect to DMQ bug workaround) */
20#define ZFCP_QDIO_LAST_SBALE_PER_SBAL (ZFCP_QDIO_MAX_SBALES_PER_SBAL - 1)
21
22/* Max SBALS for chaining */ 16/* Max SBALS for chaining */
23#define ZFCP_QDIO_MAX_SBALS_PER_REQ 36 17#define ZFCP_QDIO_MAX_SBALS_PER_REQ 36
24 18
25/* max. number of (data buffer) SBALEs in largest SBAL chain
26 * request ID + QTCB in SBALE 0 + 1 of first SBAL in chain */
27#define ZFCP_QDIO_MAX_SBALES_PER_REQ \
28 (ZFCP_QDIO_MAX_SBALS_PER_REQ * ZFCP_QDIO_MAX_SBALES_PER_SBAL - 2)
29
30/** 19/**
31 * struct zfcp_qdio - basic qdio data structure 20 * struct zfcp_qdio - basic qdio data structure
32 * @res_q: response queue 21 * @res_q: response queue
@@ -53,6 +42,8 @@ struct zfcp_qdio {
53 atomic_t req_q_full; 42 atomic_t req_q_full;
54 wait_queue_head_t req_q_wq; 43 wait_queue_head_t req_q_wq;
55 struct zfcp_adapter *adapter; 44 struct zfcp_adapter *adapter;
45 u16 max_sbale_per_sbal;
46 u16 max_sbale_per_req;
56}; 47};
57 48
58/** 49/**
@@ -155,7 +146,7 @@ void zfcp_qdio_fill_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
155{ 146{
156 struct qdio_buffer_element *sbale; 147 struct qdio_buffer_element *sbale;
157 148
158 BUG_ON(q_req->sbale_curr == ZFCP_QDIO_LAST_SBALE_PER_SBAL); 149 BUG_ON(q_req->sbale_curr == qdio->max_sbale_per_sbal - 1);
159 q_req->sbale_curr++; 150 q_req->sbale_curr++;
160 sbale = zfcp_qdio_sbale_curr(qdio, q_req); 151 sbale = zfcp_qdio_sbale_curr(qdio, q_req);
161 sbale->addr = data; 152 sbale->addr = data;
@@ -195,9 +186,10 @@ int zfcp_qdio_sg_one_sbale(struct scatterlist *sg)
195 * @q_req: The current zfcp_qdio_req 186 * @q_req: The current zfcp_qdio_req
196 */ 187 */
197static inline 188static inline
198void zfcp_qdio_skip_to_last_sbale(struct zfcp_qdio_req *q_req) 189void zfcp_qdio_skip_to_last_sbale(struct zfcp_qdio *qdio,
190 struct zfcp_qdio_req *q_req)
199{ 191{
200 q_req->sbale_curr = ZFCP_QDIO_LAST_SBALE_PER_SBAL; 192 q_req->sbale_curr = qdio->max_sbale_per_sbal - 1;
201} 193}
202 194
203/** 195/**
@@ -228,8 +220,52 @@ void zfcp_qdio_set_data_div(struct zfcp_qdio *qdio,
228{ 220{
229 struct qdio_buffer_element *sbale; 221 struct qdio_buffer_element *sbale;
230 222
231 sbale = &qdio->req_q[q_req->sbal_first]->element[0]; 223 sbale = qdio->req_q[q_req->sbal_first]->element;
232 sbale->length = count; 224 sbale->length = count;
233} 225}
234 226
227/**
228 * zfcp_qdio_sbale_count - count sbale used
229 * @sg: pointer to struct scatterlist
230 */
231static inline
232unsigned int zfcp_qdio_sbale_count(struct scatterlist *sg)
233{
234 unsigned int count = 0;
235
236 for (; sg; sg = sg_next(sg))
237 count++;
238
239 return count;
240}
241
242/**
243 * zfcp_qdio_real_bytes - count bytes used
244 * @sg: pointer to struct scatterlist
245 */
246static inline
247unsigned int zfcp_qdio_real_bytes(struct scatterlist *sg)
248{
249 unsigned int real_bytes = 0;
250
251 for (; sg; sg = sg_next(sg))
252 real_bytes += sg->length;
253
254 return real_bytes;
255}
256
257/**
258 * zfcp_qdio_set_scount - set SBAL count value
259 * @qdio: pointer to struct zfcp_qdio
260 * @q_req: The current zfcp_qdio_req
261 */
262static inline
263void zfcp_qdio_set_scount(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
264{
265 struct qdio_buffer_element *sbale;
266
267 sbale = qdio->req_q[q_req->sbal_first]->element;
268 sbale->scount = q_req->sbal_number - 1;
269}
270
235#endif /* ZFCP_QDIO_H */ 271#endif /* ZFCP_QDIO_H */
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 96c31a70445f..09126a9d62ff 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -306,8 +306,8 @@ static struct scsi_host_template zfcp_scsi_host_template = {
306 .proc_name = "zfcp", 306 .proc_name = "zfcp",
307 .can_queue = 4096, 307 .can_queue = 4096,
308 .this_id = -1, 308 .this_id = -1,
309 .sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ, 309 .sg_tablesize = 1, /* adjusted later */
310 .max_sectors = (ZFCP_QDIO_MAX_SBALES_PER_REQ * 8), 310 .max_sectors = 8, /* adjusted later */
311 .dma_boundary = ZFCP_QDIO_SBALE_LEN - 1, 311 .dma_boundary = ZFCP_QDIO_SBALE_LEN - 1,
312 .cmd_per_lun = 1, 312 .cmd_per_lun = 1,
313 .use_clustering = 1, 313 .use_clustering = 1,
@@ -665,9 +665,9 @@ void zfcp_scsi_set_prot(struct zfcp_adapter *adapter)
665 adapter->adapter_features & FSF_FEATURE_DIX_PROT_TCPIP) { 665 adapter->adapter_features & FSF_FEATURE_DIX_PROT_TCPIP) {
666 mask |= SHOST_DIX_TYPE1_PROTECTION; 666 mask |= SHOST_DIX_TYPE1_PROTECTION;
667 scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP); 667 scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP);
668 shost->sg_prot_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2; 668 shost->sg_prot_tablesize = adapter->qdio->max_sbale_per_req / 2;
669 shost->sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2; 669 shost->sg_tablesize = adapter->qdio->max_sbale_per_req / 2;
670 shost->max_sectors = ZFCP_QDIO_MAX_SBALES_PER_REQ * 8 / 2; 670 shost->max_sectors = shost->sg_tablesize * 8;
671 } 671 }
672 672
673 scsi_host_set_prot(shost, mask); 673 scsi_host_set_prot(shost, mask);