diff options
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r-- | drivers/s390/scsi/zfcp_dbf.c | 2 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_dbf.h | 1 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 9 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fc.c | 55 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 32 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.h | 2 |
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 | ||
48 | struct ct_iu_gpn_ft_resp { | 51 | struct 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 | ||
449 | static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft) | 448 | static 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 | ||
459 | static struct zfcp_gpn_ft *zfcp_alloc_sg_env(void) | 458 | static 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 | } |
480 | out: | 479 | out: |
@@ -483,7 +482,8 @@ out: | |||
483 | 482 | ||
484 | 483 | ||
485 | static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft, | 484 | static 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 | ||
541 | static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft) | 538 | static 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); |
637 | out: | 644 | out: |
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 | ||
1016 | static int zfcp_fsf_setup_sbals(struct zfcp_fsf_req *req, | 1016 | static 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 | ||
325 | struct fsf_plogi { | 327 | struct fsf_plogi { |
326 | u32 code; | 328 | u32 code; |
327 | struct fsf_nport_serv_param serv_param; | 329 | struct fsf_nport_serv_param serv_param; |