aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_fc.c
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/scsi/zfcp_fc.c
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/scsi/zfcp_fc.c')
-rw-r--r--drivers/s390/scsi/zfcp_fc.c55
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
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;