diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_fc.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_fc.c | 55 |
1 files changed, 31 insertions, 24 deletions
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; |