aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorChristof Schmitt <christof.schmitt@de.ibm.com>2008-12-19 10:57:01 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-12-29 12:38:28 -0500
commit39eb7e9aca2a582330ddb6f1167272268e6b3965 (patch)
tree59045a1bdcb5d48286f244dc700482495973a018 /drivers/s390
parentb225cf9b8040849e16add4da8e84a72a3548ada8 (diff)
[SCSI] zfcp: Add support for unchained FSF requests
Add the support to send CT and ELS requests as unchained FSF requests. This is required for older hardware and was somehow omitted during the cleanup of the FSF layer. The req_count and resp_count attributes are unused, so remove them instead of adding a special case for setting them. Also add debug data and a warning, when the ct request hits a limit. Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Acked-by: Martin Petermann <martin@linux.vnet.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c2
-rw-r--r--drivers/s390/scsi/zfcp_dbf.h1
-rw-r--r--drivers/s390/scsi/zfcp_def.h9
-rw-r--r--drivers/s390/scsi/zfcp_fc.c55
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c32
-rw-r--r--drivers/s390/scsi/zfcp_fsf.h2
6 files changed, 61 insertions, 40 deletions
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index bf691fbc4d29..150bd5390b1d 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -936,6 +936,7 @@ void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
936 rct->reason_code = hdr->reason_code; 936 rct->reason_code = hdr->reason_code;
937 rct->expl = hdr->reason_code_expl; 937 rct->expl = hdr->reason_code_expl;
938 rct->vendor_unique = hdr->vendor_unique; 938 rct->vendor_unique = hdr->vendor_unique;
939 rct->max_res_size = hdr->max_res_size;
939 rct->len = min((int)ct->resp->length - (int)sizeof(struct ct_hdr), 940 rct->len = min((int)ct->resp->length - (int)sizeof(struct ct_hdr),
940 ZFCP_DBF_SAN_MAX_PAYLOAD); 941 ZFCP_DBF_SAN_MAX_PAYLOAD);
941 debug_event(adapter->san_dbf, level, r, sizeof(*r)); 942 debug_event(adapter->san_dbf, level, r, sizeof(*r));
@@ -1043,6 +1044,7 @@ static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view,
1043 zfcp_dbf_out(&p, "reason_code", "0x%02x", ct->reason_code); 1044 zfcp_dbf_out(&p, "reason_code", "0x%02x", ct->reason_code);
1044 zfcp_dbf_out(&p, "reason_code_expl", "0x%02x", ct->expl); 1045 zfcp_dbf_out(&p, "reason_code_expl", "0x%02x", ct->expl);
1045 zfcp_dbf_out(&p, "vendor_unique", "0x%02x", ct->vendor_unique); 1046 zfcp_dbf_out(&p, "vendor_unique", "0x%02x", ct->vendor_unique);
1047 zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size);
1046 } else if (strncmp(r->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 || 1048 } else if (strncmp(r->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 ||
1047 strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 || 1049 strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
1048 strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) { 1050 strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
index 5d6b2dff855b..74998ff88e57 100644
--- a/drivers/s390/scsi/zfcp_dbf.h
+++ b/drivers/s390/scsi/zfcp_dbf.h
@@ -171,6 +171,7 @@ struct zfcp_san_dbf_record_ct_response {
171 u8 reason_code; 171 u8 reason_code;
172 u8 expl; 172 u8 expl;
173 u8 vendor_unique; 173 u8 vendor_unique;
174 u16 max_res_size;
174 u32 len; 175 u32 len;
175} __attribute__ ((packed)); 176} __attribute__ ((packed));
176 177
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index ce4094966236..510662783a6f 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -197,7 +197,6 @@ struct zfcp_ls_adisc {
197#define ZFCP_CT_UNABLE_TO_PERFORM_CMD 0x09 197#define ZFCP_CT_UNABLE_TO_PERFORM_CMD 0x09
198#define ZFCP_CT_GID_PN 0x0121 198#define ZFCP_CT_GID_PN 0x0121
199#define ZFCP_CT_GPN_FT 0x0172 199#define ZFCP_CT_GPN_FT 0x0172
200#define ZFCP_CT_MAX_SIZE 0x1020
201#define ZFCP_CT_ACCEPT 0x8002 200#define ZFCP_CT_ACCEPT 0x8002
202#define ZFCP_CT_REJECT 0x8001 201#define ZFCP_CT_REJECT 0x8001
203 202
@@ -325,8 +324,6 @@ struct ct_iu_gid_pn_resp {
325 * @wka_port: port where the request is sent to 324 * @wka_port: port where the request is sent to
326 * @req: scatter-gather list for request 325 * @req: scatter-gather list for request
327 * @resp: scatter-gather list for response 326 * @resp: scatter-gather list for response
328 * @req_count: number of elements in request scatter-gather list
329 * @resp_count: number of elements in response scatter-gather list
330 * @handler: handler function (called for response to the request) 327 * @handler: handler function (called for response to the request)
331 * @handler_data: data passed to handler function 328 * @handler_data: data passed to handler function
332 * @timeout: FSF timeout for this request 329 * @timeout: FSF timeout for this request
@@ -337,8 +334,6 @@ struct zfcp_send_ct {
337 struct zfcp_wka_port *wka_port; 334 struct zfcp_wka_port *wka_port;
338 struct scatterlist *req; 335 struct scatterlist *req;
339 struct scatterlist *resp; 336 struct scatterlist *resp;
340 unsigned int req_count;
341 unsigned int resp_count;
342 void (*handler)(unsigned long); 337 void (*handler)(unsigned long);
343 unsigned long handler_data; 338 unsigned long handler_data;
344 int timeout; 339 int timeout;
@@ -363,8 +358,6 @@ struct zfcp_gid_pn_data {
363 * @d_id: destiniation id of port where request is sent to 358 * @d_id: destiniation id of port where request is sent to
364 * @req: scatter-gather list for request 359 * @req: scatter-gather list for request
365 * @resp: scatter-gather list for response 360 * @resp: scatter-gather list for response
366 * @req_count: number of elements in request scatter-gather list
367 * @resp_count: number of elements in response scatter-gather list
368 * @handler: handler function (called for response to the request) 361 * @handler: handler function (called for response to the request)
369 * @handler_data: data passed to handler function 362 * @handler_data: data passed to handler function
370 * @completion: completion for synchronization purposes 363 * @completion: completion for synchronization purposes
@@ -377,8 +370,6 @@ struct zfcp_send_els {
377 u32 d_id; 370 u32 d_id;
378 struct scatterlist *req; 371 struct scatterlist *req;
379 struct scatterlist *resp; 372 struct scatterlist *resp;
380 unsigned int req_count;
381 unsigned int resp_count;
382 void (*handler)(unsigned long); 373 void (*handler)(unsigned long);
383 unsigned long handler_data; 374 unsigned long handler_data;
384 struct completion *completion; 375 struct completion *completion;
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 217c3b04fd01..eabdfe24456e 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -40,9 +40,12 @@ struct gpn_ft_resp_acc {
40 u64 wwpn; 40 u64 wwpn;
41} __attribute__ ((packed)); 41} __attribute__ ((packed));
42 42
43#define ZFCP_GPN_FT_ENTRIES ((PAGE_SIZE - sizeof(struct ct_hdr)) \ 43#define ZFCP_CT_SIZE_ONE_PAGE (PAGE_SIZE - sizeof(struct ct_hdr))
44 / sizeof(struct gpn_ft_resp_acc)) 44#define ZFCP_GPN_FT_ENTRIES (ZFCP_CT_SIZE_ONE_PAGE \
45 / sizeof(struct gpn_ft_resp_acc))
45#define ZFCP_GPN_FT_BUFFERS 4 46#define ZFCP_GPN_FT_BUFFERS 4
47#define ZFCP_GPN_FT_MAX_SIZE (ZFCP_GPN_FT_BUFFERS * PAGE_SIZE \
48 - sizeof(struct ct_hdr))
46#define ZFCP_GPN_FT_MAX_ENTRIES ZFCP_GPN_FT_BUFFERS * (ZFCP_GPN_FT_ENTRIES + 1) 49#define ZFCP_GPN_FT_MAX_ENTRIES ZFCP_GPN_FT_BUFFERS * (ZFCP_GPN_FT_ENTRIES + 1)
47 50
48struct ct_iu_gpn_ft_resp { 51struct ct_iu_gpn_ft_resp {
@@ -282,8 +285,6 @@ int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action,
282 gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT; 285 gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT;
283 gid_pn->ct.req = &gid_pn->req; 286 gid_pn->ct.req = &gid_pn->req;
284 gid_pn->ct.resp = &gid_pn->resp; 287 gid_pn->ct.resp = &gid_pn->resp;
285 gid_pn->ct.req_count = 1;
286 gid_pn->ct.resp_count = 1;
287 sg_init_one(&gid_pn->req, &gid_pn->ct_iu_req, 288 sg_init_one(&gid_pn->req, &gid_pn->ct_iu_req,
288 sizeof(struct ct_iu_gid_pn_req)); 289 sizeof(struct ct_iu_gid_pn_req));
289 sg_init_one(&gid_pn->resp, &gid_pn->ct_iu_resp, 290 sg_init_one(&gid_pn->resp, &gid_pn->ct_iu_resp,
@@ -295,7 +296,7 @@ int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action,
295 gid_pn->ct_iu_req.header.gs_subtype = ZFCP_CT_NAME_SERVER; 296 gid_pn->ct_iu_req.header.gs_subtype = ZFCP_CT_NAME_SERVER;
296 gid_pn->ct_iu_req.header.options = ZFCP_CT_SYNCHRONOUS; 297 gid_pn->ct_iu_req.header.options = ZFCP_CT_SYNCHRONOUS;
297 gid_pn->ct_iu_req.header.cmd_rsp_code = ZFCP_CT_GID_PN; 298 gid_pn->ct_iu_req.header.cmd_rsp_code = ZFCP_CT_GID_PN;
298 gid_pn->ct_iu_req.header.max_res_size = ZFCP_CT_MAX_SIZE; 299 gid_pn->ct_iu_req.header.max_res_size = ZFCP_CT_SIZE_ONE_PAGE / 4;
299 gid_pn->ct_iu_req.wwpn = erp_action->port->wwpn; 300 gid_pn->ct_iu_req.wwpn = erp_action->port->wwpn;
300 301
301 init_completion(&compl_rec.done); 302 init_completion(&compl_rec.done);
@@ -405,8 +406,6 @@ static int zfcp_fc_adisc(struct zfcp_port *port)
405 sg_init_one(adisc->els.resp, &adisc->ls_adisc_acc, 406 sg_init_one(adisc->els.resp, &adisc->ls_adisc_acc,
406 sizeof(struct zfcp_ls_adisc)); 407 sizeof(struct zfcp_ls_adisc));
407 408
408 adisc->els.req_count = 1;
409 adisc->els.resp_count = 1;
410 adisc->els.adapter = adapter; 409 adisc->els.adapter = adapter;
411 adisc->els.port = port; 410 adisc->els.port = port;
412 adisc->els.d_id = port->d_id; 411 adisc->els.d_id = port->d_id;
@@ -446,17 +445,17 @@ void zfcp_test_link(struct zfcp_port *port)
446 zfcp_erp_port_forced_reopen(port, 0, 65, NULL); 445 zfcp_erp_port_forced_reopen(port, 0, 65, NULL);
447} 446}
448 447
449static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft) 448static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft, int buf_num)
450{ 449{
451 struct scatterlist *sg = &gpn_ft->sg_req; 450 struct scatterlist *sg = &gpn_ft->sg_req;
452 451
453 kfree(sg_virt(sg)); /* free request buffer */ 452 kfree(sg_virt(sg)); /* free request buffer */
454 zfcp_sg_free_table(gpn_ft->sg_resp, ZFCP_GPN_FT_BUFFERS); 453 zfcp_sg_free_table(gpn_ft->sg_resp, buf_num);
455 454
456 kfree(gpn_ft); 455 kfree(gpn_ft);
457} 456}
458 457
459static struct zfcp_gpn_ft *zfcp_alloc_sg_env(void) 458static struct zfcp_gpn_ft *zfcp_alloc_sg_env(int buf_num)
460{ 459{
461 struct zfcp_gpn_ft *gpn_ft; 460 struct zfcp_gpn_ft *gpn_ft;
462 struct ct_iu_gpn_ft_req *req; 461 struct ct_iu_gpn_ft_req *req;
@@ -473,8 +472,8 @@ static struct zfcp_gpn_ft *zfcp_alloc_sg_env(void)
473 } 472 }
474 sg_init_one(&gpn_ft->sg_req, req, sizeof(*req)); 473 sg_init_one(&gpn_ft->sg_req, req, sizeof(*req));
475 474
476 if (zfcp_sg_setup_table(gpn_ft->sg_resp, ZFCP_GPN_FT_BUFFERS)) { 475 if (zfcp_sg_setup_table(gpn_ft->sg_resp, buf_num)) {
477 zfcp_free_sg_env(gpn_ft); 476 zfcp_free_sg_env(gpn_ft, buf_num);
478 gpn_ft = NULL; 477 gpn_ft = NULL;
479 } 478 }
480out: 479out:
@@ -483,7 +482,8 @@ out:
483 482
484 483
485static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft, 484static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
486 struct zfcp_adapter *adapter) 485 struct zfcp_adapter *adapter,
486 int max_bytes)
487{ 487{
488 struct zfcp_send_ct *ct = &gpn_ft->ct; 488 struct zfcp_send_ct *ct = &gpn_ft->ct;
489 struct ct_iu_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req); 489 struct ct_iu_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req);
@@ -496,8 +496,7 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
496 req->header.gs_subtype = ZFCP_CT_NAME_SERVER; 496 req->header.gs_subtype = ZFCP_CT_NAME_SERVER;
497 req->header.options = ZFCP_CT_SYNCHRONOUS; 497 req->header.options = ZFCP_CT_SYNCHRONOUS;
498 req->header.cmd_rsp_code = ZFCP_CT_GPN_FT; 498 req->header.cmd_rsp_code = ZFCP_CT_GPN_FT;
499 req->header.max_res_size = (sizeof(struct gpn_ft_resp_acc) * 499 req->header.max_res_size = max_bytes / 4;
500 (ZFCP_GPN_FT_MAX_ENTRIES - 1)) >> 2;
501 req->flags = 0; 500 req->flags = 0;
502 req->domain_id_scope = 0; 501 req->domain_id_scope = 0;
503 req->area_id_scope = 0; 502 req->area_id_scope = 0;
@@ -510,8 +509,6 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
510 ct->timeout = 10; 509 ct->timeout = 10;
511 ct->req = &gpn_ft->sg_req; 510 ct->req = &gpn_ft->sg_req;
512 ct->resp = gpn_ft->sg_resp; 511 ct->resp = gpn_ft->sg_resp;
513 ct->req_count = 1;
514 ct->resp_count = ZFCP_GPN_FT_BUFFERS;
515 512
516 init_completion(&compl_rec.done); 513 init_completion(&compl_rec.done);
517 compl_rec.handler = NULL; 514 compl_rec.handler = NULL;
@@ -538,7 +535,7 @@ static void zfcp_validate_port(struct zfcp_port *port)
538 zfcp_port_dequeue(port); 535 zfcp_port_dequeue(port);
539} 536}
540 537
541static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft) 538static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
542{ 539{
543 struct zfcp_send_ct *ct = &gpn_ft->ct; 540 struct zfcp_send_ct *ct = &gpn_ft->ct;
544 struct scatterlist *sg = gpn_ft->sg_resp; 541 struct scatterlist *sg = gpn_ft->sg_resp;
@@ -558,13 +555,17 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft)
558 return -EIO; 555 return -EIO;
559 } 556 }
560 557
561 if (hdr->max_res_size) 558 if (hdr->max_res_size) {
559 dev_warn(&adapter->ccw_device->dev,
560 "The name server reported %d words residual data\n",
561 hdr->max_res_size);
562 return -E2BIG; 562 return -E2BIG;
563 }
563 564
564 down(&zfcp_data.config_sema); 565 down(&zfcp_data.config_sema);
565 566
566 /* first entry is the header */ 567 /* first entry is the header */
567 for (x = 1; x < ZFCP_GPN_FT_MAX_ENTRIES && !last; x++) { 568 for (x = 1; x < max_entries && !last; x++) {
568 if (x % (ZFCP_GPN_FT_ENTRIES + 1)) 569 if (x % (ZFCP_GPN_FT_ENTRIES + 1))
569 acc++; 570 acc++;
570 else 571 else
@@ -609,6 +610,12 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
609{ 610{
610 int ret, i; 611 int ret, i;
611 struct zfcp_gpn_ft *gpn_ft; 612 struct zfcp_gpn_ft *gpn_ft;
613 int chain, max_entries, buf_num, max_bytes;
614
615 chain = adapter->adapter_features & FSF_FEATURE_ELS_CT_CHAINED_SBALS;
616 buf_num = chain ? ZFCP_GPN_FT_BUFFERS : 1;
617 max_entries = chain ? ZFCP_GPN_FT_MAX_ENTRIES : ZFCP_GPN_FT_ENTRIES;
618 max_bytes = chain ? ZFCP_GPN_FT_MAX_SIZE : ZFCP_CT_SIZE_ONE_PAGE;
612 619
613 if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT) 620 if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT)
614 return 0; 621 return 0;
@@ -617,23 +624,23 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
617 if (ret) 624 if (ret)
618 return ret; 625 return ret;
619 626
620 gpn_ft = zfcp_alloc_sg_env(); 627 gpn_ft = zfcp_alloc_sg_env(buf_num);
621 if (!gpn_ft) { 628 if (!gpn_ft) {
622 ret = -ENOMEM; 629 ret = -ENOMEM;
623 goto out; 630 goto out;
624 } 631 }
625 632
626 for (i = 0; i < 3; i++) { 633 for (i = 0; i < 3; i++) {
627 ret = zfcp_scan_issue_gpn_ft(gpn_ft, adapter); 634 ret = zfcp_scan_issue_gpn_ft(gpn_ft, adapter, max_bytes);
628 if (!ret) { 635 if (!ret) {
629 ret = zfcp_scan_eval_gpn_ft(gpn_ft); 636 ret = zfcp_scan_eval_gpn_ft(gpn_ft, max_entries);
630 if (ret == -EAGAIN) 637 if (ret == -EAGAIN)
631 ssleep(1); 638 ssleep(1);
632 else 639 else
633 break; 640 break;
634 } 641 }
635 } 642 }
636 zfcp_free_sg_env(gpn_ft); 643 zfcp_free_sg_env(gpn_ft, buf_num);
637out: 644out:
638 zfcp_wka_port_put(&adapter->nsp); 645 zfcp_wka_port_put(&adapter->nsp);
639 return ret; 646 return ret;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 17620ecda335..9bba56b16831 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -1013,12 +1013,29 @@ skip_fsfstatus:
1013 send_ct->handler(send_ct->handler_data); 1013 send_ct->handler(send_ct->handler_data);
1014} 1014}
1015 1015
1016static int zfcp_fsf_setup_sbals(struct zfcp_fsf_req *req, 1016static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
1017 struct scatterlist *sg_req, 1017 struct scatterlist *sg_req,
1018 struct scatterlist *sg_resp, int max_sbals) 1018 struct scatterlist *sg_resp,
1019 int max_sbals)
1019{ 1020{
1021 struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(req);
1022 u32 feat = req->adapter->adapter_features;
1020 int bytes; 1023 int bytes;
1021 1024
1025 if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
1026 if (sg_req->length > PAGE_SIZE || sg_resp->length > PAGE_SIZE ||
1027 !sg_is_last(sg_req) || !sg_is_last(sg_resp))
1028 return -EOPNOTSUPP;
1029
1030 sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
1031 sbale[2].addr = sg_virt(sg_req);
1032 sbale[2].length = sg_req->length;
1033 sbale[3].addr = sg_virt(sg_resp);
1034 sbale[3].length = sg_resp->length;
1035 sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
1036 return 0;
1037 }
1038
1022 bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ, 1039 bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ,
1023 sg_req, max_sbals); 1040 sg_req, max_sbals);
1024 if (bytes <= 0) 1041 if (bytes <= 0)
@@ -1060,8 +1077,8 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
1060 goto out; 1077 goto out;
1061 } 1078 }
1062 1079
1063 ret = zfcp_fsf_setup_sbals(req, ct->req, ct->resp, 1080 ret = zfcp_fsf_setup_ct_els_sbals(req, ct->req, ct->resp,
1064 FSF_MAX_SBALS_PER_REQ); 1081 FSF_MAX_SBALS_PER_REQ);
1065 if (ret) 1082 if (ret)
1066 goto failed_send; 1083 goto failed_send;
1067 1084
@@ -1171,7 +1188,7 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els)
1171 goto out; 1188 goto out;
1172 } 1189 }
1173 1190
1174 ret = zfcp_fsf_setup_sbals(req, els->req, els->resp, 2); 1191 ret = zfcp_fsf_setup_ct_els_sbals(req, els->req, els->resp, 2);
1175 1192
1176 if (ret) 1193 if (ret)
1177 goto failed_send; 1194 goto failed_send;
@@ -1440,7 +1457,8 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
1440 * Alternately, an ADISC/PDISC ELS should suffice, as well. 1457 * Alternately, an ADISC/PDISC ELS should suffice, as well.
1441 */ 1458 */
1442 plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els; 1459 plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els;
1443 if (req->qtcb->bottom.support.els1_length >= sizeof(*plogi)) { 1460 if (req->qtcb->bottom.support.els1_length >=
1461 FSF_PLOGI_MIN_LEN) {
1444 if (plogi->serv_param.wwpn != port->wwpn) 1462 if (plogi->serv_param.wwpn != port->wwpn)
1445 port->d_id = 0; 1463 port->d_id = 0;
1446 else { 1464 else {
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index fa2a31780611..8bb200252347 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -164,6 +164,7 @@
164#define FSF_FEATURE_LUN_SHARING 0x00000004 164#define FSF_FEATURE_LUN_SHARING 0x00000004
165#define FSF_FEATURE_NOTIFICATION_LOST 0x00000008 165#define FSF_FEATURE_NOTIFICATION_LOST 0x00000008
166#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 166#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
167#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
167#define FSF_FEATURE_UPDATE_ALERT 0x00000100 168#define FSF_FEATURE_UPDATE_ALERT 0x00000100
168#define FSF_FEATURE_MEASUREMENT_DATA 0x00000200 169#define FSF_FEATURE_MEASUREMENT_DATA 0x00000200
169 170
@@ -322,6 +323,7 @@ struct fsf_nport_serv_param {
322 u8 vendor_version_level[16]; 323 u8 vendor_version_level[16];
323} __attribute__ ((packed)); 324} __attribute__ ((packed));
324 325
326#define FSF_PLOGI_MIN_LEN 112
325struct fsf_plogi { 327struct fsf_plogi {
326 u32 code; 328 u32 code;
327 struct fsf_nport_serv_param serv_param; 329 struct fsf_nport_serv_param serv_param;