aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_fc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/scsi/zfcp_fc.c')
-rw-r--r--drivers/s390/scsi/zfcp_fc.c88
1 files changed, 46 insertions, 42 deletions
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index f009f2a7ec3e..eabdfe24456e 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -11,6 +11,20 @@
11 11
12#include "zfcp_ext.h" 12#include "zfcp_ext.h"
13 13
14enum rscn_address_format {
15 RSCN_PORT_ADDRESS = 0x0,
16 RSCN_AREA_ADDRESS = 0x1,
17 RSCN_DOMAIN_ADDRESS = 0x2,
18 RSCN_FABRIC_ADDRESS = 0x3,
19};
20
21static u32 rscn_range_mask[] = {
22 [RSCN_PORT_ADDRESS] = 0xFFFFFF,
23 [RSCN_AREA_ADDRESS] = 0xFFFF00,
24 [RSCN_DOMAIN_ADDRESS] = 0xFF0000,
25 [RSCN_FABRIC_ADDRESS] = 0x000000,
26};
27
14struct ct_iu_gpn_ft_req { 28struct ct_iu_gpn_ft_req {
15 struct ct_hdr header; 29 struct ct_hdr header;
16 u8 flags; 30 u8 flags;
@@ -26,9 +40,12 @@ struct gpn_ft_resp_acc {
26 u64 wwpn; 40 u64 wwpn;
27} __attribute__ ((packed)); 41} __attribute__ ((packed));
28 42
29#define ZFCP_GPN_FT_ENTRIES ((PAGE_SIZE - sizeof(struct ct_hdr)) \ 43#define ZFCP_CT_SIZE_ONE_PAGE (PAGE_SIZE - sizeof(struct ct_hdr))
30 / sizeof(struct gpn_ft_resp_acc)) 44#define ZFCP_GPN_FT_ENTRIES (ZFCP_CT_SIZE_ONE_PAGE \
45 / sizeof(struct gpn_ft_resp_acc))
31#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))
32#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)
33 50
34struct ct_iu_gpn_ft_resp { 51struct ct_iu_gpn_ft_resp {
@@ -160,22 +177,7 @@ static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req)
160 for (i = 1; i < no_entries; i++) { 177 for (i = 1; i < no_entries; i++) {
161 /* skip head and start with 1st element */ 178 /* skip head and start with 1st element */
162 fcp_rscn_element++; 179 fcp_rscn_element++;
163 switch (fcp_rscn_element->addr_format) { 180 range_mask = rscn_range_mask[fcp_rscn_element->addr_format];
164 case ZFCP_PORT_ADDRESS:
165 range_mask = ZFCP_PORTS_RANGE_PORT;
166 break;
167 case ZFCP_AREA_ADDRESS:
168 range_mask = ZFCP_PORTS_RANGE_AREA;
169 break;
170 case ZFCP_DOMAIN_ADDRESS:
171 range_mask = ZFCP_PORTS_RANGE_DOMAIN;
172 break;
173 case ZFCP_FABRIC_ADDRESS:
174 range_mask = ZFCP_PORTS_RANGE_FABRIC;
175 break;
176 default:
177 continue;
178 }
179 _zfcp_fc_incoming_rscn(fsf_req, range_mask, fcp_rscn_element); 181 _zfcp_fc_incoming_rscn(fsf_req, range_mask, fcp_rscn_element);
180 } 182 }
181 schedule_work(&fsf_req->adapter->scan_work); 183 schedule_work(&fsf_req->adapter->scan_work);
@@ -266,7 +268,6 @@ static void zfcp_fc_ns_gid_pn_eval(unsigned long data)
266 return; 268 return;
267 /* looks like a valid d_id */ 269 /* looks like a valid d_id */
268 port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK; 270 port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK;
269 atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status);
270} 271}
271 272
272int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action, 273int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action,
@@ -284,8 +285,6 @@ int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action,
284 gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT; 285 gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT;
285 gid_pn->ct.req = &gid_pn->req; 286 gid_pn->ct.req = &gid_pn->req;
286 gid_pn->ct.resp = &gid_pn->resp; 287 gid_pn->ct.resp = &gid_pn->resp;
287 gid_pn->ct.req_count = 1;
288 gid_pn->ct.resp_count = 1;
289 sg_init_one(&gid_pn->req, &gid_pn->ct_iu_req, 288 sg_init_one(&gid_pn->req, &gid_pn->ct_iu_req,
290 sizeof(struct ct_iu_gid_pn_req)); 289 sizeof(struct ct_iu_gid_pn_req));
291 sg_init_one(&gid_pn->resp, &gid_pn->ct_iu_resp, 290 sg_init_one(&gid_pn->resp, &gid_pn->ct_iu_resp,
@@ -297,7 +296,7 @@ int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action,
297 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;
298 gid_pn->ct_iu_req.header.options = ZFCP_CT_SYNCHRONOUS; 297 gid_pn->ct_iu_req.header.options = ZFCP_CT_SYNCHRONOUS;
299 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;
300 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;
301 gid_pn->ct_iu_req.wwpn = erp_action->port->wwpn; 300 gid_pn->ct_iu_req.wwpn = erp_action->port->wwpn;
302 301
303 init_completion(&compl_rec.done); 302 init_completion(&compl_rec.done);
@@ -407,8 +406,6 @@ static int zfcp_fc_adisc(struct zfcp_port *port)
407 sg_init_one(adisc->els.resp, &adisc->ls_adisc_acc, 406 sg_init_one(adisc->els.resp, &adisc->ls_adisc_acc,
408 sizeof(struct zfcp_ls_adisc)); 407 sizeof(struct zfcp_ls_adisc));
409 408
410 adisc->els.req_count = 1;
411 adisc->els.resp_count = 1;
412 adisc->els.adapter = adapter; 409 adisc->els.adapter = adapter;
413 adisc->els.port = port; 410 adisc->els.port = port;
414 adisc->els.d_id = port->d_id; 411 adisc->els.d_id = port->d_id;
@@ -448,17 +445,17 @@ void zfcp_test_link(struct zfcp_port *port)
448 zfcp_erp_port_forced_reopen(port, 0, 65, NULL); 445 zfcp_erp_port_forced_reopen(port, 0, 65, NULL);
449} 446}
450 447
451static 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)
452{ 449{
453 struct scatterlist *sg = &gpn_ft->sg_req; 450 struct scatterlist *sg = &gpn_ft->sg_req;
454 451
455 kfree(sg_virt(sg)); /* free request buffer */ 452 kfree(sg_virt(sg)); /* free request buffer */
456 zfcp_sg_free_table(gpn_ft->sg_resp, ZFCP_GPN_FT_BUFFERS); 453 zfcp_sg_free_table(gpn_ft->sg_resp, buf_num);
457 454
458 kfree(gpn_ft); 455 kfree(gpn_ft);
459} 456}
460 457
461static struct zfcp_gpn_ft *zfcp_alloc_sg_env(void) 458static struct zfcp_gpn_ft *zfcp_alloc_sg_env(int buf_num)
462{ 459{
463 struct zfcp_gpn_ft *gpn_ft; 460 struct zfcp_gpn_ft *gpn_ft;
464 struct ct_iu_gpn_ft_req *req; 461 struct ct_iu_gpn_ft_req *req;
@@ -475,8 +472,8 @@ static struct zfcp_gpn_ft *zfcp_alloc_sg_env(void)
475 } 472 }
476 sg_init_one(&gpn_ft->sg_req, req, sizeof(*req)); 473 sg_init_one(&gpn_ft->sg_req, req, sizeof(*req));
477 474
478 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)) {
479 zfcp_free_sg_env(gpn_ft); 476 zfcp_free_sg_env(gpn_ft, buf_num);
480 gpn_ft = NULL; 477 gpn_ft = NULL;
481 } 478 }
482out: 479out:
@@ -485,7 +482,8 @@ out:
485 482
486 483
487static 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,
488 struct zfcp_adapter *adapter) 485 struct zfcp_adapter *adapter,
486 int max_bytes)
489{ 487{
490 struct zfcp_send_ct *ct = &gpn_ft->ct; 488 struct zfcp_send_ct *ct = &gpn_ft->ct;
491 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);
@@ -498,8 +496,7 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
498 req->header.gs_subtype = ZFCP_CT_NAME_SERVER; 496 req->header.gs_subtype = ZFCP_CT_NAME_SERVER;
499 req->header.options = ZFCP_CT_SYNCHRONOUS; 497 req->header.options = ZFCP_CT_SYNCHRONOUS;
500 req->header.cmd_rsp_code = ZFCP_CT_GPN_FT; 498 req->header.cmd_rsp_code = ZFCP_CT_GPN_FT;
501 req->header.max_res_size = (sizeof(struct gpn_ft_resp_acc) * 499 req->header.max_res_size = max_bytes / 4;
502 (ZFCP_GPN_FT_MAX_ENTRIES - 1)) >> 2;
503 req->flags = 0; 500 req->flags = 0;
504 req->domain_id_scope = 0; 501 req->domain_id_scope = 0;
505 req->area_id_scope = 0; 502 req->area_id_scope = 0;
@@ -512,8 +509,6 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
512 ct->timeout = 10; 509 ct->timeout = 10;
513 ct->req = &gpn_ft->sg_req; 510 ct->req = &gpn_ft->sg_req;
514 ct->resp = gpn_ft->sg_resp; 511 ct->resp = gpn_ft->sg_resp;
515 ct->req_count = 1;
516 ct->resp_count = ZFCP_GPN_FT_BUFFERS;
517 512
518 init_completion(&compl_rec.done); 513 init_completion(&compl_rec.done);
519 compl_rec.handler = NULL; 514 compl_rec.handler = NULL;
@@ -540,7 +535,7 @@ static void zfcp_validate_port(struct zfcp_port *port)
540 zfcp_port_dequeue(port); 535 zfcp_port_dequeue(port);
541} 536}
542 537
543static 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)
544{ 539{
545 struct zfcp_send_ct *ct = &gpn_ft->ct; 540 struct zfcp_send_ct *ct = &gpn_ft->ct;
546 struct scatterlist *sg = gpn_ft->sg_resp; 541 struct scatterlist *sg = gpn_ft->sg_resp;
@@ -560,13 +555,17 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft)
560 return -EIO; 555 return -EIO;
561 } 556 }
562 557
563 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);
564 return -E2BIG; 562 return -E2BIG;
563 }
565 564
566 down(&zfcp_data.config_sema); 565 down(&zfcp_data.config_sema);
567 566
568 /* first entry is the header */ 567 /* first entry is the header */
569 for (x = 1; x < ZFCP_GPN_FT_MAX_ENTRIES && !last; x++) { 568 for (x = 1; x < max_entries && !last; x++) {
570 if (x % (ZFCP_GPN_FT_ENTRIES + 1)) 569 if (x % (ZFCP_GPN_FT_ENTRIES + 1))
571 acc++; 570 acc++;
572 else 571 else
@@ -589,7 +588,6 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft)
589 } 588 }
590 589
591 port = zfcp_port_enqueue(adapter, acc->wwpn, 590 port = zfcp_port_enqueue(adapter, acc->wwpn,
592 ZFCP_STATUS_PORT_DID_DID |
593 ZFCP_STATUS_COMMON_NOESC, d_id); 591 ZFCP_STATUS_COMMON_NOESC, d_id);
594 if (IS_ERR(port)) 592 if (IS_ERR(port))
595 ret = PTR_ERR(port); 593 ret = PTR_ERR(port);
@@ -612,6 +610,12 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
612{ 610{
613 int ret, i; 611 int ret, i;
614 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;
615 619
616 if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT) 620 if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT)
617 return 0; 621 return 0;
@@ -620,23 +624,23 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
620 if (ret) 624 if (ret)
621 return ret; 625 return ret;
622 626
623 gpn_ft = zfcp_alloc_sg_env(); 627 gpn_ft = zfcp_alloc_sg_env(buf_num);
624 if (!gpn_ft) { 628 if (!gpn_ft) {
625 ret = -ENOMEM; 629 ret = -ENOMEM;
626 goto out; 630 goto out;
627 } 631 }
628 632
629 for (i = 0; i < 3; i++) { 633 for (i = 0; i < 3; i++) {
630 ret = zfcp_scan_issue_gpn_ft(gpn_ft, adapter); 634 ret = zfcp_scan_issue_gpn_ft(gpn_ft, adapter, max_bytes);
631 if (!ret) { 635 if (!ret) {
632 ret = zfcp_scan_eval_gpn_ft(gpn_ft); 636 ret = zfcp_scan_eval_gpn_ft(gpn_ft, max_entries);
633 if (ret == -EAGAIN) 637 if (ret == -EAGAIN)
634 ssleep(1); 638 ssleep(1);
635 else 639 else
636 break; 640 break;
637 } 641 }
638 } 642 }
639 zfcp_free_sg_env(gpn_ft); 643 zfcp_free_sg_env(gpn_ft, buf_num);
640out: 644out:
641 zfcp_wka_port_put(&adapter->nsp); 645 zfcp_wka_port_put(&adapter->nsp);
642 return ret; 646 return ret;