diff options
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 10 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 18 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 2 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 6 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fc.c | 188 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 15 |
6 files changed, 219 insertions, 20 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 3ac27ee47396..2ccbd185a5fb 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -470,6 +470,12 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
470 | if (!adapter) | 470 | if (!adapter) |
471 | return -ENOMEM; | 471 | return -ENOMEM; |
472 | 472 | ||
473 | adapter->gs = kzalloc(sizeof(struct zfcp_wka_ports), GFP_KERNEL); | ||
474 | if (!adapter->gs) { | ||
475 | kfree(adapter); | ||
476 | return -ENOMEM; | ||
477 | } | ||
478 | |||
473 | ccw_device->handler = NULL; | 479 | ccw_device->handler = NULL; |
474 | adapter->ccw_device = ccw_device; | 480 | adapter->ccw_device = ccw_device; |
475 | atomic_set(&adapter->refcount, 0); | 481 | atomic_set(&adapter->refcount, 0); |
@@ -523,8 +529,7 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
523 | goto sysfs_failed; | 529 | goto sysfs_failed; |
524 | 530 | ||
525 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); | 531 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); |
526 | 532 | zfcp_fc_wka_ports_init(adapter); | |
527 | zfcp_fc_nameserver_init(adapter); | ||
528 | 533 | ||
529 | if (!zfcp_adapter_scsi_register(adapter)) | 534 | if (!zfcp_adapter_scsi_register(adapter)) |
530 | return 0; | 535 | return 0; |
@@ -571,6 +576,7 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter) | |||
571 | kfree(adapter->req_list); | 576 | kfree(adapter->req_list); |
572 | kfree(adapter->fc_stats); | 577 | kfree(adapter->fc_stats); |
573 | kfree(adapter->stats_reset_data); | 578 | kfree(adapter->stats_reset_data); |
579 | kfree(adapter->gs); | ||
574 | kfree(adapter); | 580 | kfree(adapter); |
575 | } | 581 | } |
576 | 582 | ||
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 2074d45dbf6c..49d0532bca1c 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -22,6 +22,8 @@ | |||
22 | #include <linux/syscalls.h> | 22 | #include <linux/syscalls.h> |
23 | #include <linux/scatterlist.h> | 23 | #include <linux/scatterlist.h> |
24 | #include <linux/ioctl.h> | 24 | #include <linux/ioctl.h> |
25 | #include <scsi/fc/fc_fs.h> | ||
26 | #include <scsi/fc/fc_gs.h> | ||
25 | #include <scsi/scsi.h> | 27 | #include <scsi/scsi.h> |
26 | #include <scsi/scsi_tcq.h> | 28 | #include <scsi/scsi_tcq.h> |
27 | #include <scsi/scsi_cmnd.h> | 29 | #include <scsi/scsi_cmnd.h> |
@@ -29,6 +31,7 @@ | |||
29 | #include <scsi/scsi_host.h> | 31 | #include <scsi/scsi_host.h> |
30 | #include <scsi/scsi_transport.h> | 32 | #include <scsi/scsi_transport.h> |
31 | #include <scsi/scsi_transport_fc.h> | 33 | #include <scsi/scsi_transport_fc.h> |
34 | #include <scsi/scsi_bsg_fc.h> | ||
32 | #include <asm/ccwdev.h> | 35 | #include <asm/ccwdev.h> |
33 | #include <asm/qdio.h> | 36 | #include <asm/qdio.h> |
34 | #include <asm/debug.h> | 37 | #include <asm/debug.h> |
@@ -228,11 +231,6 @@ struct zfcp_ls_adisc { | |||
228 | 231 | ||
229 | /* FC-PH/FC-GS well-known address identifiers for generic services */ | 232 | /* FC-PH/FC-GS well-known address identifiers for generic services */ |
230 | #define ZFCP_DID_WKA 0xFFFFF0 | 233 | #define ZFCP_DID_WKA 0xFFFFF0 |
231 | #define ZFCP_DID_MANAGEMENT_SERVICE 0xFFFFFA | ||
232 | #define ZFCP_DID_TIME_SERVICE 0xFFFFFB | ||
233 | #define ZFCP_DID_DIRECTORY_SERVICE 0xFFFFFC | ||
234 | #define ZFCP_DID_ALIAS_SERVICE 0xFFFFF8 | ||
235 | #define ZFCP_DID_KEY_DISTRIBUTION_SERVICE 0xFFFFF7 | ||
236 | 234 | ||
237 | /* remote port status */ | 235 | /* remote port status */ |
238 | #define ZFCP_STATUS_PORT_PHYS_OPEN 0x00000001 | 236 | #define ZFCP_STATUS_PORT_PHYS_OPEN 0x00000001 |
@@ -376,6 +374,14 @@ struct zfcp_wka_port { | |||
376 | struct delayed_work work; | 374 | struct delayed_work work; |
377 | }; | 375 | }; |
378 | 376 | ||
377 | struct zfcp_wka_ports { | ||
378 | struct zfcp_wka_port ms; /* management service */ | ||
379 | struct zfcp_wka_port ts; /* time service */ | ||
380 | struct zfcp_wka_port ds; /* directory service */ | ||
381 | struct zfcp_wka_port as; /* alias service */ | ||
382 | struct zfcp_wka_port ks; /* key distribution service */ | ||
383 | }; | ||
384 | |||
379 | struct zfcp_qdio_queue { | 385 | struct zfcp_qdio_queue { |
380 | struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q]; | 386 | struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q]; |
381 | u8 first; /* index of next free bfr in queue */ | 387 | u8 first; /* index of next free bfr in queue */ |
@@ -461,7 +467,7 @@ struct zfcp_adapter { | |||
461 | actions */ | 467 | actions */ |
462 | u32 erp_low_mem_count; /* nr of erp actions waiting | 468 | u32 erp_low_mem_count; /* nr of erp actions waiting |
463 | for memory */ | 469 | for memory */ |
464 | struct zfcp_wka_port nsp; /* adapter's nameserver */ | 470 | struct zfcp_wka_ports *gs; /* generic services */ |
465 | debug_info_t *rec_dbf; | 471 | debug_info_t *rec_dbf; |
466 | debug_info_t *hba_dbf; | 472 | debug_info_t *hba_dbf; |
467 | debug_info_t *san_dbf; /* debug feature areas */ | 473 | debug_info_t *san_dbf; /* debug feature areas */ |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index e50ea465bc2b..8030e25152fb 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -719,7 +719,7 @@ static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act) | |||
719 | zfcp_qdio_close(adapter); | 719 | zfcp_qdio_close(adapter); |
720 | zfcp_fsf_req_dismiss_all(adapter); | 720 | zfcp_fsf_req_dismiss_all(adapter); |
721 | adapter->fsf_req_seq_no = 0; | 721 | adapter->fsf_req_seq_no = 0; |
722 | zfcp_fc_wka_port_force_offline(&adapter->nsp); | 722 | zfcp_fc_wka_port_force_offline(&adapter->gs->ds); |
723 | /* all ports and units are closed */ | 723 | /* all ports and units are closed */ |
724 | zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL, | 724 | zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL, |
725 | ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); | 725 | ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 120a9a1c81f7..3044c6010306 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -106,8 +106,12 @@ extern int zfcp_fc_ns_gid_pn(struct zfcp_erp_action *); | |||
106 | extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *); | 106 | extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *); |
107 | extern void zfcp_test_link(struct zfcp_port *); | 107 | extern void zfcp_test_link(struct zfcp_port *); |
108 | extern void zfcp_fc_link_test_work(struct work_struct *); | 108 | extern void zfcp_fc_link_test_work(struct work_struct *); |
109 | extern void zfcp_fc_nameserver_init(struct zfcp_adapter *); | ||
110 | extern void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *); | 109 | extern void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *); |
110 | extern void zfcp_fc_wka_ports_init(struct zfcp_adapter *); | ||
111 | extern int zfcp_fc_execute_els_fc_job(struct fc_bsg_job *); | ||
112 | extern int zfcp_fc_execute_ct_fc_job(struct fc_bsg_job *); | ||
113 | extern void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *); | ||
114 | |||
111 | 115 | ||
112 | /* zfcp_fsf.c */ | 116 | /* zfcp_fsf.c */ |
113 | extern int zfcp_fsf_open_port(struct zfcp_erp_action *); | 117 | extern int zfcp_fsf_open_port(struct zfcp_erp_action *); |
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index bb2752b4130f..da10e0df6879 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c | |||
@@ -120,14 +120,13 @@ static void zfcp_wka_port_put(struct zfcp_wka_port *wka_port) | |||
120 | schedule_delayed_work(&wka_port->work, HZ / 100); | 120 | schedule_delayed_work(&wka_port->work, HZ / 100); |
121 | } | 121 | } |
122 | 122 | ||
123 | void zfcp_fc_nameserver_init(struct zfcp_adapter *adapter) | 123 | static void zfcp_fc_wka_port_init(struct zfcp_wka_port *wka_port, u32 d_id, |
124 | struct zfcp_adapter *adapter) | ||
124 | { | 125 | { |
125 | struct zfcp_wka_port *wka_port = &adapter->nsp; | ||
126 | |||
127 | init_waitqueue_head(&wka_port->completion_wq); | 126 | init_waitqueue_head(&wka_port->completion_wq); |
128 | 127 | ||
129 | wka_port->adapter = adapter; | 128 | wka_port->adapter = adapter; |
130 | wka_port->d_id = ZFCP_DID_DIRECTORY_SERVICE; | 129 | wka_port->d_id = d_id; |
131 | 130 | ||
132 | wka_port->status = ZFCP_WKA_PORT_OFFLINE; | 131 | wka_port->status = ZFCP_WKA_PORT_OFFLINE; |
133 | atomic_set(&wka_port->refcount, 0); | 132 | atomic_set(&wka_port->refcount, 0); |
@@ -143,6 +142,17 @@ void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *wka) | |||
143 | mutex_unlock(&wka->mutex); | 142 | mutex_unlock(&wka->mutex); |
144 | } | 143 | } |
145 | 144 | ||
145 | void zfcp_fc_wka_ports_init(struct zfcp_adapter *adapter) | ||
146 | { | ||
147 | struct zfcp_wka_ports *gs = adapter->gs; | ||
148 | |||
149 | zfcp_fc_wka_port_init(&gs->ms, FC_FID_MGMT_SERV, adapter); | ||
150 | zfcp_fc_wka_port_init(&gs->ts, FC_FID_TIME_SERV, adapter); | ||
151 | zfcp_fc_wka_port_init(&gs->ds, FC_FID_DIR_SERV, adapter); | ||
152 | zfcp_fc_wka_port_init(&gs->as, FC_FID_ALIASES, adapter); | ||
153 | zfcp_fc_wka_port_init(&gs->ks, FC_FID_SEC_KEY, adapter); | ||
154 | } | ||
155 | |||
146 | static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, | 156 | static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, |
147 | struct fcp_rscn_element *elem) | 157 | struct fcp_rscn_element *elem) |
148 | { | 158 | { |
@@ -282,7 +292,7 @@ int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action, | |||
282 | 292 | ||
283 | /* setup parameters for send generic command */ | 293 | /* setup parameters for send generic command */ |
284 | gid_pn->port = erp_action->port; | 294 | gid_pn->port = erp_action->port; |
285 | gid_pn->ct.wka_port = &adapter->nsp; | 295 | gid_pn->ct.wka_port = &adapter->gs->ds; |
286 | gid_pn->ct.handler = zfcp_fc_ns_handler; | 296 | gid_pn->ct.handler = zfcp_fc_ns_handler; |
287 | gid_pn->ct.handler_data = (unsigned long) &compl_rec; | 297 | gid_pn->ct.handler_data = (unsigned long) &compl_rec; |
288 | gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT; | 298 | gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT; |
@@ -329,13 +339,13 @@ int zfcp_fc_ns_gid_pn(struct zfcp_erp_action *erp_action) | |||
329 | 339 | ||
330 | memset(gid_pn, 0, sizeof(*gid_pn)); | 340 | memset(gid_pn, 0, sizeof(*gid_pn)); |
331 | 341 | ||
332 | ret = zfcp_wka_port_get(&adapter->nsp); | 342 | ret = zfcp_wka_port_get(&adapter->gs->ds); |
333 | if (ret) | 343 | if (ret) |
334 | goto out; | 344 | goto out; |
335 | 345 | ||
336 | ret = zfcp_fc_ns_gid_pn_request(erp_action, gid_pn); | 346 | ret = zfcp_fc_ns_gid_pn_request(erp_action, gid_pn); |
337 | 347 | ||
338 | zfcp_wka_port_put(&adapter->nsp); | 348 | zfcp_wka_port_put(&adapter->gs->ds); |
339 | out: | 349 | out: |
340 | mempool_free(gid_pn, adapter->pool.data_gid_pn); | 350 | mempool_free(gid_pn, adapter->pool.data_gid_pn); |
341 | return ret; | 351 | return ret; |
@@ -525,7 +535,7 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft, | |||
525 | req->fc4_type = ZFCP_CT_SCSI_FCP; | 535 | req->fc4_type = ZFCP_CT_SCSI_FCP; |
526 | 536 | ||
527 | /* prepare zfcp_send_ct */ | 537 | /* prepare zfcp_send_ct */ |
528 | ct->wka_port = &adapter->nsp; | 538 | ct->wka_port = &adapter->gs->ds; |
529 | ct->handler = zfcp_fc_ns_handler; | 539 | ct->handler = zfcp_fc_ns_handler; |
530 | ct->handler_data = (unsigned long)&compl_rec; | 540 | ct->handler_data = (unsigned long)&compl_rec; |
531 | ct->timeout = 10; | 541 | ct->timeout = 10; |
@@ -644,7 +654,7 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter) | |||
644 | fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV) | 654 | fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV) |
645 | return 0; | 655 | return 0; |
646 | 656 | ||
647 | ret = zfcp_wka_port_get(&adapter->nsp); | 657 | ret = zfcp_wka_port_get(&adapter->gs->ds); |
648 | if (ret) | 658 | if (ret) |
649 | return ret; | 659 | return ret; |
650 | 660 | ||
@@ -666,7 +676,7 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter) | |||
666 | } | 676 | } |
667 | zfcp_free_sg_env(gpn_ft, buf_num); | 677 | zfcp_free_sg_env(gpn_ft, buf_num); |
668 | out: | 678 | out: |
669 | zfcp_wka_port_put(&adapter->nsp); | 679 | zfcp_wka_port_put(&adapter->gs->ds); |
670 | return ret; | 680 | return ret; |
671 | } | 681 | } |
672 | 682 | ||
@@ -675,3 +685,161 @@ void _zfcp_scan_ports_later(struct work_struct *work) | |||
675 | { | 685 | { |
676 | zfcp_scan_ports(container_of(work, struct zfcp_adapter, scan_work)); | 686 | zfcp_scan_ports(container_of(work, struct zfcp_adapter, scan_work)); |
677 | } | 687 | } |
688 | |||
689 | struct zfcp_els_fc_job { | ||
690 | struct zfcp_send_els els; | ||
691 | struct fc_bsg_job *job; | ||
692 | }; | ||
693 | |||
694 | static void zfcp_fc_generic_els_handler(unsigned long data) | ||
695 | { | ||
696 | struct zfcp_els_fc_job *els_fc_job = (struct zfcp_els_fc_job *) data; | ||
697 | struct fc_bsg_job *job = els_fc_job->job; | ||
698 | struct fc_bsg_reply *reply = job->reply; | ||
699 | |||
700 | if (els_fc_job->els.status) { | ||
701 | /* request rejected or timed out */ | ||
702 | reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_REJECT; | ||
703 | goto out; | ||
704 | } | ||
705 | |||
706 | reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; | ||
707 | reply->reply_payload_rcv_len = blk_rq_bytes(job->req->next_rq); | ||
708 | |||
709 | out: | ||
710 | job->state_flags = FC_RQST_STATE_DONE; | ||
711 | job->job_done(job); | ||
712 | kfree(els_fc_job); | ||
713 | } | ||
714 | |||
715 | int zfcp_fc_execute_els_fc_job(struct fc_bsg_job *job) | ||
716 | { | ||
717 | struct zfcp_els_fc_job *els_fc_job; | ||
718 | struct fc_rport *rport = job->rport; | ||
719 | struct Scsi_Host *shost; | ||
720 | struct zfcp_adapter *adapter; | ||
721 | struct zfcp_port *port; | ||
722 | u8 *port_did; | ||
723 | |||
724 | shost = rport ? rport_to_shost(rport) : job->shost; | ||
725 | adapter = (struct zfcp_adapter *)shost->hostdata[0]; | ||
726 | |||
727 | if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN)) | ||
728 | return -EINVAL; | ||
729 | |||
730 | els_fc_job = kzalloc(sizeof(struct zfcp_els_fc_job), GFP_KERNEL); | ||
731 | if (!els_fc_job) | ||
732 | return -ENOMEM; | ||
733 | |||
734 | els_fc_job->els.adapter = adapter; | ||
735 | if (rport) { | ||
736 | read_lock_irq(&zfcp_data.config_lock); | ||
737 | port = rport->dd_data; | ||
738 | if (port) | ||
739 | zfcp_port_get(port); | ||
740 | read_unlock_irq(&zfcp_data.config_lock); | ||
741 | if (!port) { | ||
742 | kfree(els_fc_job); | ||
743 | return -EINVAL; | ||
744 | } | ||
745 | els_fc_job->els.port = port; | ||
746 | els_fc_job->els.d_id = port->d_id; | ||
747 | zfcp_port_put(port); | ||
748 | } else { | ||
749 | port_did = job->request->rqst_data.h_els.port_id; | ||
750 | els_fc_job->els.d_id = (port_did[0] << 16) + | ||
751 | (port_did[1] << 8) + port_did[2]; | ||
752 | } | ||
753 | |||
754 | els_fc_job->els.req = job->request_payload.sg_list; | ||
755 | els_fc_job->els.resp = job->reply_payload.sg_list; | ||
756 | els_fc_job->els.handler = zfcp_fc_generic_els_handler; | ||
757 | els_fc_job->els.handler_data = (unsigned long) els_fc_job; | ||
758 | els_fc_job->job = job; | ||
759 | |||
760 | return zfcp_fsf_send_els(&els_fc_job->els); | ||
761 | } | ||
762 | |||
763 | struct zfcp_ct_fc_job { | ||
764 | struct zfcp_send_ct ct; | ||
765 | struct fc_bsg_job *job; | ||
766 | }; | ||
767 | |||
768 | static void zfcp_fc_generic_ct_handler(unsigned long data) | ||
769 | { | ||
770 | struct zfcp_ct_fc_job *ct_fc_job = (struct zfcp_ct_fc_job *) data; | ||
771 | struct fc_bsg_job *job = ct_fc_job->job; | ||
772 | |||
773 | job->reply->reply_data.ctels_reply.status = ct_fc_job->ct.status ? | ||
774 | FC_CTELS_STATUS_REJECT : FC_CTELS_STATUS_OK; | ||
775 | job->state_flags = FC_RQST_STATE_DONE; | ||
776 | job->reply->reply_payload_rcv_len = blk_rq_bytes(job->req->next_rq); | ||
777 | job->job_done(job); | ||
778 | |||
779 | zfcp_wka_port_put(ct_fc_job->ct.wka_port); | ||
780 | |||
781 | kfree(ct_fc_job); | ||
782 | } | ||
783 | |||
784 | int zfcp_fc_execute_ct_fc_job(struct fc_bsg_job *job) | ||
785 | { | ||
786 | int ret; | ||
787 | u8 gs_type; | ||
788 | struct fc_rport *rport = job->rport; | ||
789 | struct Scsi_Host *shost; | ||
790 | struct zfcp_adapter *adapter; | ||
791 | struct zfcp_ct_fc_job *ct_fc_job; | ||
792 | u32 preamble_word1; | ||
793 | |||
794 | shost = rport ? rport_to_shost(rport) : job->shost; | ||
795 | |||
796 | adapter = (struct zfcp_adapter *)shost->hostdata[0]; | ||
797 | if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN)) | ||
798 | return -EINVAL; | ||
799 | |||
800 | ct_fc_job = kzalloc(sizeof(struct zfcp_ct_fc_job), GFP_KERNEL); | ||
801 | if (!ct_fc_job) | ||
802 | return -ENOMEM; | ||
803 | |||
804 | preamble_word1 = job->request->rqst_data.r_ct.preamble_word1; | ||
805 | gs_type = (preamble_word1 & 0xff000000) >> 24; | ||
806 | |||
807 | switch (gs_type) { | ||
808 | case FC_FST_ALIAS: | ||
809 | ct_fc_job->ct.wka_port = &adapter->gs->as; | ||
810 | break; | ||
811 | case FC_FST_MGMT: | ||
812 | ct_fc_job->ct.wka_port = &adapter->gs->ms; | ||
813 | break; | ||
814 | case FC_FST_TIME: | ||
815 | ct_fc_job->ct.wka_port = &adapter->gs->ts; | ||
816 | break; | ||
817 | case FC_FST_DIR: | ||
818 | ct_fc_job->ct.wka_port = &adapter->gs->ds; | ||
819 | break; | ||
820 | default: | ||
821 | kfree(ct_fc_job); | ||
822 | return -EINVAL; /* no such service */ | ||
823 | } | ||
824 | |||
825 | ret = zfcp_wka_port_get(ct_fc_job->ct.wka_port); | ||
826 | if (ret) { | ||
827 | kfree(ct_fc_job); | ||
828 | return ret; | ||
829 | } | ||
830 | |||
831 | ct_fc_job->ct.req = job->request_payload.sg_list; | ||
832 | ct_fc_job->ct.resp = job->reply_payload.sg_list; | ||
833 | ct_fc_job->ct.timeout = ZFCP_FSF_REQUEST_TIMEOUT; | ||
834 | ct_fc_job->ct.handler = zfcp_fc_generic_ct_handler; | ||
835 | ct_fc_job->ct.handler_data = (unsigned long) ct_fc_job; | ||
836 | ct_fc_job->ct.completion = NULL; | ||
837 | ct_fc_job->job = job; | ||
838 | |||
839 | ret = zfcp_fsf_send_ct(&ct_fc_job->ct, NULL, NULL); | ||
840 | if (ret) { | ||
841 | kfree(ct_fc_job); | ||
842 | zfcp_wka_port_put(ct_fc_job->ct.wka_port); | ||
843 | } | ||
844 | return ret; | ||
845 | } | ||
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 7d0da230eb63..967ede73f4c5 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -623,6 +623,20 @@ void zfcp_scsi_scan(struct work_struct *work) | |||
623 | zfcp_unit_put(unit); | 623 | zfcp_unit_put(unit); |
624 | } | 624 | } |
625 | 625 | ||
626 | static int zfcp_execute_fc_job(struct fc_bsg_job *job) | ||
627 | { | ||
628 | switch (job->request->msgcode) { | ||
629 | case FC_BSG_RPT_ELS: | ||
630 | case FC_BSG_HST_ELS_NOLOGIN: | ||
631 | return zfcp_fc_execute_els_fc_job(job); | ||
632 | case FC_BSG_RPT_CT: | ||
633 | case FC_BSG_HST_CT: | ||
634 | return zfcp_fc_execute_ct_fc_job(job); | ||
635 | default: | ||
636 | return -EINVAL; | ||
637 | } | ||
638 | } | ||
639 | |||
626 | struct fc_function_template zfcp_transport_functions = { | 640 | struct fc_function_template zfcp_transport_functions = { |
627 | .show_starget_port_id = 1, | 641 | .show_starget_port_id = 1, |
628 | .show_starget_port_name = 1, | 642 | .show_starget_port_name = 1, |
@@ -644,6 +658,7 @@ struct fc_function_template zfcp_transport_functions = { | |||
644 | .dev_loss_tmo_callbk = zfcp_scsi_dev_loss_tmo_callbk, | 658 | .dev_loss_tmo_callbk = zfcp_scsi_dev_loss_tmo_callbk, |
645 | .terminate_rport_io = zfcp_scsi_terminate_rport_io, | 659 | .terminate_rport_io = zfcp_scsi_terminate_rport_io, |
646 | .show_host_port_state = 1, | 660 | .show_host_port_state = 1, |
661 | .bsg_request = zfcp_execute_fc_job, | ||
647 | /* no functions registered for following dynamic attributes but | 662 | /* no functions registered for following dynamic attributes but |
648 | directly set by LLDD */ | 663 | directly set by LLDD */ |
649 | .show_host_port_type = 1, | 664 | .show_host_port_type = 1, |