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 | |
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')
-rw-r--r-- | drivers/s390/scsi/zfcp_dbf.c | 56 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_dbf.h | 7 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 46 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 12 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fc.c | 253 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fc.h | 7 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 28 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.h | 18 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 18 |
9 files changed, 160 insertions, 285 deletions
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 517f196b4c52..84450955ae11 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c | |||
@@ -179,7 +179,6 @@ void _zfcp_dbf_hba_fsf_response(const char *tag2, int level, | |||
179 | case FSF_QTCB_SEND_ELS: | 179 | case FSF_QTCB_SEND_ELS: |
180 | send_els = (struct zfcp_send_els *)fsf_req->data; | 180 | send_els = (struct zfcp_send_els *)fsf_req->data; |
181 | response->u.els.d_id = ntoh24(qtcb->bottom.support.d_id); | 181 | response->u.els.d_id = ntoh24(qtcb->bottom.support.d_id); |
182 | response->u.els.ls_code = send_els->ls_code >> 24; | ||
183 | break; | 182 | break; |
184 | 183 | ||
185 | case FSF_QTCB_ABORT_FCP_CMND: | 184 | case FSF_QTCB_ABORT_FCP_CMND: |
@@ -349,7 +348,6 @@ static void zfcp_dbf_hba_view_response(char **p, | |||
349 | 348 | ||
350 | case FSF_QTCB_SEND_ELS: | 349 | case FSF_QTCB_SEND_ELS: |
351 | zfcp_dbf_out(p, "d_id", "0x%06x", r->u.els.d_id); | 350 | zfcp_dbf_out(p, "d_id", "0x%06x", r->u.els.d_id); |
352 | zfcp_dbf_out(p, "ls_code", "0x%02x", r->u.els.ls_code); | ||
353 | break; | 351 | break; |
354 | 352 | ||
355 | case FSF_QTCB_ABORT_FCP_CMND: | 353 | case FSF_QTCB_ABORT_FCP_CMND: |
@@ -678,12 +676,12 @@ void zfcp_dbf_rec_action(char *id2, struct zfcp_erp_action *erp_action) | |||
678 | /** | 676 | /** |
679 | * zfcp_dbf_san_ct_request - trace event for issued CT request | 677 | * zfcp_dbf_san_ct_request - trace event for issued CT request |
680 | * @fsf_req: request containing issued CT data | 678 | * @fsf_req: request containing issued CT data |
679 | * @d_id: destination id where ct request is sent to | ||
681 | */ | 680 | */ |
682 | void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *fsf_req) | 681 | void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *fsf_req, u32 d_id) |
683 | { | 682 | { |
684 | struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; | 683 | struct zfcp_fsf_ct_els *ct = (struct zfcp_fsf_ct_els *)fsf_req->data; |
685 | struct zfcp_fc_wka_port *wka_port = ct->wka_port; | 684 | struct zfcp_adapter *adapter = fsf_req->adapter; |
686 | struct zfcp_adapter *adapter = wka_port->adapter; | ||
687 | struct zfcp_dbf *dbf = adapter->dbf; | 685 | struct zfcp_dbf *dbf = adapter->dbf; |
688 | struct fc_ct_hdr *hdr = sg_virt(ct->req); | 686 | struct fc_ct_hdr *hdr = sg_virt(ct->req); |
689 | struct zfcp_dbf_san_record *r = &dbf->san_buf; | 687 | struct zfcp_dbf_san_record *r = &dbf->san_buf; |
@@ -696,8 +694,7 @@ void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *fsf_req) | |||
696 | strncpy(r->tag, "octc", ZFCP_DBF_TAG_SIZE); | 694 | strncpy(r->tag, "octc", ZFCP_DBF_TAG_SIZE); |
697 | r->fsf_reqid = fsf_req->req_id; | 695 | r->fsf_reqid = fsf_req->req_id; |
698 | r->fsf_seqno = fsf_req->seq_no; | 696 | r->fsf_seqno = fsf_req->seq_no; |
699 | r->s_id = fc_host_port_id(adapter->scsi_host); | 697 | oct->d_id = d_id; |
700 | r->d_id = wka_port->d_id; | ||
701 | oct->cmd_req_code = hdr->ct_cmd; | 698 | oct->cmd_req_code = hdr->ct_cmd; |
702 | oct->revision = hdr->ct_rev; | 699 | oct->revision = hdr->ct_rev; |
703 | oct->gs_type = hdr->ct_fs_type; | 700 | oct->gs_type = hdr->ct_fs_type; |
@@ -718,9 +715,8 @@ void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *fsf_req) | |||
718 | */ | 715 | */ |
719 | void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *fsf_req) | 716 | void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *fsf_req) |
720 | { | 717 | { |
721 | struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; | 718 | struct zfcp_fsf_ct_els *ct = (struct zfcp_fsf_ct_els *)fsf_req->data; |
722 | struct zfcp_fc_wka_port *wka_port = ct->wka_port; | 719 | struct zfcp_adapter *adapter = fsf_req->adapter; |
723 | struct zfcp_adapter *adapter = wka_port->adapter; | ||
724 | struct fc_ct_hdr *hdr = sg_virt(ct->resp); | 720 | struct fc_ct_hdr *hdr = sg_virt(ct->resp); |
725 | struct zfcp_dbf *dbf = adapter->dbf; | 721 | struct zfcp_dbf *dbf = adapter->dbf; |
726 | struct zfcp_dbf_san_record *r = &dbf->san_buf; | 722 | struct zfcp_dbf_san_record *r = &dbf->san_buf; |
@@ -733,8 +729,6 @@ void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *fsf_req) | |||
733 | strncpy(r->tag, "rctc", ZFCP_DBF_TAG_SIZE); | 729 | strncpy(r->tag, "rctc", ZFCP_DBF_TAG_SIZE); |
734 | r->fsf_reqid = fsf_req->req_id; | 730 | r->fsf_reqid = fsf_req->req_id; |
735 | r->fsf_seqno = fsf_req->seq_no; | 731 | r->fsf_seqno = fsf_req->seq_no; |
736 | r->s_id = wka_port->d_id; | ||
737 | r->d_id = fc_host_port_id(adapter->scsi_host); | ||
738 | rct->cmd_rsp_code = hdr->ct_cmd; | 732 | rct->cmd_rsp_code = hdr->ct_cmd; |
739 | rct->revision = hdr->ct_rev; | 733 | rct->revision = hdr->ct_rev; |
740 | rct->reason_code = hdr->ct_reason; | 734 | rct->reason_code = hdr->ct_reason; |
@@ -750,8 +744,8 @@ void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *fsf_req) | |||
750 | } | 744 | } |
751 | 745 | ||
752 | static void zfcp_dbf_san_els(const char *tag, int level, | 746 | static void zfcp_dbf_san_els(const char *tag, int level, |
753 | struct zfcp_fsf_req *fsf_req, u32 s_id, u32 d_id, | 747 | struct zfcp_fsf_req *fsf_req, u32 d_id, |
754 | u8 ls_code, void *buffer, int buflen) | 748 | void *buffer, int buflen) |
755 | { | 749 | { |
756 | struct zfcp_adapter *adapter = fsf_req->adapter; | 750 | struct zfcp_adapter *adapter = fsf_req->adapter; |
757 | struct zfcp_dbf *dbf = adapter->dbf; | 751 | struct zfcp_dbf *dbf = adapter->dbf; |
@@ -763,9 +757,7 @@ static void zfcp_dbf_san_els(const char *tag, int level, | |||
763 | strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE); | 757 | strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE); |
764 | rec->fsf_reqid = fsf_req->req_id; | 758 | rec->fsf_reqid = fsf_req->req_id; |
765 | rec->fsf_seqno = fsf_req->seq_no; | 759 | rec->fsf_seqno = fsf_req->seq_no; |
766 | rec->s_id = s_id; | 760 | rec->u.els.d_id = d_id; |
767 | rec->d_id = d_id; | ||
768 | rec->u.els.ls_code = ls_code; | ||
769 | debug_event(dbf->san, level, rec, sizeof(*rec)); | 761 | debug_event(dbf->san, level, rec, sizeof(*rec)); |
770 | zfcp_dbf_hexdump(dbf->san, rec, sizeof(*rec), level, | 762 | zfcp_dbf_hexdump(dbf->san, rec, sizeof(*rec), level, |
771 | buffer, min(buflen, ZFCP_DBF_SAN_MAX_PAYLOAD)); | 763 | buffer, min(buflen, ZFCP_DBF_SAN_MAX_PAYLOAD)); |
@@ -778,12 +770,11 @@ static void zfcp_dbf_san_els(const char *tag, int level, | |||
778 | */ | 770 | */ |
779 | void zfcp_dbf_san_els_request(struct zfcp_fsf_req *fsf_req) | 771 | void zfcp_dbf_san_els_request(struct zfcp_fsf_req *fsf_req) |
780 | { | 772 | { |
781 | struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data; | 773 | struct zfcp_fsf_ct_els *els = (struct zfcp_fsf_ct_els *)fsf_req->data; |
774 | u32 d_id = ntoh24(fsf_req->qtcb->bottom.support.d_id); | ||
782 | 775 | ||
783 | zfcp_dbf_san_els("oels", 2, fsf_req, | 776 | zfcp_dbf_san_els("oels", 2, fsf_req, d_id, |
784 | fc_host_port_id(els->adapter->scsi_host), | 777 | sg_virt(els->req), els->req->length); |
785 | els->d_id, *(u8 *) sg_virt(els->req), | ||
786 | sg_virt(els->req), els->req->length); | ||
787 | } | 778 | } |
788 | 779 | ||
789 | /** | 780 | /** |
@@ -792,12 +783,11 @@ void zfcp_dbf_san_els_request(struct zfcp_fsf_req *fsf_req) | |||
792 | */ | 783 | */ |
793 | void zfcp_dbf_san_els_response(struct zfcp_fsf_req *fsf_req) | 784 | void zfcp_dbf_san_els_response(struct zfcp_fsf_req *fsf_req) |
794 | { | 785 | { |
795 | struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data; | 786 | struct zfcp_fsf_ct_els *els = (struct zfcp_fsf_ct_els *)fsf_req->data; |
787 | u32 d_id = ntoh24(fsf_req->qtcb->bottom.support.d_id); | ||
796 | 788 | ||
797 | zfcp_dbf_san_els("rels", 2, fsf_req, els->d_id, | 789 | zfcp_dbf_san_els("rels", 2, fsf_req, d_id, |
798 | fc_host_port_id(els->adapter->scsi_host), | 790 | sg_virt(els->resp), els->resp->length); |
799 | *(u8 *)sg_virt(els->req), sg_virt(els->resp), | ||
800 | els->resp->length); | ||
801 | } | 791 | } |
802 | 792 | ||
803 | /** | 793 | /** |
@@ -806,16 +796,13 @@ void zfcp_dbf_san_els_response(struct zfcp_fsf_req *fsf_req) | |||
806 | */ | 796 | */ |
807 | void zfcp_dbf_san_incoming_els(struct zfcp_fsf_req *fsf_req) | 797 | void zfcp_dbf_san_incoming_els(struct zfcp_fsf_req *fsf_req) |
808 | { | 798 | { |
809 | struct zfcp_adapter *adapter = fsf_req->adapter; | ||
810 | struct fsf_status_read_buffer *buf = | 799 | struct fsf_status_read_buffer *buf = |
811 | (struct fsf_status_read_buffer *)fsf_req->data; | 800 | (struct fsf_status_read_buffer *)fsf_req->data; |
812 | int length = (int)buf->length - | 801 | int length = (int)buf->length - |
813 | (int)((void *)&buf->payload - (void *)buf); | 802 | (int)((void *)&buf->payload - (void *)buf); |
814 | 803 | ||
815 | zfcp_dbf_san_els("iels", 1, fsf_req, ntoh24(buf->d_id), | 804 | zfcp_dbf_san_els("iels", 1, fsf_req, ntoh24(buf->d_id), |
816 | fc_host_port_id(adapter->scsi_host), | 805 | (void *)buf->payload.data, length); |
817 | buf->payload.data[0], (void *)buf->payload.data, | ||
818 | length); | ||
819 | } | 806 | } |
820 | 807 | ||
821 | static int zfcp_dbf_san_view_format(debug_info_t *id, struct debug_view *view, | 808 | static int zfcp_dbf_san_view_format(debug_info_t *id, struct debug_view *view, |
@@ -830,11 +817,10 @@ static int zfcp_dbf_san_view_format(debug_info_t *id, struct debug_view *view, | |||
830 | zfcp_dbf_tag(&p, "tag", r->tag); | 817 | zfcp_dbf_tag(&p, "tag", r->tag); |
831 | zfcp_dbf_out(&p, "fsf_reqid", "0x%0Lx", r->fsf_reqid); | 818 | zfcp_dbf_out(&p, "fsf_reqid", "0x%0Lx", r->fsf_reqid); |
832 | zfcp_dbf_out(&p, "fsf_seqno", "0x%08x", r->fsf_seqno); | 819 | zfcp_dbf_out(&p, "fsf_seqno", "0x%08x", r->fsf_seqno); |
833 | zfcp_dbf_out(&p, "s_id", "0x%06x", r->s_id); | ||
834 | zfcp_dbf_out(&p, "d_id", "0x%06x", r->d_id); | ||
835 | 820 | ||
836 | if (strncmp(r->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) { | 821 | if (strncmp(r->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) { |
837 | struct zfcp_dbf_san_record_ct_request *ct = &r->u.ct_req; | 822 | struct zfcp_dbf_san_record_ct_request *ct = &r->u.ct_req; |
823 | zfcp_dbf_out(&p, "d_id", "0x%06x", ct->d_id); | ||
838 | zfcp_dbf_out(&p, "cmd_req_code", "0x%04x", ct->cmd_req_code); | 824 | zfcp_dbf_out(&p, "cmd_req_code", "0x%04x", ct->cmd_req_code); |
839 | zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision); | 825 | zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision); |
840 | zfcp_dbf_out(&p, "gs_type", "0x%02x", ct->gs_type); | 826 | zfcp_dbf_out(&p, "gs_type", "0x%02x", ct->gs_type); |
@@ -853,7 +839,7 @@ static int zfcp_dbf_san_view_format(debug_info_t *id, struct debug_view *view, | |||
853 | strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 || | 839 | strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 || |
854 | strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) { | 840 | strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) { |
855 | struct zfcp_dbf_san_record_els *els = &r->u.els; | 841 | struct zfcp_dbf_san_record_els *els = &r->u.els; |
856 | zfcp_dbf_out(&p, "ls_code", "0x%02x", els->ls_code); | 842 | zfcp_dbf_out(&p, "d_id", "0x%06x", els->d_id); |
857 | } | 843 | } |
858 | return p - out_buf; | 844 | return p - out_buf; |
859 | } | 845 | } |
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index c3e25702df5b..8b7fd9a1033e 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h | |||
@@ -123,7 +123,6 @@ struct zfcp_dbf_hba_record_response { | |||
123 | } unit; | 123 | } unit; |
124 | struct { | 124 | struct { |
125 | u32 d_id; | 125 | u32 d_id; |
126 | u8 ls_code; | ||
127 | } els; | 126 | } els; |
128 | } u; | 127 | } u; |
129 | } __attribute__ ((packed)); | 128 | } __attribute__ ((packed)); |
@@ -167,6 +166,7 @@ struct zfcp_dbf_san_record_ct_request { | |||
167 | u8 options; | 166 | u8 options; |
168 | u16 max_res_size; | 167 | u16 max_res_size; |
169 | u32 len; | 168 | u32 len; |
169 | u32 d_id; | ||
170 | } __attribute__ ((packed)); | 170 | } __attribute__ ((packed)); |
171 | 171 | ||
172 | struct zfcp_dbf_san_record_ct_response { | 172 | struct zfcp_dbf_san_record_ct_response { |
@@ -180,16 +180,13 @@ struct zfcp_dbf_san_record_ct_response { | |||
180 | } __attribute__ ((packed)); | 180 | } __attribute__ ((packed)); |
181 | 181 | ||
182 | struct zfcp_dbf_san_record_els { | 182 | struct zfcp_dbf_san_record_els { |
183 | u8 ls_code; | 183 | u32 d_id; |
184 | u32 len; | ||
185 | } __attribute__ ((packed)); | 184 | } __attribute__ ((packed)); |
186 | 185 | ||
187 | struct zfcp_dbf_san_record { | 186 | struct zfcp_dbf_san_record { |
188 | u8 tag[ZFCP_DBF_TAG_SIZE]; | 187 | u8 tag[ZFCP_DBF_TAG_SIZE]; |
189 | u64 fsf_reqid; | 188 | u64 fsf_reqid; |
190 | u32 fsf_seqno; | 189 | u32 fsf_seqno; |
191 | u32 s_id; | ||
192 | u32 d_id; | ||
193 | union { | 190 | union { |
194 | struct zfcp_dbf_san_record_ct_request ct_req; | 191 | struct zfcp_dbf_san_record_ct_request ct_req; |
195 | struct zfcp_dbf_san_record_ct_response ct_resp; | 192 | struct zfcp_dbf_san_record_ct_response ct_resp; |
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index ea11b4e45cdc..21b29804a7a6 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -132,52 +132,6 @@ struct zfcp_adapter_mempool { | |||
132 | mempool_t *qtcb_pool; | 132 | mempool_t *qtcb_pool; |
133 | }; | 133 | }; |
134 | 134 | ||
135 | /** | ||
136 | * struct zfcp_send_ct - used to pass parameters to function zfcp_fsf_send_ct | ||
137 | * @wka_port: port where the request is sent to | ||
138 | * @req: scatter-gather list for request | ||
139 | * @resp: scatter-gather list for response | ||
140 | * @handler: handler function (called for response to the request) | ||
141 | * @handler_data: data passed to handler function | ||
142 | * @completion: completion for synchronization purposes | ||
143 | * @status: used to pass error status to calling function | ||
144 | */ | ||
145 | struct zfcp_send_ct { | ||
146 | struct zfcp_fc_wka_port *wka_port; | ||
147 | struct scatterlist *req; | ||
148 | struct scatterlist *resp; | ||
149 | void (*handler)(unsigned long); | ||
150 | unsigned long handler_data; | ||
151 | struct completion *completion; | ||
152 | int status; | ||
153 | }; | ||
154 | |||
155 | /** | ||
156 | * struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els | ||
157 | * @adapter: adapter where request is sent from | ||
158 | * @port: port where ELS is destinated (port reference count has to be increased) | ||
159 | * @d_id: destiniation id of port where request is sent to | ||
160 | * @req: scatter-gather list for request | ||
161 | * @resp: scatter-gather list for response | ||
162 | * @handler: handler function (called for response to the request) | ||
163 | * @handler_data: data passed to handler function | ||
164 | * @completion: completion for synchronization purposes | ||
165 | * @ls_code: hex code of ELS command | ||
166 | * @status: used to pass error status to calling function | ||
167 | */ | ||
168 | struct zfcp_send_els { | ||
169 | struct zfcp_adapter *adapter; | ||
170 | struct zfcp_port *port; | ||
171 | u32 d_id; | ||
172 | struct scatterlist *req; | ||
173 | struct scatterlist *resp; | ||
174 | void (*handler)(unsigned long); | ||
175 | unsigned long handler_data; | ||
176 | struct completion *completion; | ||
177 | int ls_code; | ||
178 | int status; | ||
179 | }; | ||
180 | |||
181 | struct zfcp_qdio_queue { | 135 | struct zfcp_qdio_queue { |
182 | struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q]; | 136 | struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q]; |
183 | u8 first; /* index of next free bfr in queue */ | 137 | u8 first; /* index of next free bfr in queue */ |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 6a2d6e390b68..03dec832b465 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <scsi/fc/fc_els.h> | 13 | #include <scsi/fc/fc_els.h> |
14 | #include "zfcp_def.h" | 14 | #include "zfcp_def.h" |
15 | #include "zfcp_fc.h" | ||
15 | 16 | ||
16 | /* zfcp_aux.c */ | 17 | /* zfcp_aux.c */ |
17 | extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64); | 18 | extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64); |
@@ -55,7 +56,7 @@ extern void _zfcp_dbf_hba_fsf_unsol(const char *, int level, struct zfcp_dbf *, | |||
55 | struct fsf_status_read_buffer *); | 56 | struct fsf_status_read_buffer *); |
56 | extern void zfcp_dbf_hba_qdio(struct zfcp_dbf *, unsigned int, int, int); | 57 | extern void zfcp_dbf_hba_qdio(struct zfcp_dbf *, unsigned int, int, int); |
57 | extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); | 58 | extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); |
58 | extern void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *); | 59 | extern void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *, u32); |
59 | extern void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *); | 60 | extern void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *); |
60 | extern void zfcp_dbf_san_els_request(struct zfcp_fsf_req *); | 61 | extern void zfcp_dbf_san_els_request(struct zfcp_fsf_req *); |
61 | extern void zfcp_dbf_san_els_response(struct zfcp_fsf_req *); | 62 | extern void zfcp_dbf_san_els_response(struct zfcp_fsf_req *); |
@@ -106,8 +107,7 @@ extern void zfcp_fc_link_test_work(struct work_struct *); | |||
106 | extern void zfcp_fc_wka_ports_force_offline(struct zfcp_fc_wka_ports *); | 107 | extern void zfcp_fc_wka_ports_force_offline(struct zfcp_fc_wka_ports *); |
107 | extern int zfcp_fc_gs_setup(struct zfcp_adapter *); | 108 | extern int zfcp_fc_gs_setup(struct zfcp_adapter *); |
108 | extern void zfcp_fc_gs_destroy(struct zfcp_adapter *); | 109 | extern void zfcp_fc_gs_destroy(struct zfcp_adapter *); |
109 | extern int zfcp_fc_execute_els_fc_job(struct fc_bsg_job *); | 110 | extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *); |
110 | extern int zfcp_fc_execute_ct_fc_job(struct fc_bsg_job *); | ||
111 | 111 | ||
112 | /* zfcp_fsf.c */ | 112 | /* zfcp_fsf.c */ |
113 | extern int zfcp_fsf_open_port(struct zfcp_erp_action *); | 113 | extern int zfcp_fsf_open_port(struct zfcp_erp_action *); |
@@ -128,8 +128,10 @@ extern struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *, | |||
128 | extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *); | 128 | extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *); |
129 | extern int zfcp_fsf_status_read(struct zfcp_qdio *); | 129 | extern int zfcp_fsf_status_read(struct zfcp_qdio *); |
130 | extern int zfcp_status_read_refill(struct zfcp_adapter *adapter); | 130 | extern int zfcp_status_read_refill(struct zfcp_adapter *adapter); |
131 | extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *); | 131 | extern int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *, struct zfcp_fsf_ct_els *, |
132 | extern int zfcp_fsf_send_els(struct zfcp_send_els *); | 132 | mempool_t *); |
133 | extern int zfcp_fsf_send_els(struct zfcp_adapter *, u32, | ||
134 | struct zfcp_fsf_ct_els *); | ||
133 | extern int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *, | 135 | extern int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *, |
134 | struct scsi_cmnd *); | 136 | struct scsi_cmnd *); |
135 | extern void zfcp_fsf_req_free(struct zfcp_fsf_req *); | 137 | extern void zfcp_fsf_req_free(struct zfcp_fsf_req *); |
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; |
diff --git a/drivers/s390/scsi/zfcp_fc.h b/drivers/s390/scsi/zfcp_fc.h index 9c787e043ff8..cb2a3669a384 100644 --- a/drivers/s390/scsi/zfcp_fc.h +++ b/drivers/s390/scsi/zfcp_fc.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <scsi/fc/fc_ns.h> | 15 | #include <scsi/fc/fc_ns.h> |
16 | #include <scsi/scsi_cmnd.h> | 16 | #include <scsi/scsi_cmnd.h> |
17 | #include <scsi/scsi_tcq.h> | 17 | #include <scsi/scsi_tcq.h> |
18 | #include "zfcp_fsf.h" | ||
18 | 19 | ||
19 | #define ZFCP_FC_CT_SIZE_PAGE (PAGE_SIZE - sizeof(struct fc_ct_hdr)) | 20 | #define ZFCP_FC_CT_SIZE_PAGE (PAGE_SIZE - sizeof(struct fc_ct_hdr)) |
20 | #define ZFCP_FC_GPN_FT_ENT_PAGE (ZFCP_FC_CT_SIZE_PAGE \ | 21 | #define ZFCP_FC_GPN_FT_ENT_PAGE (ZFCP_FC_CT_SIZE_PAGE \ |
@@ -55,7 +56,7 @@ struct zfcp_fc_gid_pn_resp { | |||
55 | * @gid_pn_resp: GID_PN response data | 56 | * @gid_pn_resp: GID_PN response data |
56 | */ | 57 | */ |
57 | struct zfcp_fc_gid_pn { | 58 | struct zfcp_fc_gid_pn { |
58 | struct zfcp_send_ct ct; | 59 | struct zfcp_fsf_ct_els ct; |
59 | struct scatterlist sg_req; | 60 | struct scatterlist sg_req; |
60 | struct scatterlist sg_resp; | 61 | struct scatterlist sg_resp; |
61 | struct zfcp_fc_gid_pn_req gid_pn_req; | 62 | struct zfcp_fc_gid_pn_req gid_pn_req; |
@@ -90,7 +91,7 @@ struct zfcp_fc_gpn_ft_resp { | |||
90 | * @sg_resp: scatter list entries for gpn_ft responses (per memory page) | 91 | * @sg_resp: scatter list entries for gpn_ft responses (per memory page) |
91 | */ | 92 | */ |
92 | struct zfcp_fc_gpn_ft { | 93 | struct zfcp_fc_gpn_ft { |
93 | struct zfcp_send_ct ct; | 94 | struct zfcp_fsf_ct_els ct; |
94 | struct scatterlist sg_req; | 95 | struct scatterlist sg_req; |
95 | struct scatterlist sg_resp[ZFCP_FC_GPN_FT_NUM_BUFS]; | 96 | struct scatterlist sg_resp[ZFCP_FC_GPN_FT_NUM_BUFS]; |
96 | }; | 97 | }; |
@@ -104,7 +105,7 @@ struct zfcp_fc_gpn_ft { | |||
104 | * @adisc_resp: ELS ADISC response data | 105 | * @adisc_resp: ELS ADISC response data |
105 | */ | 106 | */ |
106 | struct zfcp_fc_els_adisc { | 107 | struct zfcp_fc_els_adisc { |
107 | struct zfcp_send_els els; | 108 | struct zfcp_fsf_ct_els els; |
108 | struct scatterlist req; | 109 | struct scatterlist req; |
109 | struct scatterlist resp; | 110 | struct scatterlist resp; |
110 | struct fc_els_adisc adisc_req; | 111 | struct fc_els_adisc adisc_req; |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 057c93777f92..fb580b14a68e 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -961,10 +961,10 @@ out: | |||
961 | static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) | 961 | static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) |
962 | { | 962 | { |
963 | struct zfcp_adapter *adapter = req->adapter; | 963 | struct zfcp_adapter *adapter = req->adapter; |
964 | struct zfcp_send_ct *send_ct = req->data; | 964 | struct zfcp_fsf_ct_els *ct = req->data; |
965 | struct fsf_qtcb_header *header = &req->qtcb->header; | 965 | struct fsf_qtcb_header *header = &req->qtcb->header; |
966 | 966 | ||
967 | send_ct->status = -EINVAL; | 967 | ct->status = -EINVAL; |
968 | 968 | ||
969 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) | 969 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) |
970 | goto skip_fsfstatus; | 970 | goto skip_fsfstatus; |
@@ -972,7 +972,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) | |||
972 | switch (header->fsf_status) { | 972 | switch (header->fsf_status) { |
973 | case FSF_GOOD: | 973 | case FSF_GOOD: |
974 | zfcp_dbf_san_ct_response(req); | 974 | zfcp_dbf_san_ct_response(req); |
975 | send_ct->status = 0; | 975 | ct->status = 0; |
976 | break; | 976 | break; |
977 | case FSF_SERVICE_CLASS_NOT_SUPPORTED: | 977 | case FSF_SERVICE_CLASS_NOT_SUPPORTED: |
978 | zfcp_fsf_class_not_supp(req); | 978 | zfcp_fsf_class_not_supp(req); |
@@ -1004,8 +1004,8 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) | |||
1004 | } | 1004 | } |
1005 | 1005 | ||
1006 | skip_fsfstatus: | 1006 | skip_fsfstatus: |
1007 | if (send_ct->handler) | 1007 | if (ct->handler) |
1008 | send_ct->handler(send_ct->handler_data); | 1008 | ct->handler(ct->handler_data); |
1009 | } | 1009 | } |
1010 | 1010 | ||
1011 | static void zfcp_fsf_setup_ct_els_unchained(struct qdio_buffer_element *sbale, | 1011 | static void zfcp_fsf_setup_ct_els_unchained(struct qdio_buffer_element *sbale, |
@@ -1094,9 +1094,9 @@ static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req, | |||
1094 | * @ct: pointer to struct zfcp_send_ct with data for request | 1094 | * @ct: pointer to struct zfcp_send_ct with data for request |
1095 | * @pool: if non-null this mempool is used to allocate struct zfcp_fsf_req | 1095 | * @pool: if non-null this mempool is used to allocate struct zfcp_fsf_req |
1096 | */ | 1096 | */ |
1097 | int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool) | 1097 | int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port, |
1098 | struct zfcp_fsf_ct_els *ct, mempool_t *pool) | ||
1098 | { | 1099 | { |
1099 | struct zfcp_fc_wka_port *wka_port = ct->wka_port; | ||
1100 | struct zfcp_qdio *qdio = wka_port->adapter->qdio; | 1100 | struct zfcp_qdio *qdio = wka_port->adapter->qdio; |
1101 | struct zfcp_fsf_req *req; | 1101 | struct zfcp_fsf_req *req; |
1102 | int ret = -EIO; | 1102 | int ret = -EIO; |
@@ -1122,7 +1122,7 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool) | |||
1122 | req->qtcb->header.port_handle = wka_port->handle; | 1122 | req->qtcb->header.port_handle = wka_port->handle; |
1123 | req->data = ct; | 1123 | req->data = ct; |
1124 | 1124 | ||
1125 | zfcp_dbf_san_ct_request(req); | 1125 | zfcp_dbf_san_ct_request(req, wka_port->d_id); |
1126 | 1126 | ||
1127 | ret = zfcp_fsf_req_send(req); | 1127 | ret = zfcp_fsf_req_send(req); |
1128 | if (ret) | 1128 | if (ret) |
@@ -1139,7 +1139,7 @@ out: | |||
1139 | 1139 | ||
1140 | static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req) | 1140 | static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req) |
1141 | { | 1141 | { |
1142 | struct zfcp_send_els *send_els = req->data; | 1142 | struct zfcp_fsf_ct_els *send_els = req->data; |
1143 | struct zfcp_port *port = send_els->port; | 1143 | struct zfcp_port *port = send_els->port; |
1144 | struct fsf_qtcb_header *header = &req->qtcb->header; | 1144 | struct fsf_qtcb_header *header = &req->qtcb->header; |
1145 | 1145 | ||
@@ -1159,9 +1159,6 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req) | |||
1159 | case FSF_ADAPTER_STATUS_AVAILABLE: | 1159 | case FSF_ADAPTER_STATUS_AVAILABLE: |
1160 | switch (header->fsf_status_qual.word[0]){ | 1160 | switch (header->fsf_status_qual.word[0]){ |
1161 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: | 1161 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: |
1162 | if (port && (send_els->ls_code != ELS_ADISC)) | ||
1163 | zfcp_fc_test_link(port); | ||
1164 | /*fall through */ | ||
1165 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: | 1162 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: |
1166 | case FSF_SQ_RETRY_IF_POSSIBLE: | 1163 | case FSF_SQ_RETRY_IF_POSSIBLE: |
1167 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1164 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
@@ -1193,10 +1190,11 @@ skip_fsfstatus: | |||
1193 | * zfcp_fsf_send_els - initiate an ELS command (FC-FS) | 1190 | * zfcp_fsf_send_els - initiate an ELS command (FC-FS) |
1194 | * @els: pointer to struct zfcp_send_els with data for the command | 1191 | * @els: pointer to struct zfcp_send_els with data for the command |
1195 | */ | 1192 | */ |
1196 | int zfcp_fsf_send_els(struct zfcp_send_els *els) | 1193 | int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id, |
1194 | struct zfcp_fsf_ct_els *els) | ||
1197 | { | 1195 | { |
1198 | struct zfcp_fsf_req *req; | 1196 | struct zfcp_fsf_req *req; |
1199 | struct zfcp_qdio *qdio = els->adapter->qdio; | 1197 | struct zfcp_qdio *qdio = adapter->qdio; |
1200 | int ret = -EIO; | 1198 | int ret = -EIO; |
1201 | 1199 | ||
1202 | spin_lock_bh(&qdio->req_q_lock); | 1200 | spin_lock_bh(&qdio->req_q_lock); |
@@ -1216,7 +1214,7 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els) | |||
1216 | if (ret) | 1214 | if (ret) |
1217 | goto failed_send; | 1215 | goto failed_send; |
1218 | 1216 | ||
1219 | hton24(req->qtcb->bottom.support.d_id, els->d_id); | 1217 | hton24(req->qtcb->bottom.support.d_id, d_id); |
1220 | req->handler = zfcp_fsf_send_els_handler; | 1218 | req->handler = zfcp_fsf_send_els_handler; |
1221 | req->data = els; | 1219 | req->data = els; |
1222 | 1220 | ||
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 206b7eaff5a0..b3de682b64cf 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h | |||
@@ -437,4 +437,22 @@ struct zfcp_blk_drv_data { | |||
437 | u64 fabric_lat; | 437 | u64 fabric_lat; |
438 | } __attribute__ ((packed)); | 438 | } __attribute__ ((packed)); |
439 | 439 | ||
440 | /** | ||
441 | * struct zfcp_fsf_ct_els - zfcp data for ct or els request | ||
442 | * @req: scatter-gather list for request | ||
443 | * @resp: scatter-gather list for response | ||
444 | * @handler: handler function (called for response to the request) | ||
445 | * @handler_data: data passed to handler function | ||
446 | * @port: Optional pointer to port for zfcp internal ELS (only test link ADISC) | ||
447 | * @status: used to pass error status to calling function | ||
448 | */ | ||
449 | struct zfcp_fsf_ct_els { | ||
450 | struct scatterlist *req; | ||
451 | struct scatterlist *resp; | ||
452 | void (*handler)(void *); | ||
453 | void *handler_data; | ||
454 | struct zfcp_port *port; | ||
455 | int status; | ||
456 | }; | ||
457 | |||
440 | #endif /* FSF_H */ | 458 | #endif /* FSF_H */ |
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 3d168410036b..535f36cf2819 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <asm/atomic.h> | 14 | #include <asm/atomic.h> |
15 | #include "zfcp_ext.h" | 15 | #include "zfcp_ext.h" |
16 | #include "zfcp_dbf.h" | 16 | #include "zfcp_dbf.h" |
17 | #include "zfcp_fc.h" | ||
17 | 18 | ||
18 | static unsigned int default_depth = 32; | 19 | static unsigned int default_depth = 32; |
19 | module_param_named(queue_depth, default_depth, uint, 0600); | 20 | module_param_named(queue_depth, default_depth, uint, 0600); |
@@ -628,20 +629,6 @@ void zfcp_scsi_scan(struct work_struct *work) | |||
628 | put_device(&unit->sysfs_device); | 629 | put_device(&unit->sysfs_device); |
629 | } | 630 | } |
630 | 631 | ||
631 | static int zfcp_execute_fc_job(struct fc_bsg_job *job) | ||
632 | { | ||
633 | switch (job->request->msgcode) { | ||
634 | case FC_BSG_RPT_ELS: | ||
635 | case FC_BSG_HST_ELS_NOLOGIN: | ||
636 | return zfcp_fc_execute_els_fc_job(job); | ||
637 | case FC_BSG_RPT_CT: | ||
638 | case FC_BSG_HST_CT: | ||
639 | return zfcp_fc_execute_ct_fc_job(job); | ||
640 | default: | ||
641 | return -EINVAL; | ||
642 | } | ||
643 | } | ||
644 | |||
645 | struct fc_function_template zfcp_transport_functions = { | 632 | struct fc_function_template zfcp_transport_functions = { |
646 | .show_starget_port_id = 1, | 633 | .show_starget_port_id = 1, |
647 | .show_starget_port_name = 1, | 634 | .show_starget_port_name = 1, |
@@ -662,13 +649,14 @@ struct fc_function_template zfcp_transport_functions = { | |||
662 | .get_host_port_state = zfcp_get_host_port_state, | 649 | .get_host_port_state = zfcp_get_host_port_state, |
663 | .terminate_rport_io = zfcp_scsi_terminate_rport_io, | 650 | .terminate_rport_io = zfcp_scsi_terminate_rport_io, |
664 | .show_host_port_state = 1, | 651 | .show_host_port_state = 1, |
665 | .bsg_request = zfcp_execute_fc_job, | 652 | .bsg_request = zfcp_fc_exec_bsg_job, |
666 | /* no functions registered for following dynamic attributes but | 653 | /* no functions registered for following dynamic attributes but |
667 | directly set by LLDD */ | 654 | directly set by LLDD */ |
668 | .show_host_port_type = 1, | 655 | .show_host_port_type = 1, |
669 | .show_host_speed = 1, | 656 | .show_host_speed = 1, |
670 | .show_host_port_id = 1, | 657 | .show_host_port_id = 1, |
671 | .disable_target_scan = 1, | 658 | .disable_target_scan = 1, |
659 | .dd_bsg_size = sizeof(struct zfcp_fsf_ct_els), | ||
672 | }; | 660 | }; |
673 | 661 | ||
674 | struct zfcp_data zfcp_data = { | 662 | struct zfcp_data zfcp_data = { |