diff options
author | Christof Schmitt <christof.schmitt@de.ibm.com> | 2009-11-24 10:54:13 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-12-04 13:02:15 -0500 |
commit | 7c7dc196814b9e1d5cc254dc579a5fa78ae524f7 (patch) | |
tree | efe4800a456fa97e1f10876840fbde0983264b18 /drivers/s390/scsi/zfcp_fc.c | |
parent | 800c0cad962dcf630cabf3efdc5983619e73d4c9 (diff) |
[SCSI] zfcp: Simplify handling of ct and els requests
Remove some redundancies in FC related code and trace:
- drop redundant data from SAN trace (local s_id that only changes
during link down, ls_code that is already part of payload, d_id in
ct response trace that is always the same as in ct request trace)
- use one common fsf struct to hold zfcp data for ct and els requests
- leverage common fsf struct for FC passthrough job data, allocate it
with dd_bsg_data for passthrough requests and unify common code for
ct and els passthrough request
- simplify callback handling in zfcp_fc
Reviewed-by: Swen Schillig <swen@vnet.ibm.com>
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/s390/scsi/zfcp_fc.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_fc.c | 253 |
1 files changed, 92 insertions, 161 deletions
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index d6d1e78ba0f9..6d5ccc053e3a 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c | |||
@@ -22,12 +22,6 @@ static u32 zfcp_fc_rscn_range_mask[] = { | |||
22 | [ELS_ADDR_FMT_FAB] = 0x000000, | 22 | [ELS_ADDR_FMT_FAB] = 0x000000, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | struct zfcp_fc_ns_handler_data { | ||
26 | struct completion done; | ||
27 | void (*handler)(unsigned long); | ||
28 | unsigned long handler_data; | ||
29 | }; | ||
30 | |||
31 | static int zfcp_fc_wka_port_get(struct zfcp_fc_wka_port *wka_port) | 25 | static int zfcp_fc_wka_port_get(struct zfcp_fc_wka_port *wka_port) |
32 | { | 26 | { |
33 | if (mutex_lock_interruptible(&wka_port->mutex)) | 27 | if (mutex_lock_interruptible(&wka_port->mutex)) |
@@ -211,21 +205,10 @@ void zfcp_fc_incoming_els(struct zfcp_fsf_req *fsf_req) | |||
211 | zfcp_fc_incoming_rscn(fsf_req); | 205 | zfcp_fc_incoming_rscn(fsf_req); |
212 | } | 206 | } |
213 | 207 | ||
214 | static void zfcp_fc_ns_handler(unsigned long data) | 208 | static void zfcp_fc_ns_gid_pn_eval(void *data) |
215 | { | ||
216 | struct zfcp_fc_ns_handler_data *compl_rec = | ||
217 | (struct zfcp_fc_ns_handler_data *) data; | ||
218 | |||
219 | if (compl_rec->handler) | ||
220 | compl_rec->handler(compl_rec->handler_data); | ||
221 | |||
222 | complete(&compl_rec->done); | ||
223 | } | ||
224 | |||
225 | static void zfcp_fc_ns_gid_pn_eval(unsigned long data) | ||
226 | { | 209 | { |
227 | struct zfcp_fc_gid_pn *gid_pn = (struct zfcp_fc_gid_pn *) data; | 210 | struct zfcp_fc_gid_pn *gid_pn = data; |
228 | struct zfcp_send_ct *ct = &gid_pn->ct; | 211 | struct zfcp_fsf_ct_els *ct = &gid_pn->ct; |
229 | struct zfcp_fc_gid_pn_req *gid_pn_req = sg_virt(ct->req); | 212 | struct zfcp_fc_gid_pn_req *gid_pn_req = sg_virt(ct->req); |
230 | struct zfcp_fc_gid_pn_resp *gid_pn_resp = sg_virt(ct->resp); | 213 | struct zfcp_fc_gid_pn_resp *gid_pn_resp = sg_virt(ct->resp); |
231 | struct zfcp_port *port = gid_pn->port; | 214 | struct zfcp_port *port = gid_pn->port; |
@@ -242,18 +225,22 @@ static void zfcp_fc_ns_gid_pn_eval(unsigned long data) | |||
242 | port->d_id = ntoh24(gid_pn_resp->gid_pn.fp_fid); | 225 | port->d_id = ntoh24(gid_pn_resp->gid_pn.fp_fid); |
243 | } | 226 | } |
244 | 227 | ||
228 | static void zfcp_fc_complete(void *data) | ||
229 | { | ||
230 | complete(data); | ||
231 | } | ||
232 | |||
245 | static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port, | 233 | static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port, |
246 | struct zfcp_fc_gid_pn *gid_pn) | 234 | struct zfcp_fc_gid_pn *gid_pn) |
247 | { | 235 | { |
248 | struct zfcp_adapter *adapter = port->adapter; | 236 | struct zfcp_adapter *adapter = port->adapter; |
249 | struct zfcp_fc_ns_handler_data compl_rec; | 237 | DECLARE_COMPLETION_ONSTACK(completion); |
250 | int ret; | 238 | int ret; |
251 | 239 | ||
252 | /* setup parameters for send generic command */ | 240 | /* setup parameters for send generic command */ |
253 | gid_pn->port = port; | 241 | gid_pn->port = port; |
254 | gid_pn->ct.wka_port = &adapter->gs->ds; | 242 | gid_pn->ct.handler = zfcp_fc_complete; |
255 | gid_pn->ct.handler = zfcp_fc_ns_handler; | 243 | gid_pn->ct.handler_data = &completion; |
256 | gid_pn->ct.handler_data = (unsigned long) &compl_rec; | ||
257 | gid_pn->ct.req = &gid_pn->sg_req; | 244 | gid_pn->ct.req = &gid_pn->sg_req; |
258 | gid_pn->ct.resp = &gid_pn->sg_resp; | 245 | gid_pn->ct.resp = &gid_pn->sg_resp; |
259 | sg_init_one(&gid_pn->sg_req, &gid_pn->gid_pn_req, | 246 | sg_init_one(&gid_pn->sg_req, &gid_pn->gid_pn_req, |
@@ -270,12 +257,12 @@ static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port, | |||
270 | gid_pn->gid_pn_req.ct_hdr.ct_mr_size = ZFCP_FC_CT_SIZE_PAGE / 4; | 257 | gid_pn->gid_pn_req.ct_hdr.ct_mr_size = ZFCP_FC_CT_SIZE_PAGE / 4; |
271 | gid_pn->gid_pn_req.gid_pn.fn_wwpn = port->wwpn; | 258 | gid_pn->gid_pn_req.gid_pn.fn_wwpn = port->wwpn; |
272 | 259 | ||
273 | init_completion(&compl_rec.done); | 260 | ret = zfcp_fsf_send_ct(&adapter->gs->ds, &gid_pn->ct, |
274 | compl_rec.handler = zfcp_fc_ns_gid_pn_eval; | 261 | adapter->pool.gid_pn_req); |
275 | compl_rec.handler_data = (unsigned long) gid_pn; | 262 | if (!ret) { |
276 | ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.gid_pn_req); | 263 | wait_for_completion(&completion); |
277 | if (!ret) | 264 | zfcp_fc_ns_gid_pn_eval(gid_pn); |
278 | wait_for_completion(&compl_rec.done); | 265 | } |
279 | return ret; | 266 | return ret; |
280 | } | 267 | } |
281 | 268 | ||
@@ -374,9 +361,9 @@ void zfcp_fc_plogi_evaluate(struct zfcp_port *port, struct fc_els_flogi *plogi) | |||
374 | port->supported_classes |= FC_COS_CLASS4; | 361 | port->supported_classes |= FC_COS_CLASS4; |
375 | } | 362 | } |
376 | 363 | ||
377 | static void zfcp_fc_adisc_handler(unsigned long data) | 364 | static void zfcp_fc_adisc_handler(void *data) |
378 | { | 365 | { |
379 | struct zfcp_fc_els_adisc *adisc = (struct zfcp_fc_els_adisc *) data; | 366 | struct zfcp_fc_els_adisc *adisc = data; |
380 | struct zfcp_port *port = adisc->els.port; | 367 | struct zfcp_port *port = adisc->els.port; |
381 | struct fc_els_adisc *adisc_resp = &adisc->adisc_resp; | 368 | struct fc_els_adisc *adisc_resp = &adisc->adisc_resp; |
382 | 369 | ||
@@ -414,6 +401,7 @@ static int zfcp_fc_adisc(struct zfcp_port *port) | |||
414 | if (!adisc) | 401 | if (!adisc) |
415 | return -ENOMEM; | 402 | return -ENOMEM; |
416 | 403 | ||
404 | adisc->els.port = port; | ||
417 | adisc->els.req = &adisc->req; | 405 | adisc->els.req = &adisc->req; |
418 | adisc->els.resp = &adisc->resp; | 406 | adisc->els.resp = &adisc->resp; |
419 | sg_init_one(adisc->els.req, &adisc->adisc_req, | 407 | sg_init_one(adisc->els.req, &adisc->adisc_req, |
@@ -421,21 +409,18 @@ static int zfcp_fc_adisc(struct zfcp_port *port) | |||
421 | sg_init_one(adisc->els.resp, &adisc->adisc_resp, | 409 | sg_init_one(adisc->els.resp, &adisc->adisc_resp, |
422 | sizeof(struct fc_els_adisc)); | 410 | sizeof(struct fc_els_adisc)); |
423 | 411 | ||
424 | adisc->els.adapter = adapter; | ||
425 | adisc->els.port = port; | ||
426 | adisc->els.d_id = port->d_id; | ||
427 | adisc->els.handler = zfcp_fc_adisc_handler; | 412 | adisc->els.handler = zfcp_fc_adisc_handler; |
428 | adisc->els.handler_data = (unsigned long) adisc; | 413 | adisc->els.handler_data = adisc; |
429 | adisc->els.ls_code = adisc->adisc_req.adisc_cmd = ELS_ADISC; | ||
430 | 414 | ||
431 | /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports | 415 | /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports |
432 | without FC-AL-2 capability, so we don't set it */ | 416 | without FC-AL-2 capability, so we don't set it */ |
433 | adisc->adisc_req.adisc_wwpn = fc_host_port_name(adapter->scsi_host); | 417 | adisc->adisc_req.adisc_wwpn = fc_host_port_name(adapter->scsi_host); |
434 | adisc->adisc_req.adisc_wwnn = fc_host_node_name(adapter->scsi_host); | 418 | adisc->adisc_req.adisc_wwnn = fc_host_node_name(adapter->scsi_host); |
419 | adisc->adisc_req.adisc_cmd = ELS_ADISC; | ||
435 | hton24(adisc->adisc_req.adisc_port_id, | 420 | hton24(adisc->adisc_req.adisc_port_id, |
436 | fc_host_port_id(adapter->scsi_host)); | 421 | fc_host_port_id(adapter->scsi_host)); |
437 | 422 | ||
438 | return zfcp_fsf_send_els(&adisc->els); | 423 | return zfcp_fsf_send_els(adapter, port->d_id, &adisc->els); |
439 | } | 424 | } |
440 | 425 | ||
441 | void zfcp_fc_link_test_work(struct work_struct *work) | 426 | void zfcp_fc_link_test_work(struct work_struct *work) |
@@ -520,9 +505,9 @@ out: | |||
520 | static int zfcp_fc_send_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft, | 505 | static int zfcp_fc_send_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft, |
521 | struct zfcp_adapter *adapter, int max_bytes) | 506 | struct zfcp_adapter *adapter, int max_bytes) |
522 | { | 507 | { |
523 | struct zfcp_send_ct *ct = &gpn_ft->ct; | 508 | struct zfcp_fsf_ct_els *ct = &gpn_ft->ct; |
524 | struct zfcp_fc_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req); | 509 | struct zfcp_fc_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req); |
525 | struct zfcp_fc_ns_handler_data compl_rec; | 510 | DECLARE_COMPLETION_ONSTACK(completion); |
526 | int ret; | 511 | int ret; |
527 | 512 | ||
528 | /* prepare CT IU for GPN_FT */ | 513 | /* prepare CT IU for GPN_FT */ |
@@ -537,17 +522,14 @@ static int zfcp_fc_send_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft, | |||
537 | req->gpn_ft.fn_fc4_type = FC_TYPE_FCP; | 522 | req->gpn_ft.fn_fc4_type = FC_TYPE_FCP; |
538 | 523 | ||
539 | /* prepare zfcp_send_ct */ | 524 | /* prepare zfcp_send_ct */ |
540 | ct->wka_port = &adapter->gs->ds; | 525 | ct->handler = zfcp_fc_complete; |
541 | ct->handler = zfcp_fc_ns_handler; | 526 | ct->handler_data = &completion; |
542 | ct->handler_data = (unsigned long)&compl_rec; | ||
543 | ct->req = &gpn_ft->sg_req; | 527 | ct->req = &gpn_ft->sg_req; |
544 | ct->resp = gpn_ft->sg_resp; | 528 | ct->resp = gpn_ft->sg_resp; |
545 | 529 | ||
546 | init_completion(&compl_rec.done); | 530 | ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct, NULL); |
547 | compl_rec.handler = NULL; | ||
548 | ret = zfcp_fsf_send_ct(ct, NULL); | ||
549 | if (!ret) | 531 | if (!ret) |
550 | wait_for_completion(&compl_rec.done); | 532 | wait_for_completion(&completion); |
551 | return ret; | 533 | return ret; |
552 | } | 534 | } |
553 | 535 | ||
@@ -565,13 +547,13 @@ static void zfcp_fc_validate_port(struct zfcp_port *port, struct list_head *lh) | |||
565 | list_move_tail(&port->list, lh); | 547 | list_move_tail(&port->list, lh); |
566 | } | 548 | } |
567 | 549 | ||
568 | static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft, int max_entries) | 550 | static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft, |
551 | struct zfcp_adapter *adapter, int max_entries) | ||
569 | { | 552 | { |
570 | struct zfcp_send_ct *ct = &gpn_ft->ct; | 553 | struct zfcp_fsf_ct_els *ct = &gpn_ft->ct; |
571 | struct scatterlist *sg = gpn_ft->sg_resp; | 554 | struct scatterlist *sg = gpn_ft->sg_resp; |
572 | struct fc_ct_hdr *hdr = sg_virt(sg); | 555 | struct fc_ct_hdr *hdr = sg_virt(sg); |
573 | struct fc_gpn_ft_resp *acc = sg_virt(sg); | 556 | struct fc_gpn_ft_resp *acc = sg_virt(sg); |
574 | struct zfcp_adapter *adapter = ct->wka_port->adapter; | ||
575 | struct zfcp_port *port, *tmp; | 557 | struct zfcp_port *port, *tmp; |
576 | unsigned long flags; | 558 | unsigned long flags; |
577 | LIST_HEAD(remove_lh); | 559 | LIST_HEAD(remove_lh); |
@@ -665,7 +647,7 @@ void zfcp_fc_scan_ports(struct work_struct *work) | |||
665 | for (i = 0; i < 3; i++) { | 647 | for (i = 0; i < 3; i++) { |
666 | ret = zfcp_fc_send_gpn_ft(gpn_ft, adapter, max_bytes); | 648 | ret = zfcp_fc_send_gpn_ft(gpn_ft, adapter, max_bytes); |
667 | if (!ret) { | 649 | if (!ret) { |
668 | ret = zfcp_fc_eval_gpn_ft(gpn_ft, max_entries); | 650 | ret = zfcp_fc_eval_gpn_ft(gpn_ft, adapter, max_entries); |
669 | if (ret == -EAGAIN) | 651 | if (ret == -EAGAIN) |
670 | ssleep(1); | 652 | ssleep(1); |
671 | else | 653 | else |
@@ -677,160 +659,109 @@ out: | |||
677 | zfcp_fc_wka_port_put(&adapter->gs->ds); | 659 | zfcp_fc_wka_port_put(&adapter->gs->ds); |
678 | } | 660 | } |
679 | 661 | ||
680 | 662 | static void zfcp_fc_ct_els_job_handler(void *data) | |
681 | struct zfcp_els_fc_job { | ||
682 | struct zfcp_send_els els; | ||
683 | struct fc_bsg_job *job; | ||
684 | }; | ||
685 | |||
686 | static void zfcp_fc_generic_els_handler(unsigned long data) | ||
687 | { | 663 | { |
688 | struct zfcp_els_fc_job *els_fc_job = (struct zfcp_els_fc_job *) data; | 664 | struct fc_bsg_job *job = data; |
689 | struct fc_bsg_job *job = els_fc_job->job; | 665 | struct zfcp_fsf_ct_els *zfcp_ct_els = job->dd_data; |
690 | struct fc_bsg_reply *reply = job->reply; | 666 | int status = zfcp_ct_els->status; |
667 | int reply_status; | ||
691 | 668 | ||
692 | if (els_fc_job->els.status) { | 669 | reply_status = status ? FC_CTELS_STATUS_REJECT : FC_CTELS_STATUS_OK; |
693 | /* request rejected or timed out */ | 670 | job->reply->reply_data.ctels_reply.status = reply_status; |
694 | reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_REJECT; | 671 | job->reply->reply_payload_rcv_len = job->reply_payload.payload_len; |
695 | goto out; | ||
696 | } | ||
697 | |||
698 | reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; | ||
699 | reply->reply_payload_rcv_len = job->reply_payload.payload_len; | ||
700 | |||
701 | out: | ||
702 | job->state_flags = FC_RQST_STATE_DONE; | ||
703 | job->job_done(job); | 672 | job->job_done(job); |
704 | kfree(els_fc_job); | ||
705 | } | 673 | } |
706 | 674 | ||
707 | int zfcp_fc_execute_els_fc_job(struct fc_bsg_job *job) | 675 | static int zfcp_fc_exec_els_job(struct fc_bsg_job *job, |
676 | struct zfcp_adapter *adapter) | ||
708 | { | 677 | { |
709 | struct zfcp_els_fc_job *els_fc_job; | 678 | struct zfcp_fsf_ct_els *els = job->dd_data; |
710 | struct fc_rport *rport = job->rport; | 679 | struct fc_rport *rport = job->rport; |
711 | struct Scsi_Host *shost; | ||
712 | struct zfcp_adapter *adapter; | ||
713 | struct zfcp_port *port; | 680 | struct zfcp_port *port; |
714 | u8 *port_did; | 681 | u32 d_id; |
715 | |||
716 | shost = rport ? rport_to_shost(rport) : job->shost; | ||
717 | adapter = (struct zfcp_adapter *)shost->hostdata[0]; | ||
718 | |||
719 | if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN)) | ||
720 | return -EINVAL; | ||
721 | |||
722 | els_fc_job = kzalloc(sizeof(struct zfcp_els_fc_job), GFP_KERNEL); | ||
723 | if (!els_fc_job) | ||
724 | return -ENOMEM; | ||
725 | 682 | ||
726 | els_fc_job->els.adapter = adapter; | ||
727 | if (rport) { | 683 | if (rport) { |
728 | port = zfcp_get_port_by_wwpn(adapter, rport->port_name); | 684 | port = zfcp_get_port_by_wwpn(adapter, rport->port_name); |
729 | if (!port) { | 685 | if (!port) |
730 | kfree(els_fc_job); | ||
731 | return -EINVAL; | 686 | return -EINVAL; |
732 | } | ||
733 | 687 | ||
734 | els_fc_job->els.d_id = port->d_id; | 688 | d_id = port->d_id; |
735 | put_device(&port->sysfs_device); | 689 | put_device(&port->sysfs_device); |
736 | } else { | 690 | } else |
737 | port_did = job->request->rqst_data.h_els.port_id; | 691 | d_id = ntoh24(job->request->rqst_data.h_els.port_id); |
738 | els_fc_job->els.d_id = (port_did[0] << 16) + | ||
739 | (port_did[1] << 8) + port_did[2]; | ||
740 | } | ||
741 | |||
742 | els_fc_job->els.req = job->request_payload.sg_list; | ||
743 | els_fc_job->els.resp = job->reply_payload.sg_list; | ||
744 | els_fc_job->els.handler = zfcp_fc_generic_els_handler; | ||
745 | els_fc_job->els.handler_data = (unsigned long) els_fc_job; | ||
746 | els_fc_job->job = job; | ||
747 | 692 | ||
748 | return zfcp_fsf_send_els(&els_fc_job->els); | 693 | return zfcp_fsf_send_els(adapter, d_id, els); |
749 | } | 694 | } |
750 | 695 | ||
751 | struct zfcp_ct_fc_job { | 696 | static int zfcp_fc_exec_ct_job(struct fc_bsg_job *job, |
752 | struct zfcp_send_ct ct; | 697 | struct zfcp_adapter *adapter) |
753 | struct fc_bsg_job *job; | ||
754 | }; | ||
755 | |||
756 | static void zfcp_fc_generic_ct_handler(unsigned long data) | ||
757 | { | ||
758 | struct zfcp_ct_fc_job *ct_fc_job = (struct zfcp_ct_fc_job *) data; | ||
759 | struct fc_bsg_job *job = ct_fc_job->job; | ||
760 | |||
761 | job->reply->reply_data.ctels_reply.status = ct_fc_job->ct.status ? | ||
762 | FC_CTELS_STATUS_REJECT : FC_CTELS_STATUS_OK; | ||
763 | job->reply->reply_payload_rcv_len = job->reply_payload.payload_len; | ||
764 | job->state_flags = FC_RQST_STATE_DONE; | ||
765 | job->job_done(job); | ||
766 | |||
767 | zfcp_fc_wka_port_put(ct_fc_job->ct.wka_port); | ||
768 | |||
769 | kfree(ct_fc_job); | ||
770 | } | ||
771 | |||
772 | int zfcp_fc_execute_ct_fc_job(struct fc_bsg_job *job) | ||
773 | { | 698 | { |
774 | int ret; | 699 | int ret; |
775 | u8 gs_type; | 700 | u8 gs_type; |
776 | struct fc_rport *rport = job->rport; | 701 | struct zfcp_fsf_ct_els *ct = job->dd_data; |
777 | struct Scsi_Host *shost; | 702 | struct zfcp_fc_wka_port *wka_port; |
778 | struct zfcp_adapter *adapter; | ||
779 | struct zfcp_ct_fc_job *ct_fc_job; | ||
780 | u32 preamble_word1; | 703 | u32 preamble_word1; |
781 | 704 | ||
782 | shost = rport ? rport_to_shost(rport) : job->shost; | ||
783 | |||
784 | adapter = (struct zfcp_adapter *)shost->hostdata[0]; | ||
785 | if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN)) | ||
786 | return -EINVAL; | ||
787 | |||
788 | ct_fc_job = kzalloc(sizeof(struct zfcp_ct_fc_job), GFP_KERNEL); | ||
789 | if (!ct_fc_job) | ||
790 | return -ENOMEM; | ||
791 | |||
792 | preamble_word1 = job->request->rqst_data.r_ct.preamble_word1; | 705 | preamble_word1 = job->request->rqst_data.r_ct.preamble_word1; |
793 | gs_type = (preamble_word1 & 0xff000000) >> 24; | 706 | gs_type = (preamble_word1 & 0xff000000) >> 24; |
794 | 707 | ||
795 | switch (gs_type) { | 708 | switch (gs_type) { |
796 | case FC_FST_ALIAS: | 709 | case FC_FST_ALIAS: |
797 | ct_fc_job->ct.wka_port = &adapter->gs->as; | 710 | wka_port = &adapter->gs->as; |
798 | break; | 711 | break; |
799 | case FC_FST_MGMT: | 712 | case FC_FST_MGMT: |
800 | ct_fc_job->ct.wka_port = &adapter->gs->ms; | 713 | wka_port = &adapter->gs->ms; |
801 | break; | 714 | break; |
802 | case FC_FST_TIME: | 715 | case FC_FST_TIME: |
803 | ct_fc_job->ct.wka_port = &adapter->gs->ts; | 716 | wka_port = &adapter->gs->ts; |
804 | break; | 717 | break; |
805 | case FC_FST_DIR: | 718 | case FC_FST_DIR: |
806 | ct_fc_job->ct.wka_port = &adapter->gs->ds; | 719 | wka_port = &adapter->gs->ds; |
807 | break; | 720 | break; |
808 | default: | 721 | default: |
809 | kfree(ct_fc_job); | ||
810 | return -EINVAL; /* no such service */ | 722 | return -EINVAL; /* no such service */ |
811 | } | 723 | } |
812 | 724 | ||
813 | ret = zfcp_fc_wka_port_get(ct_fc_job->ct.wka_port); | 725 | ret = zfcp_fc_wka_port_get(wka_port); |
814 | if (ret) { | 726 | if (ret) |
815 | kfree(ct_fc_job); | ||
816 | return ret; | 727 | return ret; |
817 | } | ||
818 | 728 | ||
819 | ct_fc_job->ct.req = job->request_payload.sg_list; | 729 | ret = zfcp_fsf_send_ct(wka_port, ct, NULL); |
820 | ct_fc_job->ct.resp = job->reply_payload.sg_list; | 730 | if (ret) |
821 | ct_fc_job->ct.handler = zfcp_fc_generic_ct_handler; | 731 | zfcp_fc_wka_port_put(wka_port); |
822 | ct_fc_job->ct.handler_data = (unsigned long) ct_fc_job; | ||
823 | ct_fc_job->ct.completion = NULL; | ||
824 | ct_fc_job->job = job; | ||
825 | 732 | ||
826 | ret = zfcp_fsf_send_ct(&ct_fc_job->ct, NULL); | ||
827 | if (ret) { | ||
828 | kfree(ct_fc_job); | ||
829 | zfcp_fc_wka_port_put(ct_fc_job->ct.wka_port); | ||
830 | } | ||
831 | return ret; | 733 | return ret; |
832 | } | 734 | } |
833 | 735 | ||
736 | int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job) | ||
737 | { | ||
738 | struct Scsi_Host *shost; | ||
739 | struct zfcp_adapter *adapter; | ||
740 | struct zfcp_fsf_ct_els *ct_els = job->dd_data; | ||
741 | |||
742 | shost = job->rport ? rport_to_shost(job->rport) : job->shost; | ||
743 | adapter = (struct zfcp_adapter *)shost->hostdata[0]; | ||
744 | |||
745 | if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN)) | ||
746 | return -EINVAL; | ||
747 | |||
748 | ct_els->req = job->request_payload.sg_list; | ||
749 | ct_els->resp = job->reply_payload.sg_list; | ||
750 | ct_els->handler = zfcp_fc_ct_els_job_handler; | ||
751 | ct_els->handler_data = job; | ||
752 | |||
753 | switch (job->request->msgcode) { | ||
754 | case FC_BSG_RPT_ELS: | ||
755 | case FC_BSG_HST_ELS_NOLOGIN: | ||
756 | return zfcp_fc_exec_els_job(job, adapter); | ||
757 | case FC_BSG_RPT_CT: | ||
758 | case FC_BSG_HST_CT: | ||
759 | return zfcp_fc_exec_ct_job(job, adapter); | ||
760 | default: | ||
761 | return -EINVAL; | ||
762 | } | ||
763 | } | ||
764 | |||
834 | int zfcp_fc_gs_setup(struct zfcp_adapter *adapter) | 765 | int zfcp_fc_gs_setup(struct zfcp_adapter *adapter) |
835 | { | 766 | { |
836 | struct zfcp_fc_wka_ports *wka_ports; | 767 | struct zfcp_fc_wka_ports *wka_ports; |